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

How to #4

Closed Beidendorfer closed 3 years ago

Beidendorfer commented 4 years ago

Is there a description how to use the parser? How is it started?

klauer commented 4 years ago

Chances are good the parser won't be as good as you're hoping (it's barely a prototype at this point), but the gist of it is as follows:

  1. Preferably using non-system Python, set up an environment using, e.g., miniconda:

    $ conda create -n blark-env python=3.7
    $ conda activate blark-env
  2. Install the library (using conda or otherwise, these steps are the same)

$ pip install blark
  1. Run the parser:
$ blark parse (filename)

where filename is a supported type from a standard TwinCAT project: .tsproj, .sln, .TcPOU, .TcGVL

Beidendorfer commented 4 years ago

Thanks for quick answers, I like the idea of the IEC parser.

I get at blark parse (filename) --verbose *Parsing (file name)...

but then there is no output file or console message.

Where can I find the parsing ritual?

Thanks

klauer commented 4 years ago

No problem. The command-line tool isn't so user-friendly, try this instead: blark parse (filename) -vvv (for very-very-verbose)

You should get something that looks like the following:

``` (blark) klauer-osx:plcs klauer$ blark parse lcls-plc-liquid-jet/LiquidJet.tsproj -v * Loading project lcls-plc-liquid-jet/LiquidJet.tsproj * Parsing /Users/klauer/docs/Repos/plcs/lcls-plc-liquid-jet/LiquidJetPLC/POUs/Main.TcPOU (blark) klauer-osx:plcs klauer$ blark parse lcls-plc-liquid-jet/LiquidJet.tsproj -vvv * Loading project lcls-plc-liquid-jet/LiquidJet.tsproj * Parsing /Users/klauer/docs/Repos/plcs/lcls-plc-liquid-jet/LiquidJetPLC/POUs/Main.TcPOU Successfully parsed /Users/klauer/docs/Repos/plcs/lcls-plc-liquid-jet/LiquidJetPLC/POUs/Main.TcPOU: ------------------------------- PROGRAM Main VAR {attribute 'pytmc' := 'pv: XCS:LJH:JET:X'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 1^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 3^Input'} MJetX : DUT_MotionStage; {attribute 'pytmc' := 'pv: XCS:LJH:JET:Y'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 5^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 7^Input'} MJetY : DUT_MotionStage; {attribute 'pytmc' := 'pv: XCS:LJH:JET:Z'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 2^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 4^Input'} MJetZ : DUT_MotionStage; {attribute 'pytmc' := 'pv: XCS:LJH:DET:X'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 6^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 8^Input'} MEpix : DUT_MotionStage; {attribute 'pytmc' := 'pv: XCS:LJH:SS:TOP_X'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 1^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 3^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 5^Input'} MTopX : DUT_MotionStage; {attribute 'pytmc' := 'pv: XCS:LJH:SS:TOP_Y'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 2^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 4^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 6^Input'} MTopY : DUT_MotionStage; {attribute 'pytmc' := 'pv: XCS:LJH:SS:BOT_X'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 1^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 3^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 5^Input'} MBotX : DUT_MotionStage; {attribute 'pytmc' := 'pv: XCS:LJH:SS:BOT_Y'} {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 2^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 4^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 6^Input'} MBotY : DUT_MotionStage; fbMotionJetX : FB_MotionStage; fbMotionJetY : FB_MotionStage; fbMotionJetZ : FB_MotionStage; fbMotionEpix : FB_MotionStage; fbMotionTopX : FB_MotionStage; fbMotionTopY : FB_MotionStage; fbMotionBotX : FB_MotionStage; fbMotionBotY : FB_MotionStage; {attribute 'TcLinkTo' := 'TIID^Device 1 (EtherCAT)^E0 (EK1200)^E5 (EL2004)^Channel 1^Output'} bGigePower AT %Q* : Bool; END_VAR //Update Axis status MJetX.Axis.ReadStatus(); MJetY.Axis.ReadStatus(); MJetZ.Axis.ReadStatus(); MEpix.Axis.ReadStatus(); MTopX.Axis.ReadStatus(); MTopY.Axis.ReadStatus(); MBotX.Axis.ReadStatus(); MBotY.Axis.ReadStatus(); //fbMotion fbMotionJetX(stMotionStage := MJetX); fbMotionJetY(stMotionStage := MJetY); fbMotionJetZ(stMotionStage := MJetZ); fbMotionEpix(stMotionStage := MEpix); fbMotionTopX(stMotionStage := MTopX); fbMotionTopY(stMotionStage := MTopY); fbMotionBotX(stMotionStage := MBotX); fbMotionBotY(stMotionStage := MBotY); //Hardware Enable MJetX.bHardwareEnable := TRUE; MJetY.bHardwareEnable := TRUE; MJetZ.bHardwareEnable := TRUE; MEpix.bHardwareEnable := TRUE; MTopX.bHardwareEnable := TRUE; MTopY.bHardwareEnable := TRUE; MBotX.bHardwareEnable := TRUE; MBotY.bHardwareEnable := TRUE; //Gige Power bGigePower := TRUE; END_PROGRAM ------------------------------- start iec_source program_declaration program_type_name Main var_declarations var_body pragma {attribute 'pytmc' := 'pv: XCS:LJH:JET:X'} var_init_decl pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 1^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 3^Input'} variable_name MJetX simple_spec_init simple_type_name DUT_MotionStage pragma {attribute 'pytmc' := 'pv: XCS:LJH:JET:Y'} var_init_decl pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 5^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 7^Input'} variable_name MJetY simple_spec_init simple_type_name DUT_MotionStage pragma {attribute 'pytmc' := 'pv: XCS:LJH:JET:Z'} pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 2^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 4^Input'} var_init_decl variable_name MJetZ simple_spec_init simple_type_name DUT_MotionStage pragma {attribute 'pytmc' := 'pv: XCS:LJH:DET:X'} pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 6^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E29 (EL1088)^Channel 8^Input'} var_init_decl variable_name MEpix simple_spec_init simple_type_name DUT_MotionStage pragma {attribute 'pytmc' := 'pv: XCS:LJH:SS:TOP_X'} var_init_decl pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 1^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 3^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 5^Input'} variable_name MTopX simple_spec_init simple_type_name DUT_MotionStage pragma {attribute 'pytmc' := 'pv: XCS:LJH:SS:TOP_Y'} var_init_decl pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 2^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 4^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E22 (EL1088)^Channel 6^Input'} variable_name MTopY simple_spec_init simple_type_name DUT_MotionStage pragma {attribute 'pytmc' := 'pv: XCS:LJH:SS:BOT_X'} pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 1^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 3^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 5^Input'} var_init_decl variable_name MBotX simple_spec_init simple_type_name DUT_MotionStage pragma {attribute 'pytmc' := 'pv: XCS:LJH:SS:BOT_Y'} var_init_decl pragma {attribute 'TcLinkTo' := ' .bLimitForwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 2^Input; .bLimitBackwardEnable := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 4^Input; .bHome := TIID^Device 1 (EtherCAT)^E0 (EK1200)^E7 (EK1122)^E20 (EK1100)^E25 (EL1088)^Channel 6^Input'} variable_name MBotY simple_spec_init simple_type_name DUT_MotionStage var_init_decl variable_name fbMotionJetX simple_spec_init simple_type_name FB_MotionStage var_init_decl variable_name fbMotionJetY simple_spec_init simple_type_name FB_MotionStage var_init_decl variable_name fbMotionJetZ simple_spec_init simple_type_name FB_MotionStage var_init_decl variable_name fbMotionEpix simple_spec_init simple_type_name FB_MotionStage var_init_decl variable_name fbMotionTopX simple_spec_init simple_type_name FB_MotionStage var_init_decl variable_name fbMotionTopY simple_spec_init simple_type_name FB_MotionStage var_init_decl variable_name fbMotionBotX simple_spec_init simple_type_name FB_MotionStage var_init_decl variable_name fbMotionBotY simple_spec_init simple_type_name FB_MotionStage var_init_decl pragma {attribute 'TcLinkTo' := 'TIID^Device 1 (EtherCAT)^E0 (EK1200)^E5 (EL2004)^Channel 1^Output'} variable_name bGigePower incompl_location %Q* simple_spec_init bit_string_type_name Bool function_block_body statement_list method expression multi_element_variable variable_name MJetX field_selector variable_name Axis field_selector variable_name ReadStatus method expression multi_element_variable variable_name MJetY field_selector variable_name Axis field_selector variable_name ReadStatus method expression multi_element_variable variable_name MJetZ field_selector variable_name Axis field_selector variable_name ReadStatus method expression multi_element_variable variable_name MEpix field_selector variable_name Axis field_selector variable_name ReadStatus method expression multi_element_variable variable_name MTopX field_selector variable_name Axis field_selector variable_name ReadStatus method expression multi_element_variable variable_name MTopY field_selector variable_name Axis field_selector variable_name ReadStatus method expression multi_element_variable variable_name MBotX field_selector variable_name Axis field_selector variable_name ReadStatus method expression multi_element_variable variable_name MBotY field_selector variable_name Axis field_selector variable_name ReadStatus fb_invocation fb_name fbMotionJetX param_assignment variable_name stMotionStage expression variable_name MJetX fb_invocation fb_name fbMotionJetY param_assignment variable_name stMotionStage expression variable_name MJetY fb_invocation fb_name fbMotionJetZ param_assignment variable_name stMotionStage expression variable_name MJetZ fb_invocation fb_name fbMotionEpix param_assignment variable_name stMotionStage expression variable_name MEpix fb_invocation fb_name fbMotionTopX param_assignment variable_name stMotionStage expression variable_name MTopX fb_invocation fb_name fbMotionTopY param_assignment variable_name stMotionStage expression variable_name MTopY fb_invocation fb_name fbMotionBotX param_assignment variable_name stMotionStage expression variable_name MBotX fb_invocation fb_name fbMotionBotY param_assignment variable_name stMotionStage expression variable_name MBotY assignment_statement multi_element_variable variable_name MJetX field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement multi_element_variable variable_name MJetY field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement multi_element_variable variable_name MJetZ field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement multi_element_variable variable_name MEpix field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement multi_element_variable variable_name MTopX field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement multi_element_variable variable_name MTopY field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement multi_element_variable variable_name MBotX field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement multi_element_variable variable_name MBotY field_selector variable_name bHardwareEnable expression boolean_literal TRUE assignment_statement variable_name bGigePower expression boolean_literal TRUE ------------------------------- [Success] End of /Users/klauer/docs/Repos/plcs/lcls-plc-liquid-jet/LiquidJetPLC/POUs/Main.TcPOU ```

The original grammar is here: https://github.com/klauer/blark/blob/master/blark/iec.grammar It's converted into a lark-based grammar that's used by blark: https://github.com/klauer/blark/blob/master/blark/iec.lark

Eventually I plan to only have the .lark and remove the need for the conversion step - if I ever find time.