-
Notifications
You must be signed in to change notification settings - Fork 7
Some fixes #111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Some fixes #111
Changes from all commits
cbe013f
35f62cb
9b63097
d7528b1
415739d
2e9509c
dd412de
01d0611
5f4e831
a7317ea
822fa0d
f848d9e
a776102
1a73683
1e11cc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -33,7 +33,9 @@ _library_element_declaration: data_type_declaration | |||||||||||||
| | ";" | ||||||||||||||
|
|
||||||||||||||
| // B.1.1 | ||||||||||||||
| IDENTIFIER: /[A-Za-z_][A-Za-z0-9_]*/i | ||||||||||||||
| // Identifiers need to ignore certain keywords, but NOT typenames, as those may be used | ||||||||||||||
| // 'as values' with SIZEOF for example | ||||||||||||||
| IDENTIFIER: /\b(?!(ABSTRACT|ACTION|AND|AND_THEN|AT|BY|CASE|CONTINUE|DO|ELSE|ELSIF|END_ACTION|END_CASE|END_FOR|END_FUNCTION|END_FUNCTIONBLOCK|END_FUNCTION_BLOCK|END_IF|END_INTERFACE|END_METHOD|END_PROGRAM|END_PROPERTY|END_REPEAT|END_STRUCT|END_TYPE|END_UNION|END_VAR|END_WHILE|EXIT|EXTENDS|FINAL|FOR|FUNCTION|FUNCTIONBLOCK|FUNCTION_BLOCK|IF|IMPLEMENTS|INTERFACE|INTERNAL|JMP|METHOD|MOD|NOT|OF|OR|OR_ELSE|PERSISTENT|PRIVATE|PROGRAM|PROPERTY|PROTECTED|PUBLIC|READ_ONLY|READ_WRITE|REFERENCE|REPEAT|RETURN|STRUCT|THEN|TO|TYPE|UNION|UNTIL|VAR|VAR_ACCESS|VAR_EXTERNAL|VAR_GLOBAL|VAR_INPUT|VAR_INST|VAR_IN_OUT|VAR_OUTPUT|VAR_STAT|VAR_TEMP|WHILE|XOR)\b)[A-Za-z_][A-Za-z0-9_]*\b/i | ||||||||||||||
|
|
||||||||||||||
| // B.1.2 | ||||||||||||||
| constant: time_literal | ||||||||||||||
|
|
@@ -346,7 +348,7 @@ _array_initial_element: expression | |||||||||||||
| | enumerated_value | ||||||||||||||
| | array_initialization | ||||||||||||||
|
|
||||||||||||||
| structure_type_declaration: structure_type_name_declaration [ extends ] ":" [ indirection_type ] _STRUCT ( structure_element_declaration ";"+ )* _END_STRUCT | ||||||||||||||
| structure_type_declaration: structure_type_name_declaration [ extends ] ":" [ indirection_type ] _STRUCT ";"* ( structure_element_declaration ";"+ )* _END_STRUCT | ||||||||||||||
|
|
||||||||||||||
| initialized_structure: structure_type_name ":=" structure_initialization | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -446,7 +448,7 @@ fb_decl: fb_decl_name_list ":" function_block_type_name [ ":=" structure_initial | |||||||||||||
|
|
||||||||||||||
| fb_decl_name_list: fb_name ( "," fb_name )* | ||||||||||||||
|
|
||||||||||||||
| var_body: ( var_init_decl ";"+ )* | ||||||||||||||
| var_body: ";"* ( var_init_decl ";"+ )* | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For this, then, the following would be valid? We'll need to add a simple test like that to the suite for future-proofing.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you mind doing a similar thing as in the above comment, disabling this and finding your real-world source code example of where the current grammar didn't suffice?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, what you sent should be valid, it is accepted by TwinCAT but not by the old version of the grammar. |
||||||||||||||
|
|
||||||||||||||
| array_var_declaration: var1_list ":" array_specification | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -570,7 +572,7 @@ ACCESS_SPECIFIER: _ABSTRACT | |||||||||||||
| | _INTERNAL | ||||||||||||||
| | _FINAL | ||||||||||||||
| access_specifier: ACCESS_SPECIFIER+ | ||||||||||||||
| extends: _EXTENDS DOTTED_IDENTIFIER | ||||||||||||||
| extends: _EXTENDS DOTTED_IDENTIFIER ("," DOTTED_IDENTIFIER)* | ||||||||||||||
| implements: _IMPLEMENTS DOTTED_IDENTIFIER ("," DOTTED_IDENTIFIER)* | ||||||||||||||
|
|
||||||||||||||
| function_block_type_declaration: FUNCTION_BLOCK [ access_specifier ] derived_function_block_name [ extends ] [ implements ] fb_var_declaration* [ function_block_body ] END_FUNCTION_BLOCK ";"* | ||||||||||||||
|
|
@@ -586,6 +588,7 @@ END_FUNCTION_BLOCK: _END_FUNCTION_BLOCK | |||||||||||||
| | input_output_declarations | ||||||||||||||
| | external_var_declarations | ||||||||||||||
| | var_declarations | ||||||||||||||
| | var_inst_declaration | ||||||||||||||
| | temp_var_decls | ||||||||||||||
| | static_var_declarations | ||||||||||||||
| | incomplete_located_var_declarations | ||||||||||||||
|
|
@@ -608,7 +611,7 @@ function_block_method_declaration: _METHOD [ access_specifier ] DOTTED_IDENTIFIE | |||||||||||||
|
|
||||||||||||||
| ?property_return_type: _located_var_spec_init | ||||||||||||||
|
|
||||||||||||||
| function_block_property_declaration: _PROPERTY [ access_specifier ] DOTTED_IDENTIFIER [ ":" property_return_type ] ";"* property_var_declaration* [ function_block_body ] _END_PROPERTY ";"* | ||||||||||||||
| function_block_property_declaration: _PROPERTY [ access_specifier ] DOTTED_IDENTIFIER [ ":" property_return_type ] ";"* [ access_specifier ] property_var_declaration* [ function_block_body ] _END_PROPERTY ";"* | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We'll need to add a test case for it along the lines of this: blark/blark/tests/test_transformer.py Lines 1039 to 1044 in 1c80127
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll be honest to say that I am no PLC engineer myself strictly, it is just something that is in our codebase (which compiles, so it should be valid). Sometimes with things like this it kind of seems like TwinCAT is just very lenient with it or something? Makes me wonder, but yeah it should be valid as it builds for us, a test like that would be good. I just messed around a bit to undo this change and check where it went wrong, the source code for the failing propery is this: (i.e. the 'new' situation is with an access specifier after the type. I think perhaps I should have put it before the semicolons though...
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand - and can relate. "Compiles and is valid in TwinCAT" is exactly what blark aims to parse, so this is a good change. I'll add your example as a test case, unless you wouldn't mind adding it here in this PR.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like this behavior may be intended: the second access specifier is that of the setter or getter specifically. So the first access specifier (in the property) is the "default" access specifier for the getter and the setter. If the first access specifier is PRIVATE and the second is PUBLIC, then the resulting access specifier is PUBLIC. This can actually be done for the getter and the setter separately, and will raise no exception. |
||||||||||||||
|
|
||||||||||||||
| // B.1.5.3 | ||||||||||||||
| ?program_type_name: IDENTIFIER | ||||||||||||||
|
|
@@ -646,7 +649,7 @@ program_access_decl: access_name ":" symbolic_variable ":" non_generic_type_name | |||||||||||||
| | external_var_declarations | ||||||||||||||
| | var_declarations | ||||||||||||||
|
|
||||||||||||||
| interface_declaration: _INTERFACE IDENTIFIER [ extends ] interface_var_declaration* _END_INTERFACE ";"* | ||||||||||||||
| interface_declaration: _INTERFACE IDENTIFIER [ extends ] interface_var_declaration* _END_INTERFACE? ";"* | ||||||||||||||
|
|
||||||||||||||
| // B.2.1, B.3.1 | ||||||||||||||
| LOGICAL_OR: _OR | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made a note in #108 - I think there may be some overlap here. Should this perhaps also include
TRUE/FALSE?I'm sure there's some overhead for treating identifiers like this, but this may be the best way we have with lark.
It's possible adjusting priorities of those reserved words (as suggested in #108) could help address this in a different way, though it would certainly touch many more lines.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, type names and TRUE / FALSE should not be excluded, as they are in fact identifiers (and parsed as such in type declarations / expressions). The reason I added this is because (in combination with the access_specifier change for properties I believe) it would parse properties with PRIVATE, PROTECTED or PUBLIC as the name, which is of course wrong. Including all keywords made it so declarations were not parsed properly anymore, and neither were expressions like
SIZEOF(UINT)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do believe that TRUE and FALSE should be included here. With the current code from this PR, blark accepts this as a valid input:
Given the same snippet, TwinCAT complains "Unexpected Token 'TRUE' found", which is more in line with what I expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it did not accept that as valid input before? I think I only made the IDENTIFIER parsing more strict...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also: if TRUE / FALSE are excluded from identifiers, SIZEOF(TRUE) will not be parsed by blark (I have not tried this but I assume this will happen). Basically, anything that can be used as an argument to SIZEOF should be parsed as an identifier, or SIZEOF should be handled separately in the grammar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DenSinH No no, it did accept this as valid input before, sorry for being unclear. I'm just making an argument in favor of including TRUE and FALSE in the exclusion list for IDENTIFIER while you're at it.
If I add TRUE and FALSE to the exclusion list, then my example from above is rejected as invalid. However,
SIZEOF(TRUE)still parses fine because the argument toSIZEOFis an expression, andTRUEorFALSEare valid expressions. So I don't see a problem with that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are correct in suggesting that
SIZEOFshould be handled separately in the grammar, though. It currently seems to be handled in a generic way – that is, the same as any other function call. Which means that ifSIZEOF(BOOL)is currently accepted as valid code, the same would likely go for nonsense likeINT_TO_UINT(BOOL). But if that's the case, it should probably be handled in a separate issue.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, whether this kind of stuff should happen in a parser is up for debate though, at least to what extent. I guess to do it completely correctly, there would have to be a
type_namerule, which parses (you guessed it) built-in type names, or an identifier. Then SIZEOF(...) would only accept type names. That is, currently declarations are parsed as:this
DOTTED_IDENTIFIERwould have to betype_name, which in turn also acceptsDOTTED_IDENTIFIERand so on.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good discussion. I think some more thought will be needed to get to a proper solution - a bit more than I have the time for at the moment.
In the meantime, would you mind submitting your priority-boosting PR @alajovic?