Package: blark
Beckhoff TwinCAT IEC 61131-3 Lark-based Structured Text ToolsOr for short, blark.  B(eckhoff)-lark. It sounded good in my head, at least.The GrammarThegrammaruses Lark's Earley parser algorithm.The grammar itself is not perfect.  It may not reliably parse your source code
or produce useful Python instances just yet.Seeissuesfor further details.As a fun side project, blark isn't at the top of my priority list.  For
an idea of where the project is going, see the issues list.Requirementslark(for grammar-based parsing)lxml(for parsing TwinCAT projects)CapabilitiesTwinCAT source code file parsing (*.TcPOUand others)TwinCAT project and solution loadinglark.Treegeneration of any supported source codePython dataclasses of supported source code, with introspection and code refactoringWorks-in-progressSphinx API documentation generation (a new Sphinx domain)Code reformatting"Dependency store" - recursively parse and inspect project dependenciesSummary generation - a layer on top of dataclasses to summarize source code detailsRewriting source code directly in TwinCAT source code filesInstallationInstallation is quick with Pip.pipinstall--upgradeblarkQuickstart (pip / virtualenv with venv)Set up an environment using venv:$python-mvenvblark_venv
$sourceblark_venv/bin/activateInstall the library with pip:$python-mpipinstallblarkQuickstart (Conda)Set up an environment using conda:$condacreate-nblark-env-cconda-forgepython=3.10pipblark
$condaactivateblark-envInstall the library from conda:$condainstallblarkDevelopment installIf you run into issues or wish to run an unreleased version of blark, you may
install directly from this repository like so:$python-mpipinstallgit+https://github.com/klauer/blarkSample runsRun the parser or experimental formatter utility.  Current supported file types
include those from TwinCAT3 projects (.tsproj,.sln,.TcPOU,.TcGVL) and plain-text.stfiles.$blarkparse--print-treeblark/tests/POUs/F_SetStateParams.TcPOU
function_declarationNoneF_SetStateParamsindirect_simple_specificationNonesimple_specificationBOOLinput_declarationsNonevar1_init_declvar1_list
...(clipped)...To interact with the Python dataclasses directly, make sure IPython is
installed first and then try:$ blark parse --interactive blark/tests/POUs/F_SetStateParams.TcPOU
# Assuming IPython is installed, the following prompt will come up:

In [1]: results[0].identifier
Out[1]: 'F_SetStateParams/declaration'

In [2]: results[1].identifier
Out[2]: 'F_SetStateParams/implementation'Dump out a parsed and reformatted set of source code:$blarkformatblark/tests/source/array_of_objects.st{attribute'hide'}METHODprv_Detection:BOOLVAR_IN_OUTcurrentChannel:ARRAY[APhase..CPhase]OFclass_baseVector(SIZEOF(vector_t),0);END_VAR
END_METHODblark supports rewriting TwinCAT source code files directly as well:$blarkformatblark/tests/POUs/F_SetStateParams.TcPOU

<TcPlcObjectVersion="1.1.0.1"ProductVersion="3.1.4024.0"><POUName="F_SetStateParams"Id="{f9611d23-4bb5-422d-9f11-2cc94e61fc9e}"SpecialFunc="None"><Declaration><![CDATA[FUNCTIONF_SetStateParams:BOOLVAR_INPUTnStateRef:UDINT;rPosition:REAL;rTolerance:REAL;stBeamParams:ST_BeamParams;...(clipped)...It is also possible to parse the source code into a tokenizedSourceCodetree which supports code introspection and rewriting:In[1]:importblarkIn[2]:parsed=blark.parse_source_code(...:"""...: PROGRAM ProgramName...:     VAR_INPUT...:         iValue : INT;...:     END_VAR...:     VAR_ACCESS...:         AccessName : SymbolicVariable : TypeName READ_WRITE;...:     END_VAR...:     iValue := iValue + 1;...: END_PROGRAM...: """...:)# Access the lark Tree here:In[3]:parsed.tree.dataOut[3]:Token('RULE','iec_source')# Or the transformed information:In[3]:transformed=parsed.transform()In[4]:program=transformed.items[0]In[5]:program.declarations[0].items[0].variables[0].nameOut[5]:Token('IDENTIFIER','iValue')The supported starting grammar rules for the reusable parser include:"iec_source"
"action"
"data_type_declaration"
"function_block_method_declaration"
"function_block_property_declaration"
"function_block_type_declaration"
"function_declaration"
"global_var_declarations"
"program_declaration"
"statement_list"Other starting rules remain possible for advanced users, however a new parser
must be created in that scenario and transformations are not supported.Additionally, please note that you should avoid creating parsers on-the-fly as
there is a startup cost to re-parsing the grammar. Utilize the provided parser
fromblark.get_parser()whenever possible.In [1]: import blark

In [2]: parser = blark.new_parser(start=["any_integer"])

In [3]: Tree('hex_integer', [Token('HEX_STRING', '1010')])Adding Test CasesPresently, test cases are provided in two forms. Within theblark/tests/directory there arePOUs/andsource/directories.TwinCAT source code files belong inblark/tests/POUs.
Plain-text source code files (e.g.,.stfiles) belong inblark/tests/source.Feel free to contribute your own test cases and we'll do our best to ensure
that blark parses them (and continues to parse them) without issue.AcknowledgementsOriginally based on Volker Birk's IEC 61131-3 grammariec2xml(GitHub forkhere) andA Syntactic
Specification for the Programming Languages of theIEC 61131-3
Standardby Flor Narciso et al.  Many aspects of the grammar have been added to,
modified, and in cases entirely rewritten to better support lark grammars and
transformers.Special thanks to the blark contributors:@engineerjoe440Related, Similar, or Alternative ProjectsThere are a number of similar, or related projects that are available."MATIEC"- another IEC 61131-3 Structured
Text parser which supports IEC 61131-3 second edition, without classes,
namespaces and other fancy features. An updated version is alsoavailable on GithubOpenPLC Runtime Version 3-
As stated by the project:OpenPLC is an open-source Programmable Logic Controller that is based on easy to use software. Our focus is to provide a low cost industrial solution for automation and research. OpenPLC has been used in many research papers as a framework for industrial cyber security research, given that it is the only controller to provide the entire source code.RuSTydocumentation- Structured text
compiler written in Rust. As stated by the project:RuSTy is a structured text (ST) compiler written in Rust. RuSTy utilizes the LLVM framework to compile eventually to native code.IEC Checker- Static analysis tool
for IEC 61131-3 logic. As described by the maintainer:iec-checker has the ability to parse ST source code and dump AST and CFG to JSON format, so you can process it with your language of choice.TcBlack- Python black-like code formatter for TwinCAT code.