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

REF/ENH: better CLI handling of non-TwinCAT files #37

Closed klauer closed 2 years ago

klauer commented 2 years ago

Goal

Aside

I think there's a lot of work that remains for the CLI interface to blark - it's awkard in many ways. I'm very open to suggestions here.

The code summary and weird/ugly YAML-ish looking output are pretty much only a stopgap until I get time to figure out the apischema-related issue for JSON serialization (as in #28).

@engineerjoe440 - I'm curious as to how you might want to interact with such a CLI tool - or if the Python API will remain your interface to blark. And if anything seems off in the diff here, feel free to chime in πŸ˜ƒ

Output

blark parse -s blark/tests/source/commas_in_case.st ``` $ python -m blark parse -s blark/tests/source/commas_in_case.st Functions --------- fun_CommainCase =============== comments: - (**) name: fun_CommainCase item: name: fun_CommainCase return_type: type: type: BOOL declarations: - items: - variables: - variable: name: character dereferenced: False init: spec: type: BYTE body: statements: - expression: name: character dereferenced: False cases: - matches: - start: type_name: BYTE value: 9 stop: type_name: BYTE value: 10 - type_name: BYTE value: 13 - start: type_name: BYTE value: 28 stop: type_name: BYTE value: 126 statements: statements: - variables: - name: fun_CommainCase dereferenced: False expression: name: TRUE dereferenced: False else_clause: statements: statements: - variables: - name: fun_CommainCase dereferenced: False expression: name: FALSE dereferenced: False return_type: BOOL source_code: FUNCTION fun_CommainCase : BOOL VAR_INPUT (* Byte to be evaluated as a printable character. *) character : BYTE; END_VAR CASE character OF (* Any character that falls in the ascii range (in base-10) 0-8, 11, 12, 14-27 or >=127 is an invalid character. *) BYTE#9..BYTE#10, BYTE#13, BYTE#28..BYTE#126: fun_CommainCase := TRUE; ELSE fun_CommainCase := FALSE; END_CASE END_FUNCTION declarations: - character: comments: - (* Byte to be evaluated as a printable character. *) name: character item: variables: - variable: name: character dereferenced: False init: spec: type: BYTE parent: fun_CommainCase block: VAR_INPUT base_type: BYTE type: BYTE value: None ```
blark parse -vvv blark/tests/source/commas_in_case.st ``` $ blark parse -vvv blark/tests/source/commas_in_case.st Successfully parsed blark/tests/source/commas_in_case.st: ------------------------------- (**) FUNCTION fun_CommainCase : BOOL VAR_INPUT (* Byte to be evaluated as a printable character. *) character : BYTE; END_VAR CASE character OF (* Any character that falls in the ascii range (in base-10) 0-8, 11, 12, 14-27 or >=127 is an invalid character. *) BYTE#9..BYTE#10, BYTE#13, BYTE#28..BYTE#126: fun_CommainCase := TRUE; ELSE fun_CommainCase := FALSE; END_CASE END_FUNCTION ------------------------------- iec_source function_declaration None fun_CommainCase indirect_simple_specification None simple_specification BOOL input_declarations None var1_init_decl var1_list var1 variable_name character None None simple_spec_init None simple_specification BYTE None statement_list case_statement expression assignment_expression or_else_expression and_then_expression xor_expression and_expression comparison_expression equality_expression add_expression expression_term power_expression unary_expression None variable_name character None case_elements case_element case_list subrange expression assignment_expression or_else_expression and_then_expression xor_expression and_expression comparison_expression equality_expression add_expression expression_term power_expression unary_expression None constant bit_string_literal BYTE 9 expression assignment_expression or_else_expression and_then_expression xor_expression and_expression comparison_expression equality_expression add_expression expression_term power_expression unary_expression None constant bit_string_literal BYTE 10 bit_string_literal BYTE 13 subrange expression assignment_expression or_else_expression and_then_expression xor_expression and_expression comparison_expression equality_expression add_expression expression_term power_expression unary_expression None constant bit_string_literal BYTE 28 expression assignment_expression or_else_expression and_then_expression xor_expression and_expression comparison_expression equality_expression add_expression expression_term power_expression unary_expression None constant bit_string_literal BYTE 126 statement_list assignment_statement variable_name fun_CommainCase None expression assignment_expression or_else_expression and_then_expression xor_expression and_expression comparison_expression equality_expression add_expression expression_term power_expression unary_expression None variable_name TRUE None else_clause statement_list assignment_statement variable_name fun_CommainCase None expression assignment_expression or_else_expression and_then_expression xor_expression and_expression comparison_expression equality_expression add_expression expression_term power_expression unary_expression None variable_name FALSE None ------------------------------- [Success] End of blark/tests/source/commas_in_case.st * Loading blark/tests/source/commas_in_case.st ```
blark parse -i blark/tests/source/commas_in_case.st ``` $ python -m blark parse -i blark/tests/source/commas_in_case.st -- blark debug -- Parsed single file successfully: blark/tests/source/commas_in_case.st. Access its transformed value in the variable ``result``. -- blark debug -- Python 3.9.10 | packaged by conda-forge | (main, Feb 1 2022, 21:27:48) Type 'copyright', 'credits' or 'license' for more information IPython 8.0.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: result.items[0].name Out[1]: Token('IDENTIFIER', 'fun_CommainCase') ```
engineerjoe440 commented 2 years ago

I'm afraid I don't have any real constructive criticism or thoughts here.

I think that for now, at least, I'm going to continue with using the Python API, just because I'm wrapping this into a package to support some static analysis functions, and the AST generation has saved me a TON of time. I'd started creating my own 61131 "language" files with Lark, and had made a fair bit of progress, but this has sped that whole process up tenfold!

So... all that to say, I'm not really making use of the CLI at this point in time. Not to say that I couldn't in the future, but for now, I'm using this to build trees that the tooling I'm building can walk for additional analysis. πŸ˜„

Thank you for including me in your feedback gathering, and all of your openness towards contributions!

klauer commented 2 years ago

Fair enough - thanks for the additional context πŸ‘