klauer / blark

Beckhoff TwinCAT ST (IEC 61131-3) code parsing in Python using Lark (Earley)
https://klauer.github.io/blark/
GNU General Public License v2.0
42 stars 5 forks source link

Array Initialization with Zero #60

Closed engineerjoe440 closed 1 year ago

engineerjoe440 commented 1 year ago

This is an interesting syntax I haven't seen, before.

image

This screenshot was taken in a CODESYS environment, and I can't find specific documentation for Beckhoff systems that allow this as legal syntax (but I can't find it as illegal syntax, either, for that matter). I think this should be confirmed as legal (or proven as illegal) syntax for Beckhoff systems, and then perhaps we can proceed from there.

engineerjoe440 commented 1 year ago

Wouldn't ya know it... This is self-inflicted! 🤦 Hah! I'm looking at some mechanisms to resolve it by reverting a little bit of my changes surrounding the changes I made here: https://github.com/klauer/blark/blob/master/blark/iec.lark#L338-L339. 😅

klauer commented 1 year ago

Hah, funny how that works out sometimes.

Great that you got to the bottom of it so quickly - and looks like there's a bit more work to do 😁

engineerjoe440 commented 1 year ago

Definitely glad that it popped out sooner rather than later! 😀 It'll take me a bit of poking around to figure out exactly what I'm overlooking in the transformer that's causing the grief. Reverting my silliness, everything parses correctly, but there does seem to be some issue with the the transformer having trouble with the InputParameterAssignments:

E       AssertionError: Transformed object does not produce identical source code
E       assert 'VAR_IN_OUT\n... 3);\nEND_VAR' == 'VAR_IN_OUT\n... 3);\nEND_VAR'
E         Skipping 258 identical leading characters in diff, use -v to show
E         -  := (A := 1, B := 2, C := 3);
E         +  := (A := [1, B := 2], C := 3);
E         ?           +         +
E               fbTest : FB_Test := (1, 2, 3);
E           END_VAR

blark\tests\test_transformer.py:31: AssertionError
------------------------------------------------------------------------------------------------------- Captured stdout call ------------------------------------------------------------------------------------------------------- 

Transformed:
InputOutputDeclarations(attrs=None, items=[VariableOneInitDeclaration(variables=[DeclaredVariable(variable=SimpleVariable(name=Token('IDENTIFIER', 'iValue'), dereferenced=False), location=None)], init=TypeInitialization(indirection=None, spec=SimpleSpecification(type=Token('DOTTED_IDENTIFIER', 'INT')), value=None)), StringVariableInitDeclaration(variables=[DeclaredVariable(variable=SimpleVariable(name=Token('IDENTIFIER', 'sValue'), dereferenced=False), location=None)], spec=StringTypeSpecification(type_name=Token('STRING', 'STRING'), length=None), value=Token('SINGLE_BYTE_CHARACTER_STRING', "'abc'"), init=_GenericInit(base_type_name='STRING', full_type_name='STRING', repr="STRING := 'abc'", value="'abc'")), StringVariableInitDeclaration(variables=[DeclaredVariable(variable=SimpleVariable(name=Token('IDENTIFIER', 'wsValue'), dereferenced=False), location=None)], spec=StringTypeSpecification(type_name=Token('WSTRING', 'WSTRING'), length=None), value=Token('DOUBLE_BYTE_CHARACTER_STRING', '"abc"'), init=_GenericInit(base_type_name='WSTRING', full_type_name='WSTRING', repr='WSTRING := "abc"', value='"abc"')), FunctionBlockInvocationDeclaration(variables=[Token('IDENTIFIER', 'fbTest')], init=FunctionCall(name=SimpleVariable(name=Token('IDENTIFIER', 'FB_Test'), dereferenced=False), parameters=[InputParameterAssignment(name=None, value=Integer(value=Token('INTEGER', '1'), type_name=None)), InputParameterAssignment(name=None, value=Integer(value=Token('INTEGER', '2'), type_name=None)), InputParameterAssignment(name=None, value=Integer(value=Token('INTEGER', '3'), type_name=None))], dereferenced=False), defaults=None), FunctionBlockInvocationDeclaration(variables=[Token('IDENTIFIER', 'fbTest')], init=FunctionCall(name=SimpleVariable(name=Token('IDENTIFIER', 'FB_Test'), dereferenced=False), parameters=[InputParameterAssignment(name=SimpleVariable(name=Token('IDENTIFIER', 'A'), dereferenced=False), value=Integer(value=Token('INTEGER', '1'), type_name=None)), InputParameterAssignment(name=SimpleVariable(name=Token('IDENTIFIER', 'B'), dereferenced=False), value=Integer(value=Token('INTEGER', '2'), type_name=None)), OutputParameterAssignment(name=SimpleVariable(name=Token('IDENTIFIER', 'C'), dereferenced=False), value=Integer(value=Token('INTEGER', '3'), type_name=None), inverted=False)], dereferenced=False), defaults=None), FunctionBlockInvocationDeclaration(variables=[Token('IDENTIFIER', 'fbTest')], init=FunctionCall(name=SimpleVariable(name=Token('IDENTIFIER', 'FB_Test'), dereferenced=False), parameters=[InputParameterAssignment(name=None, value=Integer(value=Token('INTEGER', '1'), type_name=None)), InputParameterAssignment(name=None, value=Integer(value=Token('INTEGER', '2'), type_name=None)), InputParameterAssignment(name=SimpleVariable(name=Token('IDENTIFIER', 'A'), dereferenced=False), value=Integer(value=Token('INTEGER', '1'), type_name=None)), InputParameterAssignment(name=SimpleVariable(name=Token('IDENTIFIER', 'B'), dereferenced=False), value=Integer(value=Token('INTEGER', '2'), type_name=None)), OutputParameterAssignment(name=SimpleVariable(name=Token('IDENTIFIER', 'C'), dereferenced=False), value=Integer(value=Token('INTEGER', '3'), type_name=None),     wsValue : WSTRING := "abc";    fbTest : FB_Test(1, 2, 3);    fbTest : FB_Test(A := 1, B := 2, C => 3);    fbTest : FB_Test(1, 2, A := 1, B := 2, C => 3);    fbTest : FB_Test(initializer := 5) := (A := [1, B := 2], C := 3);    fbTest : FB_Test := (1, 2, 3);END_VAR
===================================================================================================== short test summary info ====================================================================================================== 
FAILED blark/tests/test_transformer.py::test_input_roundtrip[input_declarations-VAR_INPUT RETAIN\n    fbTest : FB_Test := (A := 1, B := 2, C := 3);\nEND_VAR] - AssertionError: Transformed object does not produce identical source code
FAILED blark/tests/test_transformer.py::test_input_output_roundtrip[input_output_declarations-VAR_IN_OUT\n    iValue : INT;\n    sValue : STRING := 'abc';\n    wsValue : WSTRING := "abc";\n    fbTest : FB_Test(1, 2, 3);\n    fbTest : FB_Test(A := 1, B := 2, C => 3);\n    fbTest : FB_Test(1, 2, A := 1, B := 2, C => 3);\n    fbTest : FB_Test(initializer := 5) := (A := 1, B := 2, C := 3);\n    fbTest : FB_Test := (1, 2, 3);\nEND_VAR] - AssertionError: Transformed object does not produce identical source code

We'll get there, though!!!