├── plcrex
├── models
│ ├── st
│ │ ├── __init__.py
│ │ └── st_model.cp39-win_amd64.pyd
│ ├── fbd
│ │ ├── __init__.py
│ │ └── dummy_model.cp39-win_amd64.pyd
│ ├── pim
│ │ ├── __init__.py
│ │ └── dummy_model.cp39-win_amd64.pyd
│ ├── qrz
│ │ ├── __init__.py
│ │ └── qrz_model.cp39-win_amd64.pyd
│ ├── scl
│ │ ├── __init__.py
│ │ └── scl_model.cp39-win_amd64.pyd
│ ├── smt
│ │ ├── __init__.py
│ │ └── z3py
│ │ │ ├── __init__.py
│ │ │ └── dummy_model.cp39-win_amd64.pyd
│ └── smv
│ │ ├── __init__.py
│ │ ├── nusmv
│ │ ├── __init__.py
│ │ └── dummy_model.cp39-win_amd64.pyd
│ │ └── nusmvi
│ │ ├── __init__.py
│ │ └── dummy_model.cp39-win_amd64.pyd
├── tools
│ ├── fbd2x
│ │ ├── __init__.py
│ │ ├── pyd
│ │ │ └── fbd_optimizer.cp39-win_amd64.pyd
│ │ └── call_fbd_optimizer.py
│ ├── misc
│ │ ├── __init__.py
│ │ └── generic_functions.py
│ ├── st2qrz
│ │ ├── __init__.py
│ │ ├── pyd
│ │ │ └── st2qrz_compiler.cp39-win_amd64.pyd
│ │ └── call_st2qrz_compiler.py
│ ├── st2scl
│ │ ├── __init__.py
│ │ ├── pyd
│ │ │ └── st2scl_compiler.cp39-win_amd64.pyd
│ │ └── call_st2scl_compiler.py
│ ├── fbdia
│ │ ├── pyd
│ │ │ └── io_analysis.cp39-win_amd64.pyd
│ │ ├── __init__.py
│ │ └── call_io_analysis.py
│ ├── tcgen
│ │ ├── pyd
│ │ │ └── test_case_gen.cp39-win_amd64.pyd
│ │ ├── __init__.py
│ │ └── call_test_case_gen.py
│ ├── fbd2st
│ │ ├── pyd
│ │ │ └── fbd2st_compiler.cp39-win_amd64.pyd
│ │ ├── __init__.py
│ │ └── call_fbd2st_compiler.py
│ ├── stp
│ │ ├── __init__.py
│ │ ├── call_st_parser.py
│ │ └── st_parser.py
│ ├── ieccheck
│ │ ├── __init__.py
│ │ ├── iec_checker.py
│ │ └── call_iec_checker.py
│ ├── xmlval
│ │ ├── __init__.py
│ │ ├── call_xml_validator.py
│ │ └── xml_validator.py
│ └── __init__.py
├── data
│ ├── grammars
│ │ ├── __init__.py
│ │ ├── DOTgrammar.lark
│ │ ├── scl_grammar.lark
│ │ ├── scl_grammar_EOL.lark
│ │ ├── st_grammar.lark
│ │ └── qrz_grammar.lark
│ ├── __init__.py
│ └── tc6
│ │ └── __init__.py
├── __init__.py
└── __main__.py
├── bin
└── .gitignore
├── run.bat
├── tests
├── st_to_synchr_models
│ ├── __init__.py
│ ├── TC01.st
│ ├── TC02.st
│ ├── TC03.st
│ ├── TC06.st
│ ├── TC07.st
│ ├── TC17.st
│ ├── TC20.st
│ ├── TC04.st
│ ├── TC05.st
│ ├── TC09.st
│ ├── TC18.st
│ ├── TC19.st
│ ├── TC11.st
│ ├── TC14.st
│ ├── TC15.st
│ ├── TC21.st
│ ├── TC10.st
│ ├── TC16.st
│ ├── TC12.st
│ ├── TC13.st
│ └── TC08.st
├── other_examples
│ ├── TC001_wrong_file.txt
│ ├── DOT.dot
│ └── __init__.py
├── st_examples
│ ├── TC083.st
│ ├── _TC001.st
│ ├── TC014.st
│ ├── TC015.st
│ ├── TC016.st
│ ├── TC017.st
│ ├── TC013.st
│ ├── TC018.st
│ ├── TC025.st
│ ├── TC026.st
│ ├── TC003.st
│ ├── TC006.st
│ ├── TC020.st
│ ├── TC054.st
│ ├── TC055.st
│ ├── TC056.st
│ ├── TC057.st
│ ├── TC060.st
│ ├── TC061.st
│ ├── TC005.st
│ ├── TC012.st
│ ├── TC019.st
│ ├── TC021.st
│ ├── TC022.st
│ ├── TC023.st
│ ├── TC058.st
│ ├── TC059.st
│ ├── TC062.st
│ ├── TC063.st
│ ├── TC009.st
│ ├── TC024.st
│ ├── TC064.st
│ ├── TC010.st
│ ├── TC079.st
│ ├── TC070.st
│ ├── TC027.st
│ ├── TC028.st
│ ├── TC029.st
│ ├── TC030.st
│ ├── TC031.st
│ ├── TC032.st
│ ├── TC033.st
│ ├── TC034.st
│ ├── TC035.st
│ ├── TC036.st
│ ├── TC037.st
│ ├── TC038.st
│ ├── TC039.st
│ ├── TC040.st
│ ├── TC050.st
│ ├── TC051.st
│ ├── TC052.st
│ ├── TC075.st
│ ├── TC076.st
│ ├── TC077.st
│ ├── TC078.st
│ ├── TC041.st
│ ├── TC042.st
│ ├── TC043.st
│ ├── TC044.st
│ ├── TC045.st
│ ├── TC046.st
│ ├── TC047.st
│ ├── TC048.st
│ ├── TC049.st
│ ├── TC053.st
│ ├── TC069.st
│ ├── TC071.st
│ ├── TC073.st
│ ├── TC074.st
│ ├── TC080.st
│ ├── TC011.st
│ ├── TC072.st
│ ├── TC065.st
│ ├── TC004.st
│ ├── TC007.st
│ ├── TC001.st
│ ├── TC008.st
│ ├── TC002.st
│ ├── TC066.st
│ ├── TC067.st
│ ├── TC068.st
│ ├── TC085.st
│ ├── TC006_fbd.st
│ ├── TC081.st
│ ├── TC005_fbd.st
│ ├── __init__.py
│ ├── TC084.st
│ └── TC082.st
├── __init__.py
├── plcopen_examples
│ └── __init__.py
├── real_world_FBDs
│ └── __init__.py
├── test_help.py
├── test_st2qrz.py
├── test_fbdia.py
├── test_tcgen.py
├── test_xmlval.py
├── test_version.py
├── test_st2scl.py
├── test_stp.py
├── test_ieccheck.py
├── test_fbd2st.py
└── test_fbd2x.py
├── .gitattributes
├── docs
├── fig
│ ├── TC005.png
│ ├── TC006.png
│ ├── TC21.png
│ ├── TC081_AST.png
│ ├── TC081_AST3.png
│ ├── TC006_result.png
│ ├── edge_opt_example.png
│ ├── no_opt_example.png
│ ├── coverage_comparison.png
│ ├── fbd_optimizer_designflow_HL.png
│ └── Pollutant_Indicator_WITH_ERROR.png
├── source
│ ├── contact.rst
│ ├── __init__.py
│ ├── install.rst
│ ├── publications.rst
│ ├── index.rst
│ ├── impact_analysis.rst
│ ├── st_to_qrz.rst
│ ├── st_to_scl.rst
│ ├── xml_validator.rst
│ ├── cli.rst
│ ├── st_to_sctx.rst
│ ├── iec_checker.rst
│ ├── fbd_to_st_ext.rst
│ ├── conf.py
│ ├── fbd_to_sctx.rst
│ ├── fbd_to_st.rst
│ └── st_parser.rst
├── requirements.txt
├── Makefile
└── make.bat
├── install-windows.bat
├── MANIFEST.in
├── requirements.txt
├── .readthedocs.yaml
├── .gitignore
└── pyproject.toml
/plcrex/models/st/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/fbd/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/pim/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/qrz/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/scl/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/smt/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/smv/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/tools/fbd2x/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/tools/misc/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/tools/st2qrz/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/tools/st2scl/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/bin/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/plcrex/models/smt/z3py/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/smv/nusmv/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plcrex/models/smv/nusmvi/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/run.bat:
--------------------------------------------------------------------------------
1 | cmd /k venv\Scripts\activate
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/other_examples/TC001_wrong_file.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.st linguist-language=StructuredText
2 |
--------------------------------------------------------------------------------
/docs/fig/TC005.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/TC005.png
--------------------------------------------------------------------------------
/docs/fig/TC006.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/TC006.png
--------------------------------------------------------------------------------
/docs/fig/TC21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/TC21.png
--------------------------------------------------------------------------------
/docs/fig/TC081_AST.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/TC081_AST.png
--------------------------------------------------------------------------------
/docs/fig/TC081_AST3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/TC081_AST3.png
--------------------------------------------------------------------------------
/docs/fig/TC006_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/TC006_result.png
--------------------------------------------------------------------------------
/docs/fig/edge_opt_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/edge_opt_example.png
--------------------------------------------------------------------------------
/docs/fig/no_opt_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/no_opt_example.png
--------------------------------------------------------------------------------
/install-windows.bat:
--------------------------------------------------------------------------------
1 | python -m venv venv && venv\Scripts\activate && python -m pip install -r requirements.txt
--------------------------------------------------------------------------------
/docs/fig/coverage_comparison.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/coverage_comparison.png
--------------------------------------------------------------------------------
/docs/source/contact.rst:
--------------------------------------------------------------------------------
1 | Contact
2 | =======
3 |
4 | .. contact:
5 |
6 | Marcel C. Werner, plcrex.info@gmail.com
--------------------------------------------------------------------------------
/docs/fig/fbd_optimizer_designflow_HL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/fbd_optimizer_designflow_HL.png
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC01.st:
--------------------------------------------------------------------------------
1 | PROGRAM TC01//_program
2 | VAR
3 | x0 : INT;
4 | END_VAR
5 |
6 | x0 := 0;
7 | END_PROGRAM
--------------------------------------------------------------------------------
/docs/fig/Pollutant_Indicator_WITH_ERROR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/docs/fig/Pollutant_Indicator_WITH_ERROR.png
--------------------------------------------------------------------------------
/plcrex/models/st/st_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/st/st_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/models/qrz/qrz_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/qrz/qrz_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/models/scl/scl_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/scl/scl_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/models/fbd/dummy_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/fbd/dummy_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/models/pim/dummy_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/pim/dummy_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC02.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC02//_functionBlock
2 | VAR
3 | x0 : INT;
4 | END_VAR
5 |
6 | x0 := 0;
7 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC03.st:
--------------------------------------------------------------------------------
1 | PROGRAM TC03 //_import
2 | VAR
3 | fb1 : TC04;
4 | END_VAR
5 |
6 | fb1(x0 := 2, x1 := 3);
7 | END_PROGRAM
--------------------------------------------------------------------------------
/plcrex/models/smt/z3py/dummy_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/smt/z3py/dummy_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/models/smv/nusmv/dummy_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/smv/nusmv/dummy_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/tools/fbdia/pyd/io_analysis.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/tools/fbdia/pyd/io_analysis.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/models/smv/nusmvi/dummy_model.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/models/smv/nusmvi/dummy_model.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/tools/fbd2x/pyd/fbd_optimizer.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/tools/fbd2x/pyd/fbd_optimizer.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/tools/tcgen/pyd/test_case_gen.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/tools/tcgen/pyd/test_case_gen.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/tools/fbd2st/pyd/fbd2st_compiler.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/tools/fbd2st/pyd/fbd2st_compiler.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/tools/st2qrz/pyd/st2qrz_compiler.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/tools/st2qrz/pyd/st2qrz_compiler.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/plcrex/tools/st2scl/pyd/st2scl_compiler.cp39-win_amd64.pyd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marwern/PLCreX/HEAD/plcrex/tools/st2scl/pyd/st2scl_compiler.cp39-win_amd64.pyd
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC06.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC06 //_in_outputs
2 | VAR_IN_OUT
3 | y0 : INT;
4 | y1 : INT;
5 | END_VAR
6 |
7 | y0 := y1;
8 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC07.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC07 //_localVariables
2 | VAR
3 | x0 : INT;
4 | x1 : INT := 6;
5 | END_VAR
6 |
7 | x0 := x1;
8 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC17.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC17 //_singleAssignment_1
2 | VAR
3 | x : INT := 2;
4 | y : INT;
5 | END_VAR
6 |
7 | y := x;
8 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC20.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC20//_delayedAssignment
2 | VAR
3 | x0 : INT := 2;
4 | y : INT := 1;
5 | END_VAR
6 |
7 | y := y + x0;
8 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC083.st:
--------------------------------------------------------------------------------
1 | PROGRAM TC083
2 | VAR_ACCESS
3 | Var1 : DINT;
4 | Var2 : DINT;
5 | Var3 : DINT;
6 | END_VAR
7 |
8 | Var1 := 19 / 0;
9 | Var2 := Var1 / 1;
10 | END_PROGRAM
--------------------------------------------------------------------------------
/tests/st_examples/_TC001.st:
--------------------------------------------------------------------------------
1 |
2 | PROGRAM TC001
3 | VAR_INPUT
4 | x1:INT;
5 | END_VAR
6 | VAR_OUTPUT
7 | x2:INT;
8 | END_VAR
9 | VAR
10 | x3:INT:=3;
11 | END_VAR
12 | x2:=x1+x3;
13 | END_PROGRAM
14 |
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC04.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC04 //_inputs
2 | VAR_INPUT
3 | x0 : INT;
4 | x1 : INT := 6;
5 | END_VAR
6 | VAR
7 | x2 : INT;
8 | END_VAR
9 |
10 | x2 := x1;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC05.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC05 //_outputs
2 | VAR_OUTPUT
3 | y0 : INT;
4 | y1 : INT := 6;
5 | END_VAR
6 | VAR
7 | x2 : INT;
8 | END_VAR
9 |
10 | y0 := x2;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC09.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC09 //_constants
2 | VAR
3 | x0 : BOOL;
4 | x1 : BOOL := TRUE;
5 | x2 : BOOL := FALSE;
6 | END_VAR
7 |
8 | x0 := x1;
9 | x0 := x2;
10 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC18.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC18//_singleAssignment_2
2 | VAR
3 | x0 : INT := 2;
4 | x1 : INT := 2;
5 | y0 : INT;
6 | y1 : INT;
7 | END_VAR
8 |
9 | y0 := x0;
10 | y1 := x1;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/other_examples/DOT.dot:
--------------------------------------------------------------------------------
1 | digraph G {rankdir=LR;graph [pad="0.5", nodesep="1", ranksep="4"]; splines=spline;node [shape=rect fillcolor=white style=filled];subgraph cluster_1{label=" TC001 "; style=rounded;bgcolor=beige;fontsize = 42; A->a A->b C->a}}
2 |
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC19.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC19//_multipleAssignment
2 | VAR
3 | x0 : INT := 2;
4 | x1 : INT := 2;
5 | x2 : INT := 2;
6 | y1 : INT;
7 | END_VAR
8 |
9 | y1 := x0;
10 | y1 := x1;
11 | y1 := x2;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC11.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC11 // _inEquality
2 | VAR
3 | x0 : BOOL;
4 | x1 : BOOL := TRUE;
5 | x2 : BOOL := FALSE;
6 | END_VAR
7 |
8 | x0 := x1 = x2;
9 | x0 := EQ(x1,x2);
10 | x0 := x1 <> x2;
11 | x0 := NE(x1,x2);
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC14.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC14 //_conditional
2 | VAR
3 | x0 : BOOL;
4 | x1 : BOOL := TRUE;
5 | END_VAR
6 |
7 | IF x1 THEN
8 | x0:=TRUE;
9 | ELSE
10 | x0:= FALSE;
11 | END_IF;
12 |
13 | x0 := SEL(x1,TRUE,FALSE);
14 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC014.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: INT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC014
6 | VAR
7 | x1 : INT;
8 | END_VAR
9 |
10 | x1:=5;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC015.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: DINT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC015
6 | VAR
7 | x1 : DINT;
8 | END_VAR
9 |
10 | x1:=5;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC016.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: UINT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC016
6 | VAR
7 | x1 : UINT;
8 | END_VAR
9 |
10 | x1:=5;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC017.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: REAL
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC017
6 | VAR
7 | x1 : REAL;
8 | END_VAR
9 |
10 | x1:=5.0;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC15.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC15 //_loop1
2 | VAR
3 | x0 : INT := 0;
4 | x1 : INT := 1;
5 | y : INT;
6 | i : INT;
7 | i0 : INT := 0;
8 | i1 : INT := 10;
9 | END_VAR
10 |
11 | i:=i0;
12 | WHILE i<=i1 DO
13 | y := x0;
14 | i := i+1;
15 | END_WHILE;
16 | y := x1;
17 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC013.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: BOOL
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC013
6 | VAR
7 | x1 : BOOL;
8 | END_VAR
9 |
10 | x1:=TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC018.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: TIME
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC018
6 | VAR
7 | x1 : TIME;
8 | END_VAR
9 |
10 | x1:=t#5000ms;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC025.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: FALSE
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC025
6 | VAR
7 | x1 : BOOL;
8 | END_VAR
9 |
10 | x1:=FALSE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC026.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: TRUE
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC026
6 | VAR
7 | x1 : BOOL;
8 | END_VAR
9 |
10 | x1:=TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC21.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC21
2 | VAR_OUTPUT
3 | y : INT;
4 | END_VAR
5 | VAR
6 | x : INT := 1;
7 | i : INT;
8 | i0 : INT := 0;
9 | i1 : INT := 10;
10 | END_VAR
11 |
12 | i:=i0;
13 | REPEAT
14 | y := i;
15 | i := i+1;
16 | UNTIL i>i1
17 | END_REPEAT;
18 | y := x;
19 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC10.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC10 //Boolean Operators
2 | VAR
3 | x0 : BOOL;
4 | x1 : BOOL := TRUE;
5 | x2 : BOOL := FALSE;
6 | END_VAR
7 |
8 | x0 := NOT(x1);
9 | x0 := x1 AND x2;
10 | x0 := AND(x1,x2);
11 | x0 := x1 OR x2;
12 | x0 := OR(x1,x2);
13 | x0 := x1 XOR x2;
14 | x0 := XOR(x1,x2);
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC16.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC16 // _loop2
2 | VAR
3 | x0 : INT := 0;
4 | x1 : INT := 1;
5 | y : INT;
6 | i : INT;
7 | i0 : INT := 0;
8 | i1 : INT := 10;
9 | END_VAR
10 |
11 | i:=i0;
12 | REPEAT
13 | y := x0;
14 | i := i+1;
15 | UNTIL i>i1
16 | END_REPEAT;
17 | y := x1;
18 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC003.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Program Organization Units: FUNCTION
3 | // ********************************************************************************
4 |
5 | FUNCTION TC003
6 | VAR_OUTPUT
7 | x1 : BOOL;
8 | END_VAR
9 |
10 | x1 := TRUE;
11 | END_FUNCTION
--------------------------------------------------------------------------------
/tests/st_examples/TC006.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Variable Declaration List: VAR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC006
6 | VAR
7 | x1 : BOOL := FALSE;
8 | END_VAR
9 |
10 | x1:= TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC020.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: ARRAY OF INT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC020
6 | VAR
7 | x1 : ARRAY [1..2] OF INT;
8 | END_VAR
9 |
10 | x1[1]:= 1;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC054.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: -Tau
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC054
6 | VAR
7 | x1 : INT;
8 | x2 : INT := 5;
9 | END_VAR
10 |
11 | x1 := -x2;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC055.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: -Tau
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC055
6 | VAR
7 | x1 : INT;
8 | x2 : INT := 5;
9 | END_VAR
10 |
11 | x1 := -(2);
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC056.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: *
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC056
6 | VAR
7 | x1 : INT;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:=x2*3;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC057.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: /
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC057
6 | VAR
7 | x1 : INT;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:=x2/3;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC060.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: +
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC060
6 | VAR
7 | x1 : INT;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:=x2 + 3;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC061.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: -
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC061
6 | VAR
7 | x1 : INT;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:=x2 - 3;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC005.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Program Organization Units: FUNCTION_BLOCK
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC005
6 | VAR
7 | x1 : BOOL;
8 | END_VAR
9 |
10 | x1:= TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC012.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Interface Declaration List: VAR_IN_OUT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC012
6 | VAR_IN_OUT
7 | x1 : BOOL;
8 | END_VAR
9 |
10 | x1:=TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC019.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: ARRAY OF BOOL
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC019
6 | VAR
7 | x1 : ARRAY [1..2] OF BOOL;
8 | END_VAR
9 |
10 | x1[1]:= TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC021.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: ARRAY OF DINT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC021
6 | VAR
7 | x1 : ARRAY [1..2] OF DINT;
8 | END_VAR
9 |
10 | x1[1]:= 1;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC022.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: ARRAY OF UINT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC022
6 | VAR
7 | x1 : ARRAY [1..2] OF UINT;
8 | END_VAR
9 |
10 | x1[1]:= 1;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC023.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: ARRAY OF REAL
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC023
6 | VAR
7 | x1 : ARRAY [1..2] OF REAL;
8 | END_VAR
9 |
10 | x1[1]:= 1.0;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC058.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: /
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC058
6 | VAR
7 | x1 : REAL;
8 | x2 : REAL :=5.0;
9 | END_VAR
10 |
11 | x1:=x2/3.0;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC059.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: MOD
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC059
6 | VAR
7 | x1 : INT;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:=x2 MOD 3;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC062.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: ()
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC062
6 | VAR
7 | x1 : INT;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:= (1+7) / 3;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC063.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: ()
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC063
6 | VAR
7 | x1 : INT;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:= (1-7) / 3;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC12.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC12 //_numericRelations
2 | VAR
3 | x0 : BOOL;
4 | x1 : INT := 1;
5 | x2 : INT := 2;
6 | END_VAR
7 |
8 | x0 := x1 < x2;
9 | x0 := LT(x1, x2);
10 | x0 := x1 <= x2;
11 | x0 := LE(x1, x2);
12 | x0 := x1 > x2;
13 | x0 := GT(x1, x2);
14 | x0 := x1 >= x2;
15 | x0 := GE(x1, x2);
16 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC009.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Interface Declaration List: VAR_OUTPUT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC009
6 | VAR_OUTPUT
7 | x1 : BOOL;
8 | END_VAR
9 |
10 | x1 := TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC024.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Data Types: ARRAY OF TIME
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC024
6 | VAR
7 | x1 : ARRAY [1..2] OF TIME;
8 | END_VAR
9 |
10 | x1[1]:= t#5000ms;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC064.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: ()
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC064
6 | VAR
7 | x1 : REAL;
8 | x2 : INT :=5;
9 | END_VAR
10 |
11 | x1:= (1.0-7) / 3.0;
12 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC010.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Interface Declaration List: VAR_OUTPUT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC010
6 | VAR_OUTPUT
7 | x1 : BOOL := FALSE;
8 | END_VAR
9 |
10 | x1 := TRUE;
11 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC079.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Assignment: :=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC079
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | x3 : INT;
10 | END_VAR
11 |
12 | x1:=x1+1;
13 |
14 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC070.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Bounded Loops: FOR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC070
6 | VAR
7 | x2 : INT;
8 | END_VAR
9 |
10 | FOR x1:=0 TO 10 DO
11 | x2 := x1;
12 | END_FOR;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC027.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: =
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC027
6 | VAR
7 | x1 : INT := 4;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 = x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC028.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: =
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC028
6 | VAR
7 | x1 : INT := 6;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 = x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC029.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: <>
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC029
6 | VAR
7 | x1 : INT := 4;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 <> x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC030.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: <>
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC030
6 | VAR
7 | x1 : INT := 6;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 <> x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC031.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: <
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC031
6 | VAR
7 | x1 : INT := 4;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 < x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC032.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: <
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC032
6 | VAR
7 | x1 : INT := 6;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 < x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC033.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: >
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC033
6 | VAR
7 | x1 : INT := 4;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 > x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC034.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: >
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC034
6 | VAR
7 | x1 : INT := 6;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 > x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC035.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: <=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC035
6 | VAR
7 | x1 : INT := 4;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 <= x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC036.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: <=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC036
6 | VAR
7 | x1 : INT := 6;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 <= x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC037.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: >=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC037
6 | VAR
7 | x1 : INT := 4;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 >= x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC038.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: >=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC038
6 | VAR
7 | x1 : INT := 6;
8 | x2 : INT := 6;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 >= x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC039.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: NOT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC039
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : BOOL;
9 | END_VAR
10 |
11 | x1:=NOT x1;
12 | x2 := TRUE;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC040.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: NOT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC040
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL;
9 | END_VAR
10 |
11 | x1:=NOT x1;
12 | x2 := TRUE;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC050.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: OR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC050
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : BOOL := FALSE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 OR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC051.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: OR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC051
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL := TRUE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 OR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC052.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: OR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC052
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : BOOL := TRUE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 OR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC075.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Assignment: :=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC075
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | x3 : INT;
10 | END_VAR
11 |
12 | x1:=x1+2;
13 | x2:=1;
14 |
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC076.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Assignment: :=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC076
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | x3 : INT;
10 | END_VAR
11 |
12 | x1:=2;
13 | x1:=3;
14 |
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC077.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Assignment: :=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC077
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | x3 : INT;
10 | END_VAR
11 |
12 | x1:=x2;
13 | x2:=1;
14 |
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC078.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Assignment: :=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC078
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | x3 : INT;
10 | END_VAR
11 |
12 | x1:=1;
13 | x2:=x1;
14 |
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | myst-parser==2.0.0
2 | sphinx-press-theme==0.8.0
3 | rst2pdf==0.101
4 | Sphinx==7.2.6
5 | sphinx-markdown-tables==0.0.17
6 | sphinx-rtd-theme==2.0.0
7 | sphinxcontrib-applehelp==1.0.7
8 | sphinxcontrib-devhelp==1.0.5
9 | sphinxcontrib-htmlhelp==2.0.4
10 | sphinxcontrib-jquery==4.1
11 | sphinxcontrib-jsmath==1.0.1
12 | sphinxcontrib-qthelp==1.0.6
13 | sphinxcontrib-serializinghtml==1.1.9
--------------------------------------------------------------------------------
/tests/st_examples/TC041.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: AND
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC041
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL := FALSE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 AND x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC042.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: AND
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC042
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : BOOL := FALSE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 AND x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC043.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: AND
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC043
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL := TRUE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 AND x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC044.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: AND
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC044
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL := TRUE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 AND x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC045.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: XOR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC045
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL := FALSE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 XOR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC046.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: XOR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC046
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : BOOL := FALSE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 XOR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC047.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: XOR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC047
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL := TRUE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 XOR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC048.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: XOR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC048
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : BOOL := TRUE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 XOR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC049.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: OR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC049
6 | VAR
7 | x1 : BOOL := FALSE;
8 | x2 : BOOL := FALSE;
9 | x3 : BOOL;
10 | END_VAR
11 |
12 | x3:=x1 OR x2;
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC053.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Expressions: EXPT Macro
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC053
6 | VAR
7 | x1 : REAL := 1.0;
8 | x2 : REAL := 2.0;
9 | x3 : REAL;
10 | END_VAR
11 |
12 | x3:=EXPT(x1,x2);
13 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC069.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Bounded Loops: FOR
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC069
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | END_VAR
10 |
11 | FOR x1:=0 TO 10 BY 2 DO
12 | x2 := x1+5;
13 | END_FOR;
14 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC071.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Bounded Loops: WHILE
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC071
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | END_VAR
10 |
11 | WHILE x1 <= 10 DO
12 | x1 := x2 + x1;
13 | END_WHILE;
14 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC073.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Assignment: :=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC073
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | x3 : INT;
10 | END_VAR
11 |
12 | x1:=1;
13 | x2:=1;
14 | x3:=1;
15 |
16 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC074.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Assignment: :=
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC074
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | x3 : INT;
10 | END_VAR
11 |
12 | x1:=1;
13 | x2:=1;
14 | x1:=2;
15 |
16 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC080.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Real POU
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC080
6 | VAR_INPUT
7 | S1 : BOOL;
8 | R : BOOL;
9 | END_VAR
10 | VAR_OUTPUT
11 | Q1 : BOOL;
12 | END_VAR
13 |
14 | Q1 := S1 XOR (Q1 AND NOT R);
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC011.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Interface Declaration List: VAR_EXTERNAL
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC011
6 | VAR_EXTERNAL
7 | global : BOOL;
8 | END_VAR
9 | VAR
10 | x1 : BOOL;
11 | END_VAR
12 |
13 | x1 := global;
14 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC072.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Bounded Loops: REPEAT UNTIL
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC072
6 | VAR
7 | x1 : INT;
8 | x2 : INT;
9 | END_VAR
10 |
11 | REPEAT
12 | x1 := 5 + x2;
13 | UNTIL x1 > 10
14 | END_REPEAT;
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC065.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Conditional Statements: IF ELSE
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC065
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : INT := 5;
9 | x3 : INT;
10 | END_VAR
11 |
12 | IF x1 THEN
13 | x3:=x2;
14 | END_IF;
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC004.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Program Organization Units: FUNCTION : DATATYPE
3 | // ********************************************************************************
4 |
5 | FUNCTION TC004 : BOOL
6 | VAR_INPUT
7 | x1 : BOOL;
8 | END_VAR
9 | VAR
10 | x2: BOOL := FALSE;
11 | END_VAR
12 |
13 | TC004 := x2;
14 | END_FUNCTION
--------------------------------------------------------------------------------
/tests/st_examples/TC007.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Interface Declaration List: VAR_INPUT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC007
6 | VAR_INPUT
7 | x1 : BOOL;
8 | END_VAR
9 | VAR
10 | x2 : BOOL := FALSE;
11 | x3 : BOOL := FALSE;
12 | END_VAR
13 |
14 | x2:=x1;
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC001.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Program Organization Units: PROGRAM
3 | // ********************************************************************************
4 |
5 | PROGRAM TC001
6 | VAR_INPUT
7 | x1 : INT;
8 | END_VAR
9 | VAR_OUTPUT
10 | x2 : INT;
11 | END_VAR
12 | VAR
13 | x3 : INT := 3;
14 | END_VAR
15 |
16 | x2:=x1+x3;
17 | END_PROGRAM
--------------------------------------------------------------------------------
/tests/st_examples/TC008.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Interface Declaration List: VAR_INPUT
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC008
6 | VAR_INPUT
7 | x1 : BOOL := FALSE;
8 | END_VAR
9 | VAR
10 | x2 : BOOL := FALSE;
11 | x3 : BOOL := FALSE;
12 | END_VAR
13 |
14 | x2:=x1;
15 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC002.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Program Organization Units: PROGRAM
3 | // ********************************************************************************
4 |
5 | PROGRAM TC002
6 | VAR_INPUT
7 | x1 : INT;
8 | END_VAR
9 | VAR_OUTPUT
10 | x2 : INT;
11 | END_VAR
12 | VAR
13 | x3 : INT := 3;
14 | END_VAR
15 |
16 | x2:=x1 +(x3*x1);
17 | END_PROGRAM
--------------------------------------------------------------------------------
/tests/st_examples/TC066.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Conditional Statements: IF ELSE
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC066
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : INT := 5;
9 | x3 : INT;
10 | END_VAR
11 |
12 | IF x1 THEN
13 | x3:=x2;
14 | ELSE
15 | x3:= -x2;
16 | END_IF;
17 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC067.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Conditional Statements: IF ELSE
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC067
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : INT := 5;
9 | x3 : INT;
10 | END_VAR
11 |
12 | IF x1 THEN
13 | x3:=x2;
14 | ELSIF x2 = 5 THEN
15 | x3:=-x2;
16 | END_IF;
17 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC13.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC13 //_arithmeticOperators
2 | VAR
3 | x0 : REAL;
4 | x1 : REAL := 1.0;
5 | x2 : REAL := 2.0;
6 | x3 : INT := 1;
7 | x4 : INT := 2;
8 | x5 : INT;
9 | END_VAR
10 |
11 | x0 := x1 + x2;
12 | x0 := ADD(x1, x2);
13 | x0 := x1 - x2;
14 | x0 := SUB(x1, x2);
15 | x0 := x1 * x2;
16 | x0 := MUL(x1, x2);
17 | x0 := x1 / x2;
18 | x0 := DIV(x1, x2);
19 | x0 := EXPT(x1, x2);
20 | x5 := MOD(x3, x4);
21 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC068.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Conditional Statements: IF ELSE
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC068
6 | VAR
7 | x1 : BOOL := TRUE;
8 | x2 : INT := 5;
9 | x3 : INT;
10 | END_VAR
11 |
12 | IF x1 THEN
13 | x3:=x2;
14 | ELSIF x2 = 5 THEN
15 | x3:=-x2;
16 | ELSE
17 | x3:=2*x2;
18 | END_IF;
19 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | prune bin
2 | prune docs
3 | prune tests
4 | prune venv
5 | prune PLCreX_outputs
6 | prune exports
7 | include plcrex/data/grammars/*.lark
8 | include plcrex/data/tc6/*.xsd
9 | include plcrex/tools/fbd2st/pyd/*.pyd
10 | include plcrex/tools/fbd2x/pyd/*.pyd
11 | include plcrex/tools/fbdia/pyd/*.pyd
12 | include plcrex/tools/st2qrz/pyd/*.pyd
13 | include plcrex/tools/st2scl/pyd/*.pyd
14 | include plcrex/tools/tcgen/pyd/*.pyd
15 | include plcrex/models/st/*.pyd
16 | include plcrex/models/scl/*.pyd
17 | include plcrex/models/qrz/*.pyd
--------------------------------------------------------------------------------
/tests/st_examples/TC085.st:
--------------------------------------------------------------------------------
1 | PROGRAM TC085
2 | VAR_INPUT
3 | a: INT;
4 | b: INT;
5 | END_VAR
6 | VAR_OUTPUT
7 | gcd:INT;
8 | END_VAR
9 | VAR
10 | c: INT;
11 | d: INT;
12 | END_VAR
13 |
14 | c:=a;
15 | d:=b;
16 |
17 | IF (c=0) THEN
18 | gcd := d;
19 |
20 | ELSE
21 | WHILE (d <>0) DO
22 | IF (c>d) THEN
23 | c := c-d;
24 | ELSE
25 | d := d-c;
26 | END_IF;
27 | END_WHILE;
28 | gcd := c;
29 | END_IF;
30 | END_PROGRAM
--------------------------------------------------------------------------------
/tests/st_to_synchr_models/TC08.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC08 // _datatypes
2 | VAR
3 | x0 : BOOL;
4 | x1 : BOOL := TRUE;
5 | x2 : INT;
6 | x3 : INT := 2;
7 | x4 : REAL;
8 | x5 : REAL := 1.23;
9 | x7 : TIME;
10 | x8 : TIME := t#5s;
11 | x9 : ARRAY [1..2] OF BOOL;
12 | x10 : ARRAY [1..2] OF INT;
13 | x11 : ARRAY [1..2] OF REAL;
14 | x12 : ARRAY [1..2] OF TIME;
15 | END_VAR
16 |
17 | x0 := x1;
18 | x2 := x3;
19 | x4 := x5;
20 | x7 := x8;
21 | x9[0]:=TRUE;
22 | x10[0]:=2;
23 | x11[0]:=1.23;
24 | x12[0]:=t#2s;
25 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | attrs==23.1.0
2 | click==8.1.6
3 | colorama==0.4.5
4 | coverage==6.5.0
5 | coverage-badge==1.1.0
6 | dd==0.5.7
7 | dicttoxml2==2.1.0
8 | elementpath==3.0.2
9 | exceptiongroup==1.2.0
10 | iniconfig==2.0.0
11 | lark==1.1.7
12 | markdown-it-py==3.0.0
13 | mdurl==0.1.2
14 | packaging==23.2
15 | pluggy==1.3.0
16 | pydot==1.4.2
17 | pyeda==0.29.0
18 | Pygments==2.17.2
19 | pyparsing==3.1.1
20 | pytest==7.2.0
21 | rich==13.5.1
22 | termcolor==2.3.0
23 | tomli==2.0.1
24 | typer==0.9.0
25 | typing_extensions==4.8.0
26 | xmlschema==2.1.1
27 | z3-solver==4.12.2.0
--------------------------------------------------------------------------------
/tests/st_examples/TC006_fbd.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC006
2 | VAR_INPUT
3 | i1 : BOOL;
4 | i2 : BOOL;
5 | END_VAR
6 | VAR_OUTPUT
7 | o1 : BOOL;
8 | o2 : BOOL;
9 | o3 : BOOL;
10 | END_VAR
11 | VAR
12 | l1 : BOOL;
13 | l2 : TIME := T#5s;
14 | TON0 : TON;
15 | AND1_OUT : BOOL;
16 | XOR3_OUT : BOOL;
17 | OR13_OUT : BOOL;
18 | END_VAR
19 |
20 | AND1_OUT := AND(i1, i2);
21 | TON0(AND1_OUT, l2);
22 | XOR3_OUT := XOR(AND1_OUT, TON0.Q);
23 | l1 := XOR3_OUT;
24 | o1 := TON0.Q;
25 | o2 := i1;
26 | OR13_OUT := OR(i2, l1);
27 | o3 := OR13_OUT;
28 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC081.st:
--------------------------------------------------------------------------------
1 | FUNCTION_BLOCK TC081
2 | VAR_INPUT
3 | IN1 : INT;
4 | IN2 : INT;
5 | IN3 : INT;
6 | IN4 : BOOL;
7 | END_VAR
8 | VAR_OUTPUT
9 | Wrn : BOOL;
10 | Err : BOOL;
11 | Ctr : INT;
12 | iOut2 : INT;
13 | END_VAR
14 | VAR
15 | SR1 : SR;
16 | TON1 : TON;
17 | TON2 : TON;
18 | END_VAR
19 |
20 | SR1(((((20*IN1)+(6*IN2)+IN3))=(100*2)) AND (IN1+IN2+IN3=100),IN4);
21 | TON1((((((20*IN1)+(6*IN2)+IN3))=(100*2)) AND (IN1+IN2+IN3=100)),2);
22 | TON2(IN1+IN2+IN3=42 AND SR1.Q,3);
23 | Ctr := TON2.ET;
24 | Err := TON1.Q;
25 | Wrn := SR1.Q;
26 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/tests/st_examples/TC005_fbd.st:
--------------------------------------------------------------------------------
1 | PROGRAM TC005
2 | VAR_INPUT
3 | i1 : BOOL;
4 | i2 : BOOL := FALSE;
5 | i3 : TIME;
6 | END_VAR
7 | VAR_OUTPUT
8 | o1 : BOOL := FALSE;
9 | o2 : BOOL := FALSE;
10 | END_VAR
11 | VAR
12 | o4 : BOOL;
13 | TON0 : TON;
14 | AND1_OUT : BOOL;
15 | XOR3_OUT : BOOL;
16 | END_VAR
17 |
18 | AND1_OUT := AND(i1,i2);
19 | TON0(AND1_OUT,i3);
20 | XOR3_OUT := XOR(AND1_OUT,TON0.Q);
21 | o1 := XOR3_OUT;
22 | o4 := TON0.Q;
23 | o2 := i1;
24 | END_PROGRAM
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | # .readthedocs.yaml
2 | # Read the Docs configuration file
3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4 |
5 | # Required
6 | version: 2
7 |
8 | # Set the version of Python and other tools you might need
9 | build:
10 | os: ubuntu-22.04
11 | tools:
12 | python: "3.11"
13 |
14 | # Build documentation in the docs/ directory with Sphinx
15 | sphinx:
16 | configuration: docs/source/conf.py
17 |
18 | # If using Sphinx, optionally build your docs in additional formats such as PDF
19 | formats:
20 | - pdf
21 |
22 | # Optionally declare the Python requirements required to build your docs
23 | python:
24 | install:
25 | - requirements: docs/requirements.txt
--------------------------------------------------------------------------------
/docs/source/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/tools/stp/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/data/grammars/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/tools/fbd2st/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/tools/fbdia/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/tools/ieccheck/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/tools/tcgen/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/tools/xmlval/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/data/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/data/tc6/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/plcrex/tools/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/tests/other_examples/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/tests/st_examples/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/tests/plcopen_examples/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/tests/real_world_FBDs/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # .idea folder
2 | .idea/
3 |
4 | # Byte-compiled / optimized
5 | __pycache__/
6 | *.py[co]
7 |
8 | # Unit test / coverage reports
9 | htmlcov/
10 | .tox/
11 | .nox/
12 | .coverage
13 | .coverage.*
14 | .cache
15 | nosetests.xml
16 | coverage.xml
17 | *.cover
18 | *.py,cover
19 | .hypothesis/
20 | .pytest_cache/
21 |
22 | # Sphinx documentation
23 | docs/build/
24 |
25 | # PyBuilder
26 | target/
27 |
28 | # pyenv
29 | .python-version
30 |
31 | # Environments
32 | .env
33 | .venv
34 | env/
35 | venv/
36 | ENV/
37 | env.bak/
38 | venv.bak/
39 |
40 | # Spyder project settings
41 | .spyderproject
42 | .spyproject
43 |
44 | # Rope project settings
45 | .ropeproject
46 |
47 | # mkdocs documentation
48 | /site
49 |
50 | # mypy
51 | .mypy_cache/
52 | .dmypy.json
53 | dmypy.json
54 |
55 | # Pyre type checker
56 | .pyre/
57 |
--------------------------------------------------------------------------------
/tests/st_examples/TC084.st:
--------------------------------------------------------------------------------
1 | FUNCTION dead_code_after_return : INT
2 | VAR
3 | counter : INT := 0;
4 | some_var : INT;
5 | END_VAR
6 | counter := counter + 1;
7 | counter := 2 + 2;
8 | RETURN;
9 | some_var := SQRT(16#42); (* UnreachableCode error *)
10 | some_var := 16#42; (* No additional warnings *)
11 | some_var := 19;
12 | END_FUNCTION
13 |
14 | PROGRAM dead_code_in_the_loops
15 | VAR a : INT; i : INT; END_VAR
16 | WHILE i < 10 DO
17 | IF i = 5 THEN
18 | i := i + 1;
19 | EXIT;
20 | i := 19; (* UnreachableCode error *)
21 | i := 42; (* No additional warnings *)
22 | i := 42;
23 | ELSIF i = 6 THEN
24 | CONTINUE;
25 | i := 3; (* UnreachableCode error *)
26 | i := 44; (* No additional warnings *)
27 | i := 19;
28 | END_IF;
29 | i := i + 2;
30 | END_WHILE;
31 | I := 0;
32 | END_PROGRAM
--------------------------------------------------------------------------------
/plcrex/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | __app_name__ = "plcrex"
20 | __version__ = "2.0.0"
21 | __owner__ = "Marcel C. Werner"
22 | __copyright__ = "2022-2024, " + __owner__
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 |
14 | if "%1" == "" goto help
15 |
16 | %SPHINXBUILD% >NUL 2>NUL
17 | if errorlevel 9009 (
18 | echo.
19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
20 | echo.installed, then set the SPHINXBUILD environment variable to point
21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
22 | echo.may add the Sphinx directory to PATH.
23 | echo.
24 | echo.If you don't have Sphinx installed, grab it from
25 | echo.http://sphinx-doc.org/
26 | exit /b 1
27 | )
28 |
29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
30 | goto end
31 |
32 | :help
33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
34 |
35 | :end
36 | popd
37 |
--------------------------------------------------------------------------------
/plcrex/__main__.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex import cli
20 | from plcrex import __app_name__
21 |
22 | def main():
23 | cli.app(prog_name=__app_name__)
24 |
25 | if __name__ == "__main__":
26 | main()
--------------------------------------------------------------------------------
/tests/test_help.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_help():
27 | result = runner.invoke(cli.app, ["--help"])
28 | assert result.exit_code == 0
29 |
--------------------------------------------------------------------------------
/tests/st_examples/TC082.st:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Real POU
3 | // ********************************************************************************
4 |
5 | FUNCTION_BLOCK TC082
6 | VAR_INPUT
7 | IN : BOOL;
8 | PT : INT;
9 | END_VAR
10 | VAR_OUTPUT
11 | Q : BOOL;
12 | ET : INT;
13 | END_VAR
14 | VAR
15 | CYCLE : INT;
16 | TIMER : INT;
17 | TIMERN : INT;
18 | GE7_OUT : BOOL;
19 | ADD8_OUT : INT;
20 | SEL3_OUT : INT;
21 | SEL5_OUT : INT;
22 | SEL2_OUT : INT;
23 | SEL6_OUT : INT;
24 | SEL1_OUT : BOOL;
25 | SEL4_OUT : BOOL;
26 | END_VAR
27 |
28 | GE7_OUT := GE(TIMER, PT);
29 | ADD8_OUT := ADD(TIMER, CYCLE);
30 | SEL3_OUT := SEL(GE7_OUT, TIMER, ADD8_OUT);
31 | SEL5_OUT := SEL(IN, SEL3_OUT, 0);
32 | SEL2_OUT := SEL(GE7_OUT, PT, TIMER);
33 | SEL6_OUT := SEL(IN, SEL2_OUT, 0);
34 | SEL1_OUT := SEL(GE7_OUT, true, false);
35 | SEL4_OUT := SEL(IN, SEL1_OUT, false);
36 | Q := SEL4_OUT;
37 | ET := SEL6_OUT;
38 | TIMERN := SEL5_OUT;
39 | TIMER := TIMERN;
40 | END_FUNCTION_BLOCK
--------------------------------------------------------------------------------
/plcrex/tools/st2qrz/call_st2qrz_compiler.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.st2qrz.pyd.st2qrz_compiler import *
20 | from plcrex.tools.misc.generic_functions import *
21 |
22 |
23 | def cli(
24 | source: Path,
25 | export: Path,
26 | ):
27 | print_header(
28 | ST2QRZ.__tool__,
29 | ST2QRZ.__version__,
30 | ST2QRZ.__author__
31 | )
32 | ST2QRZ().run(source, export)
33 | print_footer()
34 |
--------------------------------------------------------------------------------
/plcrex/tools/st2scl/call_st2scl_compiler.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.st2scl.pyd.st2scl_compiler import *
20 | from plcrex.tools.misc.generic_functions import *
21 |
22 |
23 | def cli(
24 | source: Path,
25 | export: Path,
26 | kicodia: Path,
27 | mode: str
28 | ):
29 | print_header(
30 | ST2SCL.__tool__,
31 | ST2SCL.__version__,
32 | ST2SCL.__author__
33 | )
34 | ST2SCL().run(source, export, kicodia, mode)
35 | print_footer()
36 |
--------------------------------------------------------------------------------
/plcrex/tools/tcgen/call_test_case_gen.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.tcgen.pyd.test_case_gen import *
20 | from plcrex.tools.misc.generic_functions import *
21 |
22 |
23 | def cli(
24 | formula: str,
25 | sc: bool,
26 | dc: bool,
27 | mcdc: bool,
28 | mcc: bool
29 | ):
30 | print_header(
31 | TestCaseGen.__tool__,
32 | TestCaseGen.__version__,
33 | TestCaseGen.__author__
34 | )
35 | TestCaseGen(formula, sc, dc, mcdc, mcc).create()
36 | print_footer()
37 |
--------------------------------------------------------------------------------
/tests/test_st2qrz.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 | from plcrex import cli
21 |
22 | runner = CliRunner()
23 |
24 |
25 | def test_help1():
26 | result = runner.invoke(cli.app, ["st-to-qrz", "--help"])
27 | assert result.exit_code == 0
28 |
29 | def test_tc01_22():
30 | for i in range(1, 22):
31 | if i != 3:
32 | result = runner.invoke(cli.app,
33 | ["st-to-qrz", fr"tests/st_to_synchr_models/TC{i:02}.st",
34 | fr"exports/TC{i:02}.qrz"])
35 | assert result.exit_code == 0
36 | assert f"Success!" in result.stdout
37 |
--------------------------------------------------------------------------------
/plcrex/data/grammars/DOTgrammar.lark:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // Start
3 | // ********************************************************************************
4 | start: digraph
5 |
6 | // ********************************************************************************
7 | // Header inlcuding POU name
8 | // ********************************************************************************
9 | name: NAME
10 | digraph: "digraph G {rankdir=LR;graph [pad=\"0.5\", nodesep=\"1\", ranksep=\"2\"]; splines=spline;node [shape=oval fillcolor=white style=filled];subgraph cluster_1{label=\"POU-Name:\n"name"\"; style=rounded;bgcolor=slategray1;fontsize = 30;" dependencies "}}"
11 |
12 | // ********************************************************************************
13 | // Header inlcuding POU name
14 | // ********************************************************************************
15 | dependencies: entry*
16 | entry: NAME "->" NAME ("," NAME)*
17 |
18 |
19 | // ********************************************************************************
20 | // Generic statements
21 | // ********************************************************************************
22 | %ignore " "
23 | MULTI_LINE_COMMENT: /\(\*.*?\*\)/s
24 | SINGLE_LINE_COMMENT: /\s*/ "//" /[^\n]/*
25 | %ignore WS
26 | %ignore MULTI_LINE_COMMENT
27 | %ignore SINGLE_LINE_COMMENT
28 | %import common.WS
29 | NAME: /[a-zA-Z_]\w*/
--------------------------------------------------------------------------------
/docs/source/install.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ============
3 |
4 | .. install:
5 |
6 | Prerequisites
7 | -------------
8 |
9 | * Python v3.9 [`.url `_]
10 | * Operating System: Windows
11 | * Microsoft Build Tools 2015 [`.url `_]
12 |
13 | PLCreX Installation via PyPI
14 | ----------------------------
15 | Run the following command to get the latest PLCreX from PyPI.org [`.url `_]
16 |
17 | .. code:: console
18 |
19 | pip install plcrex
20 |
21 | PLCreX Installation via GitHub
22 | ------------------------------
23 | 1. Download or clone PLCreX's GitHub repository [`.url `_]
24 | 2. Run the following batch script to automatically create a virtual environment (venv) and install dependencies
25 |
26 | .. code:: console
27 |
28 | install-windows.bat
29 |
30 | External tools called by PLCreX
31 | -------------------------------
32 | 1. IEC-Checker - Static analysis of IEC 61131-3 programs
33 | - Download v0.4 via GitHub [`.url `_]
34 | 2. NuSMV - Symbolic Model Checker
35 | - Download v2.6.0 via NuSMV's homepage [`.url `_]
36 | 3. Kicodia
37 | - Download v122798884 via KIELER's download page [`.url `_]
--------------------------------------------------------------------------------
/plcrex/tools/ieccheck/iec_checker.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.misc.generic_functions import *
20 | from pathlib import Path
21 | from subprocess import run
22 |
23 |
24 | class IECChecker:
25 | __version__ = "2.0.0"
26 | __author__ = "Marcel C. Werner"
27 | __tool__ = "IEC-Checker"
28 |
29 | def __init__(
30 | self,
31 | src: Path,
32 | exe: Path,
33 | option: str,
34 | dest: Path
35 | ):
36 | self.src = src
37 | self.exe = exe
38 | self.option = option
39 | self.dest = dest
40 |
41 | def run_checker(self):
42 | run([rf'{self.exe}', self.src, self.option], stdout=open(self.dest, 'w'))
43 | return
44 |
--------------------------------------------------------------------------------
/plcrex/tools/stp/call_st_parser.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.stp.st_parser import *
20 | from pathlib import Path
21 | import os
22 |
23 |
24 | def cli(source: Path, export: Path, filename: str, txt: bool, dot: bool, beckhoff: bool):
25 | print_header(
26 | STParser.__tool__,
27 | STParser.__version__,
28 | STParser.__author__
29 | )
30 | if source.is_file() and source.suffix == '.st':
31 | dir_path = Path(fr'{export}\PLCreX_outputs')
32 | # Ensure the directory exists
33 | os.makedirs(dir_path, exist_ok=True)
34 | STParser(source, dir_path, filename, txt, dot, beckhoff).translate()
35 | else:
36 | raise RuntimeError("no ST file found")
37 | print_footer()
38 |
--------------------------------------------------------------------------------
/tests/test_fbdia.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 | def test_help():
26 | result = runner.invoke(cli.app, ["impact-analysis", "--help"])
27 | assert result.exit_code == 0
28 |
29 |
30 | def test_wrong_file():
31 | result = runner.invoke(cli.app, ["impact-analysis", r".\tests\other_examples\TC001_wrong_file.txt", r".\exports\st2ia1"])
32 | assert result.exit_code == 1
33 |
34 | #test_bwd_noformal_io_analysis
35 | def test_bwd_noformal_io_analysis():
36 | result = runner.invoke(cli.app, ["impact-analysis", r".\tests\plcopen_examples\TC006_FBD.xml", r".\exports\st2ia2"])
37 | assert result.exit_code == 0
38 | assert f"Success!" in result.stdout
39 |
--------------------------------------------------------------------------------
/plcrex/tools/fbd2st/call_fbd2st_compiler.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.fbd2st.pyd.fbd2st_compiler import *
20 | from plcrex.tools.misc.generic_functions import *
21 | from pathlib import Path
22 | import os
23 |
24 | def cli(source:Path, export:Path, filename:str, bwd:bool, formal:bool):
25 | print_header(
26 | FBD2ST.__tool__,
27 | FBD2ST.__version__,
28 | FBD2ST.__author__
29 | )
30 | if source.is_file() and source.suffix == '.xml':
31 | dir_path = Path(fr'{export}\PLCreX_outputs')
32 | # Ensure the directory exists
33 | os.makedirs(dir_path, exist_ok=True)
34 | FBD2ST(source, dir_path, filename, bwd, formal).translate()
35 | else:
36 | raise RuntimeError("no xml file found")
37 | print_footer()
38 |
--------------------------------------------------------------------------------
/docs/source/publications.rst:
--------------------------------------------------------------------------------
1 | Publications
2 | ============
3 |
4 | .. publications:
5 |
6 | - M.C. Werner and K. Schneider, *From Imperative Sequential Structured Text Models to Synchronous Quartz and Sequentially Constructive Models*, Methoden und Beschreibungssprachen zur Modellierung und Verifikation von Schaltungen und Systemen (MBMV), 2024
7 |
8 | .. |1| unicode:: U+0020
9 |
10 | - M.C. Werner and K. Schneider, *PLCreX -- Open-Source Project for Simplification, Transformation, Analysis, and Validation of Programmable Logic Controllers*, Methoden und Beschreibungssprachen zur Modellierung und Verifikation von Schaltungen und Systemen (MBMV), 2024
11 |
12 | .. |2| unicode:: U+0020
13 |
14 | - M.C. Werner and K. Schneider, *Formal Methods-based Optimization of Dataflow Models with Translation to Synchronous Models*, Forum on Specification and Design Languages (FDL), 2023
15 |
16 | .. |3| unicode:: U+0020
17 |
18 | - M.C. Werner and K. Schneider, *From IEC 61131-3 Function Block Diagrams to Sequentially Constructive Statecharts*, Forum on Specification and Design Languages (FDL), 2022
19 |
20 | .. |4| unicode:: U+0020
21 |
22 | - M.C. Werner and K. Schneider, *Translation of Continuous Function Charts to Imperative Synchronous Quartz Programs*, Formal Methods and Models for Codesign (MEMOCODE), 2021
23 |
24 | .. |5| unicode:: U+0020
25 |
26 | - M.C. Werner and K. Schneider, *Reengineering Programmable Logic Controllers Using Synchronous Programming Languages*, Forum on Specification and Design Languages (FDL), 2020
27 |
28 | .. |6| unicode:: U+0020
--------------------------------------------------------------------------------
/plcrex/tools/xmlval/call_xml_validator.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.xmlval.xml_validator import *
20 | from pathlib import Path
21 | from plcrex.tools.misc.generic_functions import *
22 |
23 |
24 | def cli(source: Path, v201: bool):
25 | print_header(
26 | XMLValidation.__tool__,
27 | XMLValidation.__version__,
28 | XMLValidation.__author__
29 | )
30 | if source.is_file() and source.suffix == '.xml':
31 | if v201:
32 | # tc6_xml_v201.xsd (https: // plcopen.org / downloads / plcopen-xml-version-201-xsd-file-0)
33 | XMLValidation(source, "tc6_xml_v201.xsd").validate()
34 | else:
35 | # tc6_xml_v10.xsd (Beremiz v1.2)
36 | XMLValidation(source, "tc6_xml_v10.xsd").validate()
37 | else:
38 | raise RuntimeError("no xml file found")
39 | print_footer()
40 |
--------------------------------------------------------------------------------
/plcrex/tools/xmlval/xml_validator.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from pathlib import Path
20 | from plcrex.tools.misc.generic_functions import *
21 | import xmlschema
22 |
23 |
24 | class XMLValidation:
25 | __version__ = "2.0.0"
26 | __author__ = "Marcel C. Werner"
27 | __tool__ = "XML-Validator"
28 |
29 | def __init__(self,
30 | xml_file: Path,
31 | validation_file: str
32 | ):
33 | self.xml_file = xml_file
34 | self.validation_file = validation_file
35 | #logging.debug(
36 | # f"Module: {self.__tool__}, Version: {self.__version__}, Author: {self.__author__}")
37 |
38 |
39 |
40 | def validate(self):
41 | xsd_file = get_file(fr'plcrex\data\tc6\{self.validation_file}')
42 |
43 | # create validation scheme
44 | scheme = xmlschema.XMLSchema(xsd_file)
45 |
46 | # validate PLCopen xml file
47 | scheme.validate(self.xml_file)
48 |
--------------------------------------------------------------------------------
/tests/test_tcgen.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_help():
27 | result = runner.invoke(cli.app, ["test-case-gen", "--help"])
28 | assert result.exit_code == 0
29 |
30 |
31 | def test_ds2ts_001():
32 | result = runner.invoke(cli.app, ["test-case-gen", "a&b"])
33 | assert result.exit_code == 0
34 | assert f"Success!" in result.stdout
35 |
36 | def test_ds2ts_002():
37 | result = runner.invoke(cli.app, ["test-case-gen", "--sc", "a&b"])
38 | assert result.exit_code == 0
39 | assert f"Success!" in result.stdout
40 |
41 | def test_ds2ts_003():
42 | result = runner.invoke(cli.app, ["test-case-gen", "--mcdc", "a&b"])
43 | assert result.exit_code == 0
44 | assert f"Success!" in result.stdout
45 |
46 | def test_ds2ts_004():
47 | result = runner.invoke(cli.app, ["test-case-gen", "--mcc", "a&b"])
48 | assert result.exit_code == 0
49 | assert f"Success!" in result.stdout
--------------------------------------------------------------------------------
/plcrex/tools/fbdia/call_io_analysis.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.fbdia.pyd.io_analysis import *
20 | from plcrex.tools.fbd2st import call_fbd2st_compiler
21 | from pathlib import Path
22 | from plcrex.tools.misc.generic_functions import *
23 | import os
24 |
25 | def cli(source: Path, export: Path, filename: str):
26 | print_header(
27 | IOAnalysis.__tool__,
28 | IOAnalysis.__version__,
29 | IOAnalysis.__author__
30 | )
31 | if source.is_file() and source.suffix == '.xml':
32 | dir_path = Path(fr'{export}\PLCreX_outputs')
33 | # Ensure the directory exists
34 | os.makedirs(dir_path, exist_ok=True)
35 |
36 | # 1. FBD-to-ST, backward + no-formal
37 | call_fbd2st_compiler.cli(source, export, filename, True, False)
38 |
39 | # 2. ST-to-I/O Dependency
40 | IOAnalysis(Path(fr'{dir_path}\{filename}.st'), dir_path, filename).data_flow_analysis_st()
41 | else:
42 | raise RuntimeError("no xml file found")
43 | print_footer()
44 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=61.0", "wheel"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [project]
6 | name = "plcrex"
7 | version = "2.0.0"
8 | requires-python = ">=3.9"
9 | authors = [
10 | { name="Marcel C. Werner", email="plcrex.info@gmail.com" },
11 | ]
12 | description = "PLCreX - Simplification, Transformation, Analysis, and Validation of IEC 61131-3 Programmable Logic Controllers"
13 | readme = "README.md"
14 | classifiers = [
15 | "Programming Language :: Python :: 3.9",
16 | "Operating System :: Microsoft :: Windows",
17 | ]
18 | license = {file = "LICENSE"}
19 | keywords = ["PLC", "SPS", "IEC-61131", "FBD", "ST", "testing", "development", "verification"]
20 | dependencies = [
21 | "attrs==23.1.0",
22 | "click==8.1.6",
23 | "colorama==0.4.5",
24 | "coverage==6.5.0",
25 | "coverage-badge==1.1.0",
26 | "dd==0.5.7",
27 | "dicttoxml2==2.1.0",
28 | "elementpath==3.0.2",
29 | "exceptiongroup==1.2.0",
30 | "iniconfig==2.0.0",
31 | "lark==1.1.7",
32 | "markdown-it-py==3.0.0",
33 | "mdurl==0.1.2",
34 | "packaging==23.2",
35 | "pluggy==1.3.0",
36 | "pydot==1.4.2",
37 | "pyeda==0.29.0",
38 | "Pygments==2.17.2",
39 | "pyparsing==3.1.1",
40 | "pytest==7.2.0",
41 | "rich==13.5.1",
42 | "termcolor==2.3.0",
43 | "tomli==2.0.1",
44 | "typer==0.9.0",
45 | "typing_extensions==4.8.0",
46 | "xmlschema==2.1.1",
47 | "z3-solver==4.12.2.0",
48 | ]
49 |
50 | [tool.setuptools]
51 | #packages = ["plcrex"]
52 | include-package-data = true
53 |
54 | [tool.setuptools.packages]
55 | find = {} # Scan the project directory with the default parameters
56 |
57 | [project.urls]
58 | "Homepage" = "https://github.com/marwern/PLCreX"
59 | "Bug Tracker" = "https://github.com/marwern/PLCreX/issues"
60 |
--------------------------------------------------------------------------------
/tests/test_xmlval.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_help():
27 | result = runner.invoke(cli.app, ["xml-validator", "--help"])
28 | assert result.exit_code == 0
29 |
30 |
31 | def test_v201_passed():
32 | result = runner.invoke(cli.app, ["xml-validator", "--v201", r".\tests\plcopen_examples\TC001.xml"])
33 | assert result.exit_code == 0
34 | assert f"Success!" in result.stdout
35 |
36 |
37 | def test_v201_failed():
38 | result = runner.invoke(cli.app, ["xml-validator", "--v201", r".\tests\plcopen_examples\TC001_failed.xml"])
39 | assert result.exit_code == 1
40 |
41 | #TODO
42 | #def test_v10_passed():
43 |
44 | def test_v10_failed():
45 | result = runner.invoke(cli.app, ["xml-validator", r".\tests\plcopen_examples\TC001.xml"])
46 | assert result.exit_code == 1
47 |
48 |
49 | def test_wrong_file():
50 | result = runner.invoke(cli.app, ["xml-validator", r".\tests\other_examples\TC001_wrong_file.txt"])
51 | assert result.exit_code == 1
52 |
--------------------------------------------------------------------------------
/tests/test_version.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 | from plcrex import cli
21 | from plcrex import __app_name__, __version__
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_version_1():
27 | result = runner.invoke(cli.app, ["--version"])
28 | assert result.exit_code == 0
29 | assert fr"""
30 | PLCreX-{__version__}, plcrex.info@gmail.com
31 |
32 | Copyright (c) 2022-2024 Marcel C. Werner.
33 |
34 | This program is free software: you can redistribute it and/or modify
35 | it under the terms of the GNU General Public License as published by
36 | the Free Software Foundation, version 3.
37 |
38 | This program is distributed in the hope that it will be useful, but
39 | WITHOUT ANY WARRANTY; without even the implied warranty of
40 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 | General Public License for more details.
42 |
43 | You should have received a copy of the GNU General Public License
44 | along with this program. If not, see .
45 | """ in result.stdout
46 |
--------------------------------------------------------------------------------
/tests/test_st2scl.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 | from plcrex import cli
21 |
22 | runner = CliRunner()
23 |
24 |
25 | def test_help1():
26 | result = runner.invoke(cli.app, ["st-to-scl", "--help"])
27 | assert result.exit_code == 0
28 |
29 | def test_help2():
30 | result = runner.invoke(cli.app, ["st-to-sctx", "--help"])
31 | assert result.exit_code == 0
32 |
33 | def test_tc01_22_scl():
34 | for i in range(1, 22):
35 | if i != 3:
36 | result = runner.invoke(cli.app,
37 | ["st-to-scl", fr"tests/st_to_synchr_models/TC{i:02}.st",
38 | fr"exports/TC{i:02}.scl"])
39 | assert result.exit_code == 0
40 | assert f"Success!" in result.stdout
41 |
42 | def test_tc01_22_sctx():
43 | for i in range(1, 22):
44 | if i != 3:
45 | result = runner.invoke(cli.app,
46 | ["st-to-sctx", fr"tests/st_to_synchr_models/TC{i:02}.st",
47 | fr"exports/TC{i:02}.sctx", r".\bin\kicodia-win.bat"])
48 | assert result.exit_code == 0
49 | assert f"Success!" in result.stdout
50 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | PLCreX - Simplification, Transformation, Analysis, and Validation of IEC 61131-3 Programmable Logic Controllers
2 | ===============================================================================================================
3 |
4 | .. index:
5 |
6 | About PLCreX
7 | ------------
8 |
9 | PLCreX is a modular command-line interface application tailored for IEC 61131-3 Programmable Logic Controllers (PLCs) and beyond. It's designed with a focus on issues such as review, redesign, reuse, and reliability, among others. This project is driven by our ongoing research and we're committed to progressively integrating new features. PLCreX serves as a comprehensive suite of analysis and reuse capabilities for existing IEC 61131-3 Program Organization Units (POUs) implemented in Function Block Diagrams (FBDs) or Structured Text (ST).
10 |
11 | .. figure:: ../fig/overview.svg
12 | :align: center
13 |
14 | |
15 |
16 |
17 | ..
18 | .. toctree::
19 | :glob:
20 | :titlesonly:
21 |
22 | *
23 |
24 | .. toctree::
25 | :maxdepth: 2
26 | :caption: Getting Started
27 | :hidden:
28 |
29 | install
30 | test
31 |
32 | .. toctree::
33 | :maxdepth: 2
34 | :caption: Usage
35 | :hidden:
36 |
37 | cli
38 |
39 | .. toctree::
40 | :maxdepth: 2
41 | :caption: Validation
42 | :hidden:
43 |
44 | xml_validator
45 |
46 | .. toctree::
47 | :maxdepth: 2
48 | :caption: Analysis
49 | :hidden:
50 |
51 | iec_checker
52 | impact_analysis
53 | st_parser
54 | test_case_gen
55 |
56 | .. toctree::
57 | :maxdepth: 2
58 | :caption: Transformation & Simplification
59 | :hidden:
60 |
61 | fbd_to_st
62 | fbd_to_st_ext
63 | fbd_to_sctx
64 | st_to_qrz
65 | st_to_scl
66 | st_to_sctx
67 |
68 | .. toctree::
69 | :maxdepth: 2
70 | :caption: Additional Resources
71 | :hidden:
72 |
73 | publications
74 |
75 | contact
--------------------------------------------------------------------------------
/plcrex/tools/fbd2x/call_fbd_optimizer.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.fbd2x.pyd.fbd_optimizer import *
20 | from plcrex.tools.fbd2st.pyd.fbd2st_compiler import *
21 | from plcrex.tools.misc.generic_functions import *
22 | from pathlib import Path
23 | import os
24 |
25 |
26 | def cli(
27 | source: Path,
28 | export: Path,
29 | filename: str,
30 | exe: Path,
31 | edge_opt: bool,
32 | var_opt: bool,
33 | op_opt: bool,
34 | target_format: str
35 | ):
36 | print_header(
37 | FBDOptimizer.__tool__,
38 | FBDOptimizer.__version__,
39 | FBDOptimizer.__author__
40 | )
41 | if source.is_file() and source.suffix == '.xml':
42 | dir_path = Path(fr'{export}\PLCreX_outputs')
43 | # Ensure the directory exists
44 | os.makedirs(dir_path, exist_ok=True)
45 |
46 | # 1. FBD-to-ST Translation (backward + formal)
47 | FBD2ST(source, dir_path, filename, True, True).translate()
48 |
49 | # 2. ST-to-X Translation
50 | FBDOptimizer(Path(fr'{dir_path}\{filename}.st'),
51 | dir_path, filename, exe,
52 | edge_opt, var_opt, op_opt, edge_opt or var_opt or op_opt, target_format).translate()
53 |
54 | else:
55 | raise RuntimeError("no xml file found")
56 | print_footer()
57 |
--------------------------------------------------------------------------------
/tests/test_stp.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_help():
27 | result = runner.invoke(cli.app, ["st-parser", "--help"])
28 | assert result.exit_code == 0
29 |
30 |
31 | def test_dot_txt():
32 | result = runner.invoke(cli.app, ["st-parser", r".\tests\st_examples\TC081.st", r".\exports\st2ast1"])
33 | assert result.exit_code == 0
34 | assert f"Success!" in result.stdout
35 |
36 |
37 | def test_dot():
38 | result = runner.invoke(cli.app, ["st-parser", r".\tests\st_examples\TC081.st", r".\exports\st2ast2", "--no-txt"])
39 | assert result.exit_code == 0
40 | assert f"Success!" in result.stdout
41 |
42 |
43 | def test_txt():
44 | result = runner.invoke(cli.app, ["st-parser", r".\tests\st_examples\TC081.st", r".\exports\st2ast3", "--no-dot"])
45 | assert result.exit_code == 0
46 | assert f"Success!" in result.stdout
47 |
48 | def test_beckhoff_txt_dot():
49 | result = runner.invoke(cli.app, ["st-parser", r".\tests\st_examples\TC079.st", r".\exports\st2ast4", "--beckhoff"])
50 | assert result.exit_code == 0
51 | assert f"Success!" in result.stdout
52 |
53 | def test_wrong_file():
54 | result = runner.invoke(cli.app, ["st-parser", r".\tests\other_examples\TC001_wrong_file.txt", r".\exports\st2ast5"])
55 | assert result.exit_code == 1
56 |
--------------------------------------------------------------------------------
/plcrex/tools/ieccheck/call_iec_checker.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from plcrex.tools.misc.generic_functions import *
20 | from plcrex.tools.ieccheck.iec_checker import *
21 | from pathlib import Path
22 | import os
23 |
24 |
25 | def cli(source: Path, exe: Path, verbose: bool, export: Path, filename: str, help_: bool):
26 | print_header(
27 | IECChecker.__tool__,
28 | IECChecker.__version__,
29 | IECChecker.__author__
30 | )
31 | if source.is_file():
32 | if exe.is_file():
33 | dir_path = Path(fr'{export}\PLCreX_outputs')
34 | # Ensure the directory exists
35 | os.makedirs(dir_path, exist_ok=True)
36 | dest = Path(fr'{dir_path}\{filename}.log')
37 | if source.is_file() and (source.suffix == '.st' or source.suffix == '.xml'):
38 | # call iec-checker with ONE supported OPTIONS (only a subset is covered)
39 | if help_:
40 | IECChecker(source, exe, '--help', dest).run_checker()
41 | elif not verbose:
42 | IECChecker(source, exe, '--quiet', dest).run_checker()
43 | elif verbose:
44 | IECChecker(source, exe, '--verbose', dest).run_checker()
45 | with open(dest, 'rt') as file:
46 | print(file.read())
47 | file.close()
48 | else:
49 | raise RuntimeError("no ST/xml file found")
50 | else:
51 | raise RuntimeError(rf"no .exe found at {exe}")
52 | print_footer()
53 |
--------------------------------------------------------------------------------
/plcrex/tools/stp/st_parser.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from lark import Lark, tree
20 | from pathlib import Path
21 | from plcrex.tools.misc.generic_functions import *
22 |
23 | class STParser:
24 | __version__ = "2.0.0"
25 | __author__ = "Marcel C. Werner"
26 | __tool__ = "ST-Parser"
27 |
28 | def __init__(
29 | self,
30 | src: Path,
31 | dir_path: Path,
32 | filename: str,
33 | txt: bool = False,
34 | dot: bool = False,
35 | beckhoff: bool = False
36 | ):
37 | self.src = src
38 | self.dir_path = dir_path
39 | self.filename = filename
40 | self.txt = txt
41 | self.dot = dot
42 | self.beckhoff = beckhoff
43 |
44 | def read_src(self, src_dir: Path):
45 | f = open(src_dir, 'rt')
46 | src_txt = f.read()
47 | f.close()
48 | return src_txt
49 |
50 | def translate(self):
51 |
52 | if self.beckhoff:
53 | grammar = get_file(r'plcrex\data\grammars\STgrammar_Beckhoff.lark')
54 | else:
55 | grammar = get_file(r'plcrex\data\grammars\STgrammar.lark')
56 |
57 | parser = Lark(grammar, maybe_placeholders=False, keep_all_tokens=False)
58 | source = self.read_src(self.src)
59 |
60 | # write (pretty) tree as .txt
61 | if self.txt:
62 | txt_export = open(fr'{self.dir_path}\{self.filename}.txt', "w")
63 | txt_export.write(str(parser.parse(source).pretty()))
64 | txt_export.close()
65 |
66 | # write tree as .dot file
67 | if self.dot:
68 | tree.pydot__tree_to_dot(parser.parse(source), fr'{self.dir_path}\{self.filename}.dot')
69 |
--------------------------------------------------------------------------------
/docs/source/impact_analysis.rst:
--------------------------------------------------------------------------------
1 | I/O-Impact Analysis
2 | ===================
3 |
4 | .. impact_analysis:
5 |
6 | The I/O-Impact Analysis feature identifies the dependencies between POU outputs and inputs.
7 |
8 | **Usage**
9 |
10 | .. code-block:: console
11 |
12 | python -m plcrex impact-analysis --help
13 |
14 |
15 | .. code:: console
16 |
17 | Usage: plcrex impact-analysis [OPTIONS] SOURCE EXPORT
18 |
19 | I/O-Impact Analysis *.xml → *.dot
20 |
21 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
22 | │ * source PATH source path [default: None] [required] │
23 | │ * export PATH export path [default: None] [required] │
24 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
25 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
26 | │ --help Show this message and exit. │
27 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
28 |
29 |
30 | ..
31 | .. figure:: ../fig/impact_analysis_demo.png
32 | :align: center
33 | :width: 600px
34 |
35 | |
36 |
37 | POU ``TC006_FBD.xml``
38 | ---------------------
39 |
40 | The following POU was manually implemented using Beremiz [`.url `_].
41 |
42 | .. figure:: ../fig/TC006.png
43 | :align: center
44 | :width: 450px
45 |
46 | |
47 |
48 | Example 1
49 | ---------
50 |
51 | **Command**
52 |
53 | .. code-block:: console
54 |
55 | python -m plcrex impact-analysis ".\tests\plcopen_examples\TC006_FBD.xml" ".\exports\01"
56 |
57 | **Results**
58 |
59 | ``01.dot``
60 |
61 | .. code-block:: console
62 |
63 | ...
64 | digraph G {
65 | rankdir=LR;
66 | graph [pad="0.5", nodesep="1", ranksep="2"];
67 | splines=spline;
68 | node [shape=oval fillcolor=white style=filled];
69 | subgraph cluster_1{
70 | label="POU-Name:\nTC006";
71 | style=rounded;bgcolor=slategray1;fontsize = 30;
72 | i1->o1 i2->o1 i1->o2 i2->o3 i1->o3 i3->o4
73 | }
74 | }
75 | ...
76 |
77 | .. figure:: ../fig/TC006_result.png
78 | :align: center
79 | :width: 300px
80 |
81 | |
--------------------------------------------------------------------------------
/docs/source/st_to_qrz.rst:
--------------------------------------------------------------------------------
1 | ST-to-Quartz Compiler
2 | =====================
3 |
4 | .. st_to_qrz:
5 |
6 | The ST-to-Quartz Compiler translates imperative sequential ST models to imperative synchronous Quartz models.
7 | The results are intended for reuse in model-based design and formal verification using `Averest `_ [1,2].
8 |
9 | **Usage**
10 |
11 | .. code-block:: console
12 |
13 | python -m plcrex st-to-qrz --help
14 |
15 |
16 | .. code:: console
17 |
18 | Usage: plcrex st-to-qrz [OPTIONS] SOURCE EXPORT
19 |
20 | ST-to-Quartz Compiler *.st → *.qrz
21 |
22 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
23 | │ * source PATH source path [default: None] [required] │
24 | │ * export PATH export path [default: None] [required] │
25 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
26 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
27 | │ --help Show this message and exit. │
28 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
29 |
30 | |
31 |
32 | Example: ``REPEAT-UNTIL`` loop
33 | ------------------------------------------
34 |
35 | The following POU was manually implemented using Beremiz [`.url `_].
36 |
37 | .. code-block:: console
38 |
39 | FUNCTION_BLOCK TC21
40 | VAR_OUTPUT
41 | y : INT;
42 | END_VAR
43 | VAR
44 | x : INT := 1;
45 | i : INT;
46 | i0 : INT := 0;
47 | i1 : INT := 10;
48 | END_VAR
49 |
50 | i:=i0;
51 | REPEAT
52 | y := i;
53 | i := i+1;
54 | UNTIL i>i1
55 | END_REPEAT;
56 | y := x;
57 | END_FUNCTION_BLOCK
58 |
59 | |
60 |
61 |
62 | **Command**
63 |
64 | .. code-block:: console
65 |
66 | python -m plcrex st-to-qrz "tests/st_to_synchr_models/TC21.st" "exports/TC21.qrz"
67 |
68 | **Result**
69 |
70 | ``TC21.qrz``
71 |
72 | .. code-block:: console
73 |
74 | //--- This file was generated by PLCreX ---
75 | //--- https://github.com/marwern/PLCreX ---
76 | //-----------------------------------------
77 |
78 | module TC21(int !y){
79 | int x;
80 | int i;
81 | int i0;
82 | int i1;
83 | x=1;
84 | i0=0;
85 | i1=10;
86 | i=i0;
87 | do{
88 | y=i;
89 | next(i)=i+1;
90 | pause;
91 | }while(!(i>i1));
92 | y=x;
93 | }
94 |
--------------------------------------------------------------------------------
/docs/source/st_to_scl.rst:
--------------------------------------------------------------------------------
1 | ST-to-SCL Compiler
2 | ==================
3 |
4 | .. st_to_scl:
5 |
6 | The ST-to-SCL Compiler translates imperative sequential ST models to Sequentially Constructive Language (SCL) models.
7 | The results are intended for reuse in model-based design and formal verification using `KIELER `_ [1,2].
9 |
10 | **Usage**
11 |
12 | .. code-block:: console
13 |
14 | python -m plcrex st-to-scl --help
15 |
16 |
17 | .. code:: console
18 |
19 | Usage: plcrex st-to-scl [OPTIONS] SOURCE EXPORT
20 |
21 | ST-to-SCL Compiler *.st → *.scl
22 |
23 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
24 | │ * source PATH source path [default: None] [required] │
25 | │ * export PATH export path [default: None] [required] │
26 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
27 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
28 | │ --help Show this message and exit. │
29 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
30 |
31 | |
32 |
33 | Example: ``REPEAT-UNTIL`` loop
34 | ------------------------------------------
35 |
36 | The following POU was manually implemented using Beremiz [`.url `_].
37 |
38 | .. code-block:: console
39 |
40 | FUNCTION_BLOCK TC21
41 | VAR_OUTPUT
42 | y : INT;
43 | END_VAR
44 | VAR
45 | x : INT := 1;
46 | i : INT;
47 | i0 : INT := 0;
48 | i1 : INT := 10;
49 | END_VAR
50 |
51 | i:=i0;
52 | REPEAT
53 | y := i;
54 | i := i+1;
55 | UNTIL i>i1
56 | END_REPEAT;
57 | y := x;
58 | END_FUNCTION_BLOCK
59 |
60 | |
61 |
62 |
63 | **Command**
64 |
65 | .. code-block:: console
66 |
67 | python -m plcrex st-to-scl "tests/st_to_synchr_models/TC21.st" "exports/TC21.scl"
68 |
69 | **Result**
70 |
71 | ``TC21.scl``
72 |
73 | .. code-block:: console
74 |
75 | //--- This file was generated by PLCreX ---
76 | //--- https://github.com/marwern/PLCreX ---
77 | //-----------------------------------------
78 |
79 | module TC21{
80 | output int y;
81 | int x=1;
82 | int i;
83 | int i0=0;
84 | int i1=10;
85 | i=i0;
86 | do:
87 | y=i;
88 | pause;
89 | i=i+1;
90 | if(!(i>i1)){
91 | goto do;
92 | }else{
93 | y=x;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/docs/source/xml_validator.rst:
--------------------------------------------------------------------------------
1 | XML-Validator
2 | =============
3 |
4 | .. xml_validator:
5 |
6 | The PLCopen XML-Validator feature uses ``tc6_xml_v201.xsd`` and ``tc6_xml_v10.xsd`` to validate that the PLCopen XML exchange format conforms to the PLCopen specification [`.url `_].
7 |
8 |
9 | **Usage**
10 |
11 | .. code-block:: console
12 |
13 | python -m plcrex xml-validator --help
14 |
15 | .. code:: console
16 |
17 | Usage: plcrex xml-validator [OPTIONS] SOURCE
18 |
19 | XML-Validator *.xml → stdout
20 |
21 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
22 | │ * source PATH source path [default: None] [required] │
23 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
24 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
25 | │ --v201 --no-v201 use tc6_xml_v201.xsd [default: no-v201] │
26 | │ --help Show this message and exit. │
27 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
28 |
29 |
30 | ..
31 | .. figure:: ../fig/xml_validator_demo.png
32 | :align: center
33 | :width: 600px
34 |
35 | |
36 |
37 | Example 1: ``--v201`` (PASSED)
38 | ------------------------------
39 |
40 | **Command**
41 |
42 | .. code-block:: console
43 |
44 | python -m plcrex xml-validator --v201 ".\tests\plcopen_examples\TC001.xml"
45 |
46 |
47 | **Results**
48 |
49 | .. code-block:: console
50 |
51 | Success!
52 |
53 |
54 | Example 2: ``--v201`` (FAILED)
55 | ------------------------------
56 |
57 | **Command**
58 |
59 | .. code-block:: console
60 |
61 | python -m plcrex xml-validator --v201 ".\tests\plcopen_examples\TC001_failed.xml"
62 |
63 |
64 | **Results**
65 |
66 | .. code-block:: console
67 |
68 | ...
69 | XMLSchemaDecodeError: failed validating '2022-09-01 14:53:16' with
70 | XsdAtomicBuiltin(name='xs:dateTime'):
71 |
72 | Reason: attribute modificationDateTime='2022-09-01 14:53:16': Invalid datetime string '2022-09-01
73 | 14:53:16' for
74 |
75 | Schema:
76 |
77 |
79 |
80 |
81 |
82 | ...
--------------------------------------------------------------------------------
/tests/test_ieccheck.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_help():
27 | result = runner.invoke(cli.app, ["iec-check", "--help"])
28 | assert result.exit_code == 0
29 |
30 |
31 | def test_help_iec_checker():
32 | result = runner.invoke(cli.app, ["iec-check", r".\tests\st_examples\TC001.st", r".\bin\iec_checker_Windows_x86_64_v0.4.exe", "--help_iec_checker", r".\exports\iec_checker1"])
33 | assert result.exit_code == 0
34 | assert f"Success!" in result.stdout
35 |
36 |
37 | def test_verbose_st():
38 | result = runner.invoke(cli.app, ["iec-check", r".\tests\st_examples\TC001.st", r".\bin\iec_checker_Windows_x86_64_v0.4.exe", "--verbose", r".\exports\iec_checker2"])
39 | assert result.exit_code == 0
40 | assert f"Success!" in result.stdout
41 |
42 |
43 | def test_quiet_st():
44 | result = runner.invoke(cli.app, ["iec-check", r".\tests\st_examples\TC001.st", r".\bin\iec_checker_Windows_x86_64_v0.4.exe", r".\exports\iec_checker3"])
45 | assert result.exit_code == 0
46 | assert f"Success!" in result.stdout
47 |
48 |
49 | def test_wrong_file():
50 | result = runner.invoke(cli.app, ["iec-check", r".\tests\other_examples\TC001_wrong_file.txt", r".\bin\iec_checker_Windows_x86_64_v0.4.exe", r".\exports\iec_checker4"])
51 | assert result.exit_code == 1
52 |
53 |
54 | def test_verbose_xml():
55 | result = runner.invoke(cli.app, ["iec-check", r".\tests\plcopen_examples\TC001.xml", r".\bin\iec_checker_Windows_x86_64_v0.4.exe", "--verbose", r".\exports\iec_checker5"])
56 | assert result.exit_code == 0
57 | assert f"Success!" in result.stdout
58 |
59 |
60 | def test_quiet_xml():
61 | result = runner.invoke(cli.app, ["iec-check", r".\tests\plcopen_examples\TC001.xml", r".\bin\iec_checker_Windows_x86_64_v0.4.exe", r".\exports\iec_checker6"])
62 | assert result.exit_code == 0
63 | assert f"Success!" in result.stdout
64 |
65 | def test_wrong_exe():
66 | result = runner.invoke(cli.app, ["iec-check", r".\tests\plcopen_examples\TC001.xml", r".\bin\_.exe", r".\exports\iec_checker7"])
67 | assert result.exit_code == 1
68 |
--------------------------------------------------------------------------------
/docs/source/cli.rst:
--------------------------------------------------------------------------------
1 | Command Line Interface
2 | ======================
3 |
4 | .. cli:
5 |
6 |
7 | .. code:: console
8 |
9 | Usage: plcrex [OPTIONS] COMMAND [ARGS]...
10 |
11 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
12 | │ --version │
13 | │ --install-completion [bash|zsh|fish|powershell|pwsh] Install completion for the │
14 | │ specified shell. │
15 | │ [default: None] │
16 | │ --show-completion [bash|zsh|fish|powershell|pwsh] Show completion for the │
17 | │ specified shell, to copy it or │
18 | │ customize the installation. │
19 | │ [default: None] │
20 | │ --help Show this message and exit. │
21 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
22 | ╭─ Commands ───────────────────────────────────────────────────────────────────────────────────╮
23 | │ fbd-to-sctx FBD-to-SCCharts Compiler (Data-Flow) *.xml → *.sctx │
24 | │ fbd-to-st FBD-to-ST Compiler *.xml → *.st │
25 | │ fbd-to-st-ext FBD-to-ST Compiler (extended) *.xml → *.st │
26 | │ iec-check IEC-Checker *.st → *.log │
27 | │ impact-analysis I/O-Impact Analysis *.xml → *.dot │
28 | │ st-parser ST-Parser *.st → *.dot/*.txt │
29 | │ st-to-qrz ST-to-Quartz Compiler *.st → *.qrz │
30 | │ st-to-scl ST-to-SCL Compiler *.st → *.scl │
31 | │ st-to-sctx ST-to-SCCharts Compiler (Control-Flow) *.st → *.sctx │
32 | │ test-case-gen Test-Case-Generator stdin → stdout │
33 | │ xml-validator XML-Validator *.xml → stdout │
34 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
35 |
36 |
37 | |
38 |
39 | Installed via PyPI
40 | ------------------
41 |
42 | 1. Run the following command to call PLCreX's help
43 |
44 | .. code:: console
45 |
46 | python -m plcrex --help
47 |
48 | Installed via GitHub
49 | --------------------
50 |
51 | 1. Run the following command to activate virtual environment (venv)
52 |
53 | .. code:: console
54 |
55 | run.bat
56 |
57 | 2. Run the following command to call PLCreX's help
58 |
59 | .. code-block:: console
60 |
61 | python -m plcrex --help
--------------------------------------------------------------------------------
/docs/source/st_to_sctx.rst:
--------------------------------------------------------------------------------
1 | ST-to-SCCharts Compiler
2 | =======================
3 |
4 | .. st_to_sctx:
5 |
6 | The ST-to-SCCharts Compiler translates imperative sequential ST models to Sequentially Constructive Statecharts (SCCharts).
7 | The results are intended for reuse in model-based design and formal verification using `KIELER `_ [1,2].
9 |
10 | **Usage**
11 |
12 | .. code-block:: console
13 |
14 | python -m plcrex st-to-sctx --help
15 |
16 |
17 | .. code:: console
18 |
19 | Usage: plcrex st-to-sctx [OPTIONS] SOURCE EXPORT BAT_DIR
20 |
21 | ST-to-SCCharts Compiler (Control-Flow) *.st → *.sctx
22 |
23 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
24 | │ * source PATH source path [default: None] [required] │
25 | │ * export PATH export path [default: None] [required] │
26 | │ * bat_dir PATH kicodia-win.bat path [default: None] [required] │
27 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
28 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
29 | │ --help Show this message and exit. │
30 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
31 |
32 | |
33 |
34 | Example: ``REPEAT-UNTIL`` loop
35 | ------------------------------------------
36 |
37 | The following POU was manually implemented using Beremiz [`.url `_].
38 |
39 | .. code-block:: console
40 |
41 | FUNCTION_BLOCK TC21
42 | VAR_OUTPUT
43 | y : INT;
44 | END_VAR
45 | VAR
46 | x : INT := 1;
47 | i : INT;
48 | i0 : INT := 0;
49 | i1 : INT := 10;
50 | END_VAR
51 |
52 | i:=i0;
53 | REPEAT
54 | y := i;
55 | i := i+1;
56 | UNTIL i>i1
57 | END_REPEAT;
58 | y := x;
59 | END_FUNCTION_BLOCK
60 |
61 | |
62 |
63 |
64 | **Command**
65 |
66 | .. code-block:: console
67 |
68 | python -m plcrex st-to-sctx "tests/st_to_synchr_models/TC21.st" "exports/TC21.sctx" "./bin\kicodia-win.bat"
69 |
70 | **Result**
71 |
72 | ``TC21.sctx``
73 |
74 | .. code-block:: console
75 |
76 | scchart TC21 {
77 | output int y
78 | int x
79 | int i
80 | int i0
81 | int i1
82 |
83 | region region0 {
84 | initial state state1
85 | immediate do i1 = 10; i0 = 0; x = 1; i = i0 go to state5
86 |
87 | state state5
88 | immediate do y = i go to state6
89 |
90 | state state6
91 | do i = i + 1 go to state9
92 |
93 | state state9
94 | immediate if !(i > i1) go to state5
95 | immediate do y = x go to finalState10
96 |
97 | final state finalState10
98 | }
99 | }
100 |
101 | .. figure:: ../fig/TC21.png
102 | :align: center
103 | :width: 300px
104 |
105 |
106 | |
--------------------------------------------------------------------------------
/docs/source/iec_checker.rst:
--------------------------------------------------------------------------------
1 | IEC-Checker
2 | ===========
3 |
4 | .. iec_checker:
5 |
6 | The IEC-Checker is an external tool for static code analysis of IEC 61131-3 POUs and called via PLCreX. Among other things, it checks the following issues [`.url `_]:
7 |
8 | * PLCopen Guidelines
9 |
10 | * CP1: Access to a member shall be by name
11 | * CP2: All code shall be used in the application
12 | * CP3: All variables shall be initialized before being used
13 | * CP4: Direct addressing should not overlap
14 | * CP6: Avoid external variables in functions, function blocks and classes
15 | * CP8: Floating point comparison shall not be equality or inequality
16 | * CP9: Limit the complexity of POU code
17 | * CP13: POUs shall not call themselves directly or indirectly
18 | * CP25: Data type conversion should be explicit
19 | * CP28: Time and physical measures comparisons shall not be equality or inequality
20 | * L10: Usage of CONTINUE and EXIT instruction should be avoided
21 | * L17: Each IF instruction should have an ELSE clause
22 | * Declaration analysis for derived types
23 | * Intraprocedural control flow analysis: detection of unreachable code blocks inside the POUs
24 | * Detection of unused variables
25 |
26 | .. note::
27 | IEC-Checker can only work with IEC 61131-3 ST supported by the matiec compiler [`.url `_].
28 | Most likely, it will fail on the source code containing non-standard language extensions.
29 |
30 |
31 | **Usage**
32 |
33 | .. code-block:: console
34 |
35 | python -m plcrex iec-check --help
36 |
37 | .. code:: console
38 |
39 | Usage: plcrex iec-check [OPTIONS] SOURCE EXE EXPORT
40 |
41 | IEC-Checker *.st → *.log
42 |
43 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
44 | │ * source PATH source path [default: None] [required] │
45 | │ * exe PATH iec_checker_Windows_x86_64_v0.4.exe path [default: None] [required] │
46 | │ * export PATH export path [default: None] [required] │
47 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
48 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
49 | │ --verbose --no-verbose print full log [default: no-verbose] │
50 | │ --help_iec_checker call iec-check help │
51 | │ --help Show this message and exit. │
52 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
53 |
54 |
55 | ..
56 | .. figure:: ../fig/iec_checker_demo.png
57 | :align: center
58 | :width: 600px
59 |
60 | |
61 |
62 | POU ``TC083.st``
63 | ----------------
64 |
65 | .. code-block:: console
66 |
67 | PROGRAM TC083
68 | VAR_ACCESS
69 | Var1 : DINT;
70 | Var2 : DINT;
71 | Var3 : DINT;
72 | END_VAR
73 |
74 | Var1 := 19 / 0;
75 | Var2 := Var1 / 1;
76 | END_PROGRAM
77 |
78 |
79 | Example 1
80 | ---------
81 |
82 | **Command**
83 |
84 | .. code-block:: console
85 |
86 | python -m plcrex iec-check --verbose ".\tests\st_examples\TC083.st" "./bin/iec_checker_Windows_x86_64_v0.4.exe" ".\exports\01"
87 |
88 | **Results**
89 |
90 | ``01.log``
91 |
92 | .. code-block:: console
93 |
94 | ...
95 | Running check for program TC083
96 | 5:8 UnusedVariable: Found unused local variable: VAR3
97 | 8:12 ZeroDivision: Constant 19 is divided by zero!
98 | 3:8 PLCOPEN-CP3: Variable VAR1 shall be initialized before being used
99 | 4:8 PLCOPEN-CP3: Variable VAR2 shall be initialized before being used
100 | ...
--------------------------------------------------------------------------------
/docs/source/fbd_to_st_ext.rst:
--------------------------------------------------------------------------------
1 | FBD-to-ST Compiler (extended)
2 | =============================
3 |
4 | .. fbd_to_st_ext:
5 |
6 | The extended FBD-to-ST Compiler represents a feature for optimizing FBDs, where the behavior of instantiated function blocks can be unknown. The optimization approach is shown in figure below and involves configuration with respect
7 | to Halstead’s metrics N (number of edges) ``--edge-opt``, N1 (number of operators) ``--op-opt``, and N2 (variable accesses) ``--var-opt`` [3].
8 |
9 | .. figure:: ../fig/fbd_optimizer_designflow_HL.png
10 | :align: center
11 | :width: 400px
12 |
13 |
14 | **Usage**
15 |
16 | .. code-block:: console
17 |
18 | python -m plcrex fbd-to-st-ext --help
19 |
20 |
21 | .. code:: console
22 |
23 | Usage: plcrex fbd-to-st-ext [OPTIONS] SOURCE EXE EXPORT
24 |
25 | FBD-to-ST Compiler (extended) *.xml → *.st
26 |
27 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
28 | │ * source PATH source path [default: None] [required] │
29 | │ * exe PATH NuSMV.exe path [default: None] [required] │
30 | │ * export PATH export path [default: None] [required] │
31 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
32 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
33 | │ --edge-opt --no-edge-opt optimize edges [default: no-edge-opt] │
34 | │ --var-opt --no-var-opt optimize variables [default: no-var-opt] │
35 | │ --op-opt --no-op-opt optimize operators [default: no-op-opt] │
36 | │ --help Show this message and exit. │
37 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
38 |
39 | |
40 |
41 | POU ``Pollutant_Indicator_WITH_ERROR.xml``
42 | ------------------------------------------
43 |
44 | The following POU was manually implemented using Beremiz [`.url `_].
45 |
46 | .. figure:: ../fig/Pollutant_Indicator_WITH_ERROR.png
47 | :align: center
48 | :width: 450px
49 |
50 | |
51 |
52 |
53 | Example 1: ``--no-edge-opt``, ``--no-var-opt``, ``--no-op-opt``
54 | ----------------------------------------------------------------
55 |
56 | **Command**
57 |
58 | .. code-block:: console
59 |
60 | python -m plcrex fbd-to-st-ext "tests/real_world_FBDs/Pollutant_Indicator_WITH_ERROR.xml" "bin/NuSMV.exe" ".\exports\01"
61 |
62 | **Results**
63 |
64 | ``01_no_opt.st``
65 |
66 | .. code-block:: console
67 |
68 | //--- This file was generated by PLCreX ---
69 | //--- https://github.com/marwern/PLCreX ---
70 | //-----------------------------------------
71 |
72 | FUNCTION_BLOCK
73 | Pollutant_Indicator
74 | VAR_INPUT
75 | IN1:BOOL;
76 | IN2:BOOL;
77 | IN3:BOOL;
78 | END_VAR
79 | VAR_OUTPUT
80 | OUT1:BOOL;
81 | OUT2:BOOL;
82 | OUT3:BOOL;
83 | END_VAR
84 | OUT1:=OR(AND(NOT(IN3),NOT(IN2),IN1),AND(NOT(IN3),IN2,NOT(IN1),AND(IN3,NOT(IN2),NOT(IN1))));
85 | OUT2:=OR(AND(NOT(IN3),IN2,IN1),AND(IN3,NOT(IN2),IN1),AND(IN3,IN2,NOT(IN1)));
86 | OUT3:=AND(IN1,IN2,IN3);
87 | END_FUNCTION_BLOCK
88 |
89 | |
90 |
91 |
92 | Example 2: ``--edge-opt``
93 | --------------------------
94 |
95 | **Command**
96 |
97 | .. code-block:: console
98 |
99 | python -m plcrex fbd-to-st-ext --edge-opt "tests/real_world_FBDs/Pollutant_Indicator_WITH_ERROR.xml" "bin/NuSMV.exe" ".\exports\01"
100 |
101 | **Results**
102 |
103 | ``01_edge_opt.st``
104 |
105 | .. code-block:: console
106 |
107 | //--- This file was generated by PLCreX ---
108 | //--- https://github.com/marwern/PLCreX ---
109 | //-----------------------------------------
110 |
111 | FUNCTION_BLOCK
112 | Pollutant_Indicator
113 | VAR_INPUT
114 | IN1:BOOL;
115 | IN2:BOOL;
116 | IN3:BOOL;
117 | END_VAR
118 | VAR_OUTPUT
119 | OUT1:BOOL;
120 | OUT2:BOOL;
121 | OUT3:BOOL;
122 | END_VAR
123 | OUT1:=AND(IN1,NOT(IN2),NOT(IN3));
124 | OUT2:=SEL(IN1,XOR(IN2,IN3),AND(IN2,IN3));
125 | OUT3:=AND(IN1,IN2,IN3);
126 | END_FUNCTION_BLOCK
127 |
128 | |
129 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | import os
20 | import sys
21 | #import tomllib #need Python 3.11
22 | import time
23 |
24 | try:
25 | import tomllib
26 | except ModuleNotFoundError:
27 | import tomli as tomllib
28 |
29 | with open("../../pyproject.toml", "rb") as f:
30 | _META = tomllib.load(f)
31 |
32 | PROJ_NAME = _META["project"]["name"]
33 | VERSION = _META["project"]["version"]
34 | AUTHOR = _META["project"]["authors"][0]["name"]
35 |
36 | sys.path.insert(0, os.path.abspath("../"))
37 |
38 | # -- Project information
39 | project = "PLCreX" #PROJ_NAME
40 | copyright = f'{time.strftime("%Y")}, {AUTHOR}'
41 | version = VERSION
42 | release = VERSION
43 | author = AUTHOR
44 | show_authors = True
45 |
46 | # -- General configuration
47 | extensions = [
48 | 'sphinx.ext.duration',
49 | 'sphinx.ext.doctest',
50 | 'sphinx.ext.autodoc',
51 | 'sphinx.ext.autosummary',
52 | 'sphinx.ext.intersphinx',
53 | 'sphinx.ext.napoleon',
54 | 'sphinx_rtd_theme',
55 | 'myst_parser',
56 | 'rst2pdf.pdfbuilder',
57 | 'sphinx_markdown_tables',
58 | ]
59 |
60 | # The name of the Pygments (syntax highlighting) style to use.
61 | pygments_style = 'sphinx'
62 |
63 | #intersphinx_mapping = {
64 | # 'python': ('https://docs.python.org/3/', None),
65 | # 'sphinx': ('https://www.sphinx-doc.org/en/master/', None),
66 | #}
67 | #intersphinx_disabled_domains = ['std']
68 |
69 | templates_path = ['_templates']
70 |
71 | # -- Options for HTML output
72 | html_theme = 'sphinx_rtd_theme' #sphinx_pdj_theme #press #sphinx_rtd_theme
73 |
74 | # Theme options are theme-specific and customize the look and feel of a theme
75 | # further. For a list of options available for each theme, see the
76 | # documentation.
77 | #
78 | html_theme_options = {
79 | 'prev_next_buttons_location': 'both'
80 | }
81 |
82 | #needed for alabaster theme
83 | #html_theme_options = {
84 | # 'collapse_navigation': True,
85 | # 'sticky_navigation': True,
86 | # 'navigation_depth': 4,
87 | # 'includehidden': True,
88 | # 'titles_only': False
89 | #}
90 |
91 | # The markdown parser
92 | #source_parsers = {'.md': 'recommonmark.parser.CommonMarkParser'}
93 |
94 | # The suffix(es) of source filenames.
95 | # You can specify multiple suffix as a list of string:
96 | #
97 | source_suffix = ['.rst', '.md']
98 | # source_suffix = {
99 | # '.rst': 'restructuredtext',
100 | # '.md': 'markdown'
101 | # }
102 |
103 | # The master toctree document.
104 | master_doc = 'index'
105 |
106 | pdf_documents = [(master_doc, u'plcrex-doc', u'PLCreX', author),]
107 | #pdf_stylesheets = ['autumn','kerning','a4-landscape']
108 |
109 | # -- Options for EPUB output
110 | epub_show_urls = 'footnote'
111 |
112 | # -- Options for HTML output ----------------------------------------------
113 |
114 | # Theme options are theme-specific and customize the look and feel of a theme
115 | # further. For a list of options available for each theme, see the
116 | # documentation.
117 | #
118 | # html_theme_options = {}
119 |
120 | # Add any paths that contain custom static files (such as style sheets) here,
121 | # relative to this directory. They are copied after the builtin static files,
122 | # so a file named "default.css" will overwrite the builtin "default.css".
123 | html_static_path = []
124 |
125 | # Custom sidebar templates, must be a dictionary that maps document names
126 | # to template names.
127 | #
128 | # This is required for the alabaster theme
129 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
130 | #html_sidebars = {
131 | #'**': [
132 | # 'relations.html', # needs 'show_related': True theme option to display
133 | # 'searchbox.html',
134 | # 'globaltoc.html',
135 | # 'navigation.html',
136 | # ]
137 | #}
--------------------------------------------------------------------------------
/tests/test_fbd2st.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_help():
27 | result = runner.invoke(cli.app, ["fbd-to-st", "--help"])
28 | assert result.exit_code == 0
29 |
30 |
31 | def test_wrong_file():
32 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\other_examples\TC001_wrong_file.txt", r".\exports\fbd2st1.st"])
33 | assert result.exit_code == 1
34 |
35 |
36 | # TC004 Function Block
37 |
38 | # test_nobwd_noformal1
39 | def test_nobwd_noformal1():
40 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC004.xml", r".\exports\fbd2st2.st"])
41 | assert result.exit_code == 0
42 | assert f"Success!" in result.stdout
43 |
44 |
45 | # test_nobwd_noformal2
46 | def test_nobwd_noformal2():
47 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC005_FB.xml", r".\exports\fbd2st3.st"])
48 | assert result.exit_code == 0
49 | assert f"Success!" in result.stdout
50 |
51 |
52 | # test_nobwd_noformal3
53 | def test_nobwd_noformal3():
54 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC005_FUN.xml", r".\exports\fbd2st4.st"])
55 | assert result.exit_code == 0
56 | assert f"Success!" in result.stdout
57 |
58 |
59 | # test_nobwd_noformal4
60 | def test_nobwd_noformal4():
61 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC005_PRG.xml", r".\exports\fbd2st5.st"])
62 | assert result.exit_code == 0
63 | assert f"Success!" in result.stdout
64 |
65 |
66 | # test_nobwd_formal1
67 | def test_nobwd_formal1():
68 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC004.xml", r".\exports\fbd2st62.st", "--formal"])
69 | assert result.exit_code == 0
70 | assert f"Success!" in result.stdout
71 |
72 |
73 | # test_nobwd_formal2
74 | def test_nobwd_formal2():
75 | result = runner.invoke(cli.app,
76 | ["fbd-to-st", r".\tests\plcopen_examples\TC005_PRG.xml", r".\exports\fbd2st7.st", "--formal"])
77 | assert result.exit_code == 0
78 | assert f"Success!" in result.stdout
79 |
80 |
81 | # formal + stp not supported by stp
82 |
83 | # test_bwd_noformal1
84 | def test_bwd_noformal1():
85 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC004.xml", r".\exports\fbd2st8.st", "--bwd"])
86 | assert result.exit_code == 0
87 | assert f"Success!" in result.stdout
88 |
89 |
90 | # test_bwd_noformal2
91 | def test_bwd_noformal2():
92 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC005_PRG.xml", r".\exports\fbd2st9.st", "--bwd"])
93 | assert result.exit_code == 0
94 | assert f"Success!" in result.stdout
95 |
96 |
97 | # test_bwd_formal1
98 | def test_bwd_formal1():
99 | result = runner.invoke(cli.app,
100 | ["fbd-to-st", r".\tests\plcopen_examples\TC004.xml", r".\exports\fbd2st10.st", "--bwd", "--formal"])
101 | assert result.exit_code == 0
102 | assert f"Success!" in result.stdout
103 |
104 |
105 | # test_bwd_formal2
106 | def test_bwd_formal2():
107 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC005_PRG.xml", r".\exports\fbd2st11.st", "--bwd",
108 | "--formal"])
109 | assert result.exit_code == 0
110 | assert f"Success!" in result.stdout
111 |
112 |
113 | # test_bwd_noformal_st2ast
114 | def test_bwd_noformal_st2ast():
115 | result = runner.invoke(cli.app, ["fbd-to-st", r".\tests\plcopen_examples\TC004.xml", r".\exports\fbd2st12.st", "--bwd"])
116 | assert result.exit_code == 0
117 | assert f"Success!" in result.stdout
118 | #result = runner.invoke(cli.app,
119 | # ["st-parser", r".\PLCreX_outputs\fbd2st12.st", r".\exports\fbdst13", "--txt"])
120 | #assert result.exit_code == 0
121 | assert f"Success!" in result.stdout
122 |
--------------------------------------------------------------------------------
/docs/source/fbd_to_sctx.rst:
--------------------------------------------------------------------------------
1 | FBD-to-SCCharts Compiler
2 | ========================
3 |
4 | .. fbd_to_sctx:
5 |
6 | The FBD-to-SCCharts Compiler represents a feature for optimizing FBDs, where the behavior of instantiated function blocks can be unknown. The optimization approach is shown in figure below and involves configuration with respect
7 | to Halstead’s metrics N (number of edges) ``--edge-opt``, N1 (number of operators) ``--op-opt``, and N2 (variable accesses) ``--var-opt``. Furthermore, this feature translates FBDs into Sequentially Constructive Statecharts (SCCharts) for reuse in model-based design of reactive systems and formal verification [3].
8 |
9 | .. figure:: ../fig/fbd_optimizer_designflow_HL.png
10 | :align: center
11 | :width: 400px
12 |
13 |
14 | **Usage**
15 |
16 | .. code-block:: console
17 |
18 | python -m plcrex fbd-to-sctx --help
19 |
20 |
21 | .. code:: console
22 |
23 | Usage: plcrex fbd-to-sctx [OPTIONS] SOURCE EXE EXPORT
24 |
25 | FBD-to-SCCharts Compiler (Data-Flow) *.xml → *.sctx
26 |
27 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
28 | │ * source PATH source path [default: None] [required] │
29 | │ * exe PATH NuSMV.exe path [default: None] [required] │
30 | │ * export PATH export path [default: None] [required] │
31 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
32 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
33 | │ --edge-opt --no-edge-opt optimize edges [default: no-edge-opt] │
34 | │ --var-opt --no-var-opt optimize variables [default: no-var-opt] │
35 | │ --op-opt --no-op-opt optimize operators [default: no-op-opt] │
36 | │ --help Show this message and exit. │
37 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
38 |
39 | ..
40 | .. figure:: ../fig/fbd_optimizer_demo.png
41 | :align: center
42 | :width: 600px
43 |
44 | |
45 |
46 | POU ``Pollutant_Indicator_WITH_ERROR.xml``
47 | ------------------------------------------
48 |
49 | The following POU was manually implemented using Beremiz [`.url `_].
50 |
51 | .. figure:: ../fig/Pollutant_Indicator_WITH_ERROR.png
52 | :align: center
53 | :width: 450px
54 |
55 | |
56 |
57 |
58 | Example 1: ``--no-edge-opt``, ``--no-var-opt``, ``--no-op-opt``
59 | ----------------------------------------------------------------
60 |
61 | **Command**
62 |
63 | .. code-block:: console
64 |
65 | python -m plcrex fbd-to-sctx "tests/real_world_FBDs/Pollutant_Indicator_WITH_ERROR.xml" "bin/NuSMV.exe" ".\exports\01"
66 |
67 | **Results**
68 |
69 | ``01_no_opt.sctx``
70 |
71 | .. code-block:: console
72 |
73 | //--- This file was generated by PLCreX ---
74 | //--- https://github.com/marwern/PLCreX ---
75 | //-----------------------------------------
76 |
77 | scchart Pollutant_Indicator{
78 | input bool IN1
79 | input bool IN2
80 | input bool IN3
81 | output bool OUT1
82 | output bool OUT2
83 | output bool OUT3
84 | dataflow{
85 | OUT1=((!(IN3)&!(IN2)&IN1)|(!(IN3)&IN2&!(IN1)&(IN3&!(IN2)&!(IN1))))
86 | seq
87 | OUT2=((!(IN3)&IN2&IN1)|(IN3&!(IN2)&IN1)|(IN3&IN2&!(IN1)))
88 | seq
89 | OUT3=(IN1&IN2&IN3)
90 | seq}}
91 |
92 | .. figure:: ../fig/no_opt_example.png
93 | :align: center
94 | :width: 300px
95 |
96 |
97 | |
98 |
99 |
100 | Example 2: ``--edge-opt``
101 | --------------------------
102 |
103 | **Command**
104 |
105 | .. code-block:: console
106 |
107 | python -m plcrex fbd-to-sctx --edge-opt "tests/real_world_FBDs/Pollutant_Indicator_WITH_ERROR.xml" "bin/NuSMV.exe" ".\exports\01"
108 |
109 | **Results**
110 |
111 | ``01_edge_opt.sctx``
112 |
113 | .. code-block:: console
114 |
115 | //--- This file was generated by PLCreX ---
116 | //--- https://github.com/marwern/PLCreX ---
117 | //-----------------------------------------
118 |
119 | scchart Pollutant_Indicator{
120 | input bool IN1
121 | input bool IN2
122 | input bool IN3
123 | output bool OUT1
124 | output bool OUT2
125 | output bool OUT3
126 | dataflow{
127 | OUT1=(IN1&!(IN2)&!(IN3))
128 | seq
129 | OUT2=((IN1)?(((IN2)^(IN3))):((IN2&IN3)))
130 | seq
131 | OUT3=(IN1&IN2&IN3)
132 | seq}}
133 |
134 | .. figure:: ../fig/edge_opt_example.png
135 | :align: center
136 | :width: 300px
137 |
138 |
139 | |
140 |
--------------------------------------------------------------------------------
/docs/source/fbd_to_st.rst:
--------------------------------------------------------------------------------
1 | FBD-to-ST Compiler
2 | ==================
3 |
4 | .. fbd_to_st:
5 |
6 | The FBD-to-ST Compiler translates IEC 61131-3 FBDs stored in PLCopen XML format into ST POUs. In this context, PLCreX supports the translation in different formats. In general, PLCreX distinguishes between a **formal** representation of the parameter list of instantiated POUs,
7 | for example ``TONx(IN := A, PT := B);`` and a **non formal** representation, ``TONx(A,B);``. Furthermore, we distinguish between a **forward** translation strategy and a **backward** translation strategy.
8 |
9 | .. warning::
10 | The backward translation strategy can change the semantics because the variables are updated at the end of a cycle. In contrast, without database, additional local variables needed for forward translation are declared as ``BOOL`` by default,
11 | unless the data type is implicit given by connected component.
12 |
13 |
14 | **Usage**
15 |
16 | .. code-block:: console
17 |
18 | python -m plcrex fbd-to-st --help
19 |
20 |
21 | .. code:: console
22 |
23 | Usage: plcrex fbd-to-st [OPTIONS] SOURCE EXPORT
24 |
25 | FBD-to-ST Compiler *.xml → *.st
26 |
27 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
28 | │ * source PATH source path [default: None] [required] │
29 | │ * export PATH export path [default: None] [required] │
30 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
31 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
32 | │ --bwd --no-bwd use backward translation [default: no-bwd] │
33 | │ --formal --no-formal formal parameter list [default: no-formal] │
34 | │ --help Show this message and exit. │
35 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
36 |
37 |
38 | ..
39 | .. figure:: ../fig/fbd_to_st_demo.png
40 | :align: center
41 | :width: 600px
42 |
43 | |
44 |
45 | POU ``TC005_PRG.xml``
46 | ---------------------
47 |
48 | The following POU was manually implemented using Beremiz [`.url `_].
49 |
50 | .. figure:: ../fig/TC005.png
51 | :align: center
52 | :width: 450px
53 |
54 | |
55 |
56 | Example 1: ``--no-formal`` ``--no-bwd``
57 | ---------------------------------------
58 |
59 | **Command**
60 |
61 | .. code-block:: console
62 |
63 | python -m plcrex fbd-to-st --no-formal --no-bwd ".\tests\plcopen_examples\TC005_PRG.xml" ".\exports\01"
64 |
65 | **Results**
66 |
67 | ``01.st``
68 |
69 | .. code-block:: console
70 |
71 | ...
72 | AND1_OUT := AND(i1,i2);
73 | TON0(AND1_OUT,i3);
74 | XOR3_OUT := XOR(AND1_OUT,TON0.Q);
75 | o1 := XOR3_OUT;
76 | o4 := TON0.Q;
77 | o2 := i1;
78 | ...
79 |
80 | Example 2: ``--no-formal`` ``--bwd``
81 | ------------------------------------
82 |
83 | **Command**
84 |
85 | .. code-block:: console
86 |
87 | python -m plcrex fbd-to-st --no-formal --bwd ".\tests\plcopen_examples\TC005_PRG.xml" ".\exports\02"
88 |
89 | **Results**
90 |
91 | ``02.st``
92 |
93 | .. code-block:: console
94 |
95 | ...
96 | TON0(AND(i1,i2),i3);
97 | o1 := XOR(AND(i1,i2),TON0.Q);
98 | o4 := TON0.Q;
99 | o2 := i1;
100 | ...
101 |
102 | Example 3: ``--formal`` ``--no-bwd``
103 | ------------------------------------
104 |
105 | **Command**
106 |
107 | .. code-block:: console
108 |
109 | python -m plcrex fbd-to-st --formal --no-bwd ".\tests\plcopen_examples\TC005_PRG.xml" ".\exports\03"
110 |
111 | **Results**
112 |
113 | ``03.st``
114 |
115 | .. code-block:: console
116 |
117 | ...
118 | AND1_OUT := AND(i1,i2);
119 | TON0(IN := AND1_OUT,PT := i3);
120 | XOR3_OUT := XOR(AND1_OUT,TON0.Q);
121 | o1 := XOR3_OUT;
122 | o4 := TON0.Q;
123 | o2 := i1;
124 | ...
125 |
126 |
127 | Example 4: ``--formal`` ``--bwd``
128 | ---------------------------------
129 |
130 | **Command**
131 |
132 | .. code-block:: console
133 |
134 | python -m plcrex fbd-to-st --formal --bwd ".\tests\plcopen_examples\TC005_PRG.xml" ".\exports\04"
135 |
136 | **Results**
137 |
138 | ``04.st``
139 |
140 | .. code-block:: console
141 |
142 | ...
143 | TON0(IN := AND(i1,i2),PT := i3);
144 | o1 := XOR(AND(i1,i2),TON0.Q);
145 | o4 := TON0.Q;
146 | o2 := i1;
147 | ...
--------------------------------------------------------------------------------
/tests/test_fbd2x.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | from typer.testing import CliRunner
20 |
21 | from plcrex import cli
22 |
23 | runner = CliRunner()
24 |
25 |
26 | def test_help1():
27 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--help"])
28 | assert result.exit_code == 0
29 |
30 | def test_help2():
31 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--help"])
32 | assert result.exit_code == 0
33 |
34 | def test_wrong_file1():
35 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--edge-opt", r".\tests\other_examples\TC001_wrong_file.txt", "bin/NuSMV.exe", r".\exports\st2x1.st"])
36 | assert result.exit_code == 1
37 |
38 | def test_wrong_file2():
39 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--edge-opt", r".\tests\other_examples\TC001_wrong_file.txt", "bin/NuSMV.exe", r".\exports\st2x1.sctx"])
40 | assert result.exit_code == 1
41 |
42 | def test_edge_opt1_st():
43 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--edge-opt", r"tests/real_world_FBDs/Antivalence_3x.xml", "bin/NuSMV.exe", r".\exports\st2x2.st"])
44 | assert result.exit_code == 0
45 | assert f"Success!" in result.stdout
46 |
47 | def test_edge_opt1_sctx():
48 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--edge-opt", r"tests/real_world_FBDs/Antivalence_3x.xml", "bin/NuSMV.exe", r".\exports\st2x2.sctx"])
49 | assert result.exit_code == 0
50 | assert f"Success!" in result.stdout
51 |
52 | def test_edge_opt2_st():
53 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--edge-opt", r"tests/real_world_FBDs/Bending_Machine_Control.xml", "bin/NuSMV.exe", r".\exports\st2x4.st"])
54 | assert result.exit_code == 0
55 | assert f"Success!" in result.stdout
56 |
57 | def test_edge_opt2_sctx():
58 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--edge-opt", r"tests/real_world_FBDs/Bending_Machine_Control.xml", "bin/NuSMV.exe", r".\exports\st2x4.sctx"])
59 | assert result.exit_code == 0
60 | assert f"Success!" in result.stdout
61 |
62 | def test_edge_opt3_st():
63 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--edge-opt", r"tests/real_world_FBDs/Cylinder_Control_System.xml", "bin/NuSMV.exe", r".\exports\st2x6.st"])
64 | assert result.exit_code == 0
65 | assert f"Success!" in result.stdout
66 |
67 | def test_edge_opt3_sctx():
68 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--edge-opt", r"tests/real_world_FBDs/Cylinder_Control_System.xml", "bin/NuSMV.exe", r".\exports\st2x6.sctx"])
69 | assert result.exit_code == 0
70 | assert f"Success!" in result.stdout
71 |
72 | def test_edge_opt4_st():
73 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--edge-opt", r"tests/real_world_FBDs/KV_Diagram_optimized_Chart.xml", "bin/NuSMV.exe", r".\exports\st2x8.st"])
74 | assert result.exit_code == 0
75 | assert f"Success!" in result.stdout
76 |
77 | def test_edge_opt4_sctx():
78 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--edge-opt", r"tests/real_world_FBDs/KV_Diagram_optimized_Chart.xml", "bin/NuSMV.exe", r".\exports\st2x8.sctx"])
79 | assert result.exit_code == 0
80 | assert f"Success!" in result.stdout
81 |
82 | def test_var_opt_st():
83 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--var-opt", r"tests/real_world_FBDs/Antivalence_3x.xml", "bin/NuSMV.exe", r".\exports\st2x10.st"])
84 | assert result.exit_code == 0
85 | assert f"Success!" in result.stdout
86 |
87 | def test_var_opt_sctx():
88 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--var-opt", r"tests/real_world_FBDs/Antivalence_3x.xml", "bin/NuSMV.exe", r".\exports\st2x10.sctx"])
89 | assert result.exit_code == 0
90 | assert f"Success!" in result.stdout
91 |
92 | def test_op_opt_st():
93 | result = runner.invoke(cli.app, ["fbd-to-st-ext", "--var-opt", r"tests/real_world_FBDs/Antivalence_3x.xml", "bin/NuSMV.exe", r".\exports\st2x12.st"])
94 | assert result.exit_code == 0
95 | assert f"Success!" in result.stdout
96 |
97 | def test_op_opt_sctx():
98 | result = runner.invoke(cli.app, ["fbd-to-sctx", "--var-opt", r"tests/real_world_FBDs/Antivalence_3x.xml", "bin/NuSMV.exe", r".\exports\st2x12.sctx"])
99 | assert result.exit_code == 0
100 | assert f"Success!" in result.stdout
--------------------------------------------------------------------------------
/plcrex/tools/misc/generic_functions.py:
--------------------------------------------------------------------------------
1 | #
2 | # This file is part of PLCreX (https://github.com/marwern/PLCreX).
3 | #
4 | # Copyright (c) 2022-2024 Marcel C. Werner.
5 | #
6 | # This program is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, version 3.
9 | #
10 | # This program is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 | #
18 |
19 | import time
20 | import datetime
21 | from lark import Tree, Lark
22 | import os
23 | import site
24 | import typer
25 | import logging
26 |
27 | # ANSI escape sequences for terminal colors
28 | class ColorCodes:
29 | RED = '\033[91m'
30 | GREEN = '\033[92m'
31 | YELLOW = '\033[93m'
32 | BLUE = '\033[94m'
33 | RESET = '\033[0m'
34 |
35 |
36 | # Custom formatter class
37 | class CustomFormatter(logging.Formatter):
38 | format = "%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d\n%(message)s"
39 |
40 | FORMATS = {
41 | logging.DEBUG: ColorCodes.BLUE + format + ColorCodes.RESET,
42 | logging.INFO: ColorCodes.GREEN + format + ColorCodes.RESET,
43 | logging.WARNING: ColorCodes.YELLOW + format + ColorCodes.RESET,
44 | logging.ERROR: ColorCodes.RED + format + ColorCodes.RESET,
45 | logging.CRITICAL: ColorCodes.RED + format + ColorCodes.RESET,
46 | }
47 |
48 | def format(self, record):
49 | log_fmt = self.FORMATS.get(record.levelno)
50 | formatter = logging.Formatter(log_fmt)
51 | return formatter.format(record)
52 |
53 | format_cli = "%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d\n%(message)s"
54 | logging.basicConfig(format=format_cli)
55 |
56 | # Configure logging
57 | #logging.basicConfig(level=logging.DEBUG)
58 | #logger = logging.getLogger()
59 | #handler = logger.handlers[0]
60 | #handler.setFormatter(CustomFormatter())
61 |
62 | def parse_src(grammar, source: str, debug_flag):
63 | src_parser = Lark(
64 | get_file(fr'plcrex\data\grammars\{grammar}.lark'),
65 | maybe_placeholders=True,
66 | keep_all_tokens=False,
67 | debug=False)
68 | src_ast = src_parser.parse(source)
69 | #print(src_ast) if debug_flag else None
70 | return src_ast
71 |
72 |
73 | def find_1st_parent_tree(tree, target_node):
74 | if not isinstance(tree, Tree):
75 | return None
76 |
77 | for child in tree.children:
78 | if child == target_node:
79 | return tree
80 | parent = find_1st_parent_tree(child, target_node)
81 | if parent is not None:
82 | return parent
83 | return None
84 |
85 |
86 | def find_all_parent_trees(tree, target_node, parent_list=None):
87 | if parent_list is None:
88 | parent_list = []
89 |
90 | if not isinstance(tree, Tree):
91 | return parent_list
92 |
93 | for child in tree.children:
94 | if child == target_node:
95 | parent_list.append(tree)
96 | else:
97 | find_all_parent_trees(child, target_node, parent_list)
98 |
99 | return parent_list
100 |
101 |
102 | def get_file(rel_path: str):
103 | # initialize grammar
104 | f = ""
105 |
106 | # Get the list of all global site-packages directories
107 | site_packages_dirs = site.getsitepackages()
108 |
109 | # Iterate over all site-packages directories
110 | for dir in site_packages_dirs:
111 | # Create an absolute path to the file
112 | abs_file_path = os.path.join(dir, rel_path)
113 |
114 | # Check if the file exists at this path
115 | if os.path.isfile(abs_file_path):
116 | #print(abs_file_path)
117 | # If the file exists, open it
118 | with open(abs_file_path, 'rt') as file:
119 | f = file.read()
120 | #logging.warning(f"Ignoring data from local developer package! > {rel_path}")
121 | typer.echo(typer.style(f"WARNING: Ignoring data from local developer package! > {rel_path}",
122 | fg=typer.colors.YELLOW, bold=True))
123 | #file.close()
124 | return f
125 |
126 | # if plcrex is not installed via pip, use local dir
127 | if f == "":
128 | with open(rel_path, 'rt') as file:
129 | f = file.read()
130 | #logging.warning(f"Ignoring data from global site-package! > {rel_path}")
131 | typer.echo(
132 | typer.style(f"WARNING: Ignoring data from global site-package! > {rel_path}", fg=typer.colors.YELLOW,
133 | bold=True))
134 | #file.close()
135 | return f
136 |
137 |
138 | def print_header(script_name:str, version:str, author:str):
139 |
140 | global start_time
141 | start_time = time.time()
142 | current_time = datetime.datetime.now().strftime("%H:%M:%S")
143 |
144 | typer.echo("--------------------------------------------------")
145 | typer.echo(f"Tool:\t\t{script_name}")
146 | typer.echo(f"Version:\t{version}")
147 | typer.echo(f"Author:\t\t{author}")
148 | typer.echo(f"Start:\t\t{current_time} {datetime.date.today()}")
149 | typer.echo("--------------------------------------------------")
150 |
151 |
152 | def print_footer():
153 | typer.echo("--------------------------------------------------")
154 | typer.echo(f"Runtime: %s seconds" % format((time.time() - start_time), ".3f"))
155 |
--------------------------------------------------------------------------------
/docs/source/st_parser.rst:
--------------------------------------------------------------------------------
1 | ST-Parser
2 | =========
3 |
4 | .. st-parser:
5 |
6 | The ST-Parser includes an executable grammar for IEC 61131-3 ST POUs as well as the possibility to save the
7 | resulting syntax tree visually or as plain text and reuse it for subsequent analysis. The embedded default grammar covers the following constructs and the ``--beckhoff`` grammar contains almost all ST constructs:
8 |
9 | * IEC 61131-3 POU-Types: ``Program``, ``Functionblock``, ``Function``
10 | * Sections (each available only once): ``VAR_INPUT``, ``VAR``, ``VAR_OUTPUT``, ``VAR_IN_OUT``, ``VAR_EXTERNAL``
11 | * Data types: ``BOOL``, ``INT``, ``DINT``, ``UINT``, ``REAL``, ``TIME``, ``ARRAY``
12 | * Operators: ``*``, ``/``, ``MOD``, ``+``, ``-``, ``NOT``, ``AND``, ``XOR``, ``OR``, ``<=``, ``>=``, ``<``, ``>``, ``=``, ``<>``, ``FALSE``, ``TRUE``, ``external function/functionblocks``, ``variable``, ``constant````
13 | * Statements: ``assignments``, ``if/else``, ``case``, ``macro``, ``for``, ``while``, ``repeat``, ``exit``, ``return``
14 | * Parameter list: informal, e.g. ``TONx(A,B);`` instead of ``TONx(IN := A, PT := B);``
15 |
16 |
17 | **Usage**
18 |
19 | .. code-block:: console
20 |
21 | python -m plcrex st-parser --help
22 |
23 |
24 | .. code:: console
25 |
26 | Usage: plcrex st-parser [OPTIONS] SOURCE EXPORT
27 |
28 | ST-Parser *.st → *.dot/*.txt
29 |
30 | ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────╮
31 | │ * source PATH source path [default: None] [required] │
32 | │ * export PATH export path [default: None] [required] │
33 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
34 | ╭─ Options ────────────────────────────────────────────────────────────────────────────────────╮
35 | │ --txt --no-txt tree export as *.txt [default: txt] │
36 | │ --dot --no-dot tree export as *.dot [default: dot] │
37 | │ --beckhoff --no-beckhoff use Beckhoff TwinCAT ST grammar [default: no-beckhoff] │
38 | │ --help Show this message and exit. │
39 | ╰──────────────────────────────────────────────────────────────────────────────────────────────╯
40 |
41 |
42 | ..
43 | .. figure:: ../fig/st_parser_demo.png
44 | :align: center
45 | :width: 600px
46 |
47 | |
48 |
49 | POU ``TC081.st``
50 | ----------------
51 |
52 | .. code-block:: console
53 |
54 | FUNCTION_BLOCK TC081
55 | VAR_INPUT
56 | IN1 : INT;
57 | IN2 : INT;
58 | IN3 : INT;
59 | IN4 : BOOL;
60 | END_VAR
61 | VAR_OUTPUT
62 | Wrn : BOOL;
63 | Err : BOOL;
64 | Ctr : INT;
65 | iOut2 : INT;
66 | END_VAR
67 | VAR
68 | SR1 : SR;
69 | TON1 : TON;
70 | TON2 : TON;
71 | END_VAR
72 |
73 | SR1(((((20*IN1)+(6*IN2)+IN3))=(100*2)) AND (IN1+IN2+IN3=100),IN4);
74 | TON1((((((20*IN1)+(6*IN2)+IN3))=(100*2)) AND (IN1+IN2+IN3=100)),2);
75 | TON2(IN1+IN2+IN3=42 AND SR1.Q,3);
76 | Ctr := TON2.ET;
77 | Err := TON1.Q;
78 | Wrn := SR1.Q;
79 | END_FUNCTION_BLOCK
80 |
81 |
82 | Example 1 ``--no-beckhoff``
83 | ---------------------------
84 |
85 | **Command**
86 |
87 | .. code-block:: console
88 |
89 | python -m plcrex st-parser ".\tests\st_examples\TC081.st" ".\exports\01"
90 |
91 | **Results**
92 |
93 | ``01.dot``
94 |
95 | .. code-block:: console
96 |
97 | digraph G {
98 | rankdir=LR;
99 | 0 [label="Token('NAME', 'TC081')"];
100 | 1 [fillcolor="#aec5e0", label=name, style=filled];
101 | 1 -> 0;
102 | ...
103 |
104 | ``01.txt``
105 |
106 | .. code-block:: console
107 |
108 | start
109 | module
110 | name TC081
111 | idcl
112 | var_input
113 | dcllist
114 | declaration
115 | variable IN1
116 | datatype INT
117 | declaration
118 | variable IN2
119 | datatype INT
120 | declaration
121 | variable IN3
122 | datatype INT
123 | declaration
124 | variable IN4
125 | ...
126 |
127 | .. figure:: ../fig/TC081_AST.png
128 | :align: center
129 | :width: 600px
130 |
131 | |
132 |
133 | Example 2 ``--beckhoff``
134 | ---------------------------
135 |
136 | **Command**
137 |
138 | .. code-block:: console
139 |
140 | python -m plcrex st-parser --beckhoff ".\tests\st_examples\TC081.st" ".\exports\02"
141 |
142 | **Results**
143 |
144 | ``02.dot``
145 |
146 | .. code-block:: console
147 |
148 | digraph G {
149 | rankdir=LR;
150 | 0 [label="Token('FUNCTION_BLOCK', 'FUNCTION_BLOCK')"];
151 | 1 [label="Token('IDENTIFIER', 'TC081')"];
152 | 2 [label="Token('IDENTIFIER', 'IN1')"];
153 | 3 [fillcolor="#b9d2eb", label=variable_name, style=filled];
154 | 3 -> 2;
155 | 4 [fillcolor="#8e96ea", label=var1, style=filled];
156 | 4 -> 3;
157 | 5 [fillcolor="#dea4f6", label=var1_list, style=filled];
158 | 5 -> 4;
159 | ...
160 |
161 | ``02.txt``
162 |
163 | .. code-block:: console
164 |
165 | iec_source
166 | function_block_type_declaration
167 | FUNCTION_BLOCK
168 | TC081
169 | input_declarations
170 | var1_init_decl
171 | var1_list
172 | var1
173 | variable_name IN1
174 | simple_spec_init
175 | simple_specification INT
176 | var1_init_decl
177 | var1_list
178 | var1
179 | variable_name IN2
180 | simple_spec_init
181 | simple_specification INT
182 | ...
183 |
184 | .. figure:: ../fig/TC081_AST3.png
185 | :align: center
186 | :width: 600px
187 |
188 | |
--------------------------------------------------------------------------------
/plcrex/data/grammars/scl_grammar.lark:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // POU Declaration List
3 | // ********************************************************************************
4 | ?start: type pou "{" (idcl | vdcl )* statlist? "}" -> module
5 | pou: NAME -> name
6 |
7 | type: TYPE
8 | TYPE: "module"
9 |
10 |
11 | // ********************************************************************************
12 | // Interface/Variable Declaration List
13 | // ********************************************************************************
14 | idcl: (var_input | var_output | var_in_out)* -> idcl
15 |
16 | vdcl: var_local -> vdcl
17 |
18 | dcllist: declaration
19 |
20 | declaration:
21 | | datatype variable ";"
22 | | datatype variable "=" _expr ";"
23 | | datatype variable array ";"
24 |
25 | var_input: "input" dcllist
26 |
27 | var_output: "output" dcllist
28 |
29 | var_in_out: "input output" dcllist
30 |
31 | var_local: dcllist
32 |
33 |
34 | // ********************************************************************************
35 | // Datatypes
36 | // ********************************************************************************
37 | datatype: TYPE_BOOL | TYPE_INT | TYPE_REAL | TYPE_TIME | macro_name
38 |
39 | TYPE_BOOL: "bool"
40 | TYPE_INT: "int"
41 | TYPE_REAL: "float"
42 | TYPE_TIME: "int"
43 | array: "[" constant_int "]"
44 | macro_name: MACRO_NAME
45 |
46 |
47 | // ********************************************************************************
48 | // Functions/User-POUs
49 | // ********************************************************************************
50 | macro:
51 | | MACRO_NAME "." macro_out
52 | | MACRO_NAME "(" macro_assignment ("," macro_assignment)* ");"
53 | macro_out: MACRO_NAME
54 |
55 |
56 | // ********************************************************************************
57 | // Arithmetic operators
58 | // ********************************************************************************
59 | multiply_with: _expr "*" _expr
60 | divide_by: _expr "/" _expr
61 | modulo: _expr "%" _expr
62 | adding: _expr "+" _expr
63 | subtracting: _expr "-" _expr
64 | expt: "EXPT(" _expr "," _expr ")"
65 | unaryminus: "-" _expr
66 |
67 |
68 | // ********************************************************************************
69 | // Boolean operators
70 | // ********************************************************************************
71 | not_op: "!(" _expr ")"
72 | and_op: _expr "&&" _expr
73 | xor_op: _expr "^" _expr
74 | or_op: _expr "||" _expr
75 |
76 |
77 | // ********************************************************************************
78 | // Numeric operators
79 | // ********************************************************************************
80 | less_or_equal.1: _expr "<=" _expr
81 | greater_or_equal.1: _expr ">=" _expr
82 | less_than: _expr "<" _expr
83 | greater_than: _expr ">" _expr
84 |
85 |
86 | // ********************************************************************************
87 | // Equality
88 | // ********************************************************************************
89 | equality: _expr EQ _expr | "EQ(" _expr "," _expr ")"
90 | EQ:/[==]/
91 | inequality: _expr NEQ _expr | "NE(" _expr "," _expr ")"
92 | NEQ:/[!=]/
93 |
94 | // ********************************************************************************
95 | // General expressions
96 | // ********************************************************************************
97 | _expr:
98 | | equality
99 | | variable ("[" constant_int "]")*
100 | | multiply_with
101 | | divide_by
102 | | modulo
103 | | adding
104 | | subtracting
105 | | "(" _expr ")"
106 | | expt
107 | | constant
108 | | constant_time
109 | | not_op
110 | | and_op
111 | | xor_op
112 | | or_op
113 | | inequality
114 | | less_or_equal
115 | | greater_or_equal
116 | | less_than
117 | | greater_than
118 | | false
119 | | true
120 | | unaryminus
121 | | if_statement_short
122 |
123 | false: FALSE
124 | FALSE: "false"
125 | true: TRUE
126 | TRUE: "true"
127 |
128 |
129 | // ********************************************************************************
130 | // Statementlist
131 | // ********************************************************************************
132 | constant_time.2: MS_DURATION
133 | constant.1: UINT | REAL
134 | constant_int.1: UINT
135 | UINT: /[0-9]+/
136 | REAL: /[0-9][.]?[0-9]*/
137 | MS_DURATION: UINT
138 | //NUMBER: /[+-]?[0-9]+/
139 |
140 | statlist: statement*
141 |
142 | statement:
143 | | immediate_assignment
144 | | if_statement
145 | | while_statement
146 | | repeat_statement
147 | | macro
148 | | macro_assignment
149 |
150 |
151 | // ********************************************************************************
152 | // Assignments
153 | // ********************************************************************************
154 | immediate_assignment: variable("["constant_int"]")* "=" _expr ";"
155 |
156 | macro_assignment: variable "=" _expr
157 |
158 |
159 | // ********************************************************************************
160 | // selection statement
161 | // ********************************************************************************
162 | if_statement: "if(" _expr "){" statlist "}else{" statlist "}"
163 |
164 | if_statement_short: "(" _expr "?" _expr ":" _expr ")"
165 |
166 |
167 |
168 | // ********************************************************************************
169 | // iteration statements
170 | // ********************************************************************************
171 | while_statement: "while(" _expr "){" statlist "pause;" statlist "}"
172 | //statlist_while: statement* "pause;" statement -> statlist
173 |
174 | repeat_statement: "do:" statlist "pause;" statlist "if(!(" _expr ")){" "goto do;" "}else{" statlist "}"
175 |
176 |
177 | // ********************************************************************************
178 | // Additional Terminals and_op rules
179 | // ********************************************************************************
180 | variable: NAME
181 |
182 |
183 | // ********************************************************************************
184 | // Lark statements
185 | // ********************************************************************************
186 | MULTI_LINE_COMMENT: /\(\*.*?\*\)/s
187 | SINGLE_LINE_COMMENT: /\s*/ "//" /[^\n]/*
188 |
189 | %ignore WS
190 | %ignore MULTI_LINE_COMMENT
191 | %ignore SINGLE_LINE_COMMENT
192 | %import common.WS
193 | NAME: /[_]?(?!(true|false|BOOL|INT|REAL|ARRAY\b))[a-zA-Z0-9_]\w*/
194 | MACRO_NAME: /[_]?(?!(true|false|BOOL|INT|REAL|ARRAY\b))[a-zA-Z_]\w*/
--------------------------------------------------------------------------------
/plcrex/data/grammars/scl_grammar_EOL.lark:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // POU Declaration List
3 | // ********************************************************************************
4 | ?start: "_LINEBREAK_" type pou "{" "_LINEBREAK_" (idcl | vdcl)* statlist? "}" -> module
5 | pou: NAME -> name
6 |
7 | type: TYPE
8 | TYPE: "module"
9 |
10 |
11 | // ********************************************************************************
12 | // Interface/Variable Declaration List
13 | // ********************************************************************************
14 | idcl: (var_input | var_output | var_in_out)* -> idcl
15 |
16 | vdcl: var_local -> vdcl
17 |
18 | dcllist: declaration
19 |
20 | declaration:
21 | | datatype variable ";" "_LINEBREAK_"
22 | | datatype variable "=" _expr ";" "_LINEBREAK_"
23 | | datatype variable array ";" "_LINEBREAK_"
24 |
25 | var_input: "input" dcllist
26 |
27 | var_output: "output" dcllist
28 |
29 | var_in_out: "input output" dcllist
30 |
31 | var_local: dcllist
32 |
33 |
34 | // ********************************************************************************
35 | // Datatypes
36 | // ********************************************************************************
37 | datatype: TYPE_BOOL | TYPE_INT | TYPE_REAL | TYPE_TIME | macro_name
38 |
39 | TYPE_BOOL: "bool"
40 | TYPE_INT: "int"
41 | TYPE_REAL: "float"
42 | TYPE_TIME: "int"
43 | array: "[" constant_int "]"
44 | macro_name: MACRO_NAME
45 |
46 |
47 | // ********************************************************************************
48 | // Functions/User-POUs
49 | // ********************************************************************************
50 | macro:
51 | | MACRO_NAME "." macro_out
52 | | MACRO_NAME "(" macro_assignment ("," macro_assignment)* ");"
53 | macro_out: MACRO_NAME
54 |
55 |
56 | // ********************************************************************************
57 | // Arithmetic operators
58 | // ********************************************************************************
59 | multiply_with: _expr "*" _expr
60 | divide_by: _expr "/" _expr
61 | modulo: _expr "%" _expr
62 | adding: _expr "+" _expr
63 | subtracting: _expr "-" _expr
64 | expt: "exp(" _expr "," _expr ")"
65 | unaryminus: "-" _expr
66 |
67 |
68 | // ********************************************************************************
69 | // Boolean operators
70 | // ********************************************************************************
71 | not_op: "!(" _expr ")"
72 | and_op: _expr "&&" _expr
73 | xor_op: "(" _expr ")" "^" "(" _expr ")"
74 | or_op: _expr "||" _expr
75 |
76 |
77 | // ********************************************************************************
78 | // Numeric operators
79 | // ********************************************************************************
80 | less_or_equal.1: _expr "<=" _expr
81 | greater_or_equal.1: _expr ">=" _expr
82 | less_than: _expr "<" _expr
83 | greater_than: _expr ">" _expr
84 |
85 |
86 | // ********************************************************************************
87 | // Equality
88 | // ********************************************************************************
89 | equality.1: _expr "==" _expr
90 | inequality.1: _expr "!=" _expr
91 |
92 |
93 | // ********************************************************************************
94 | // General expressions
95 | // ********************************************************************************
96 | _expr:
97 | | equality
98 | | variable ("[" constant_int "]")*
99 | | multiply_with
100 | | divide_by
101 | | modulo
102 | | adding
103 | | subtracting
104 | | "(" _expr ")"
105 | | expt
106 | | constant
107 | | constant_time
108 | | not_op
109 | | and_op
110 | | xor_op
111 | | or_op
112 | | inequality
113 | | less_or_equal
114 | | greater_or_equal
115 | | less_than
116 | | greater_than
117 | | false
118 | | true
119 | | unaryminus
120 | | if_statement_short
121 |
122 | false: FALSE
123 | FALSE: "false"
124 | true: TRUE
125 | TRUE: "true"
126 |
127 |
128 | // ********************************************************************************
129 | // Statementlist
130 | // ********************************************************************************
131 | constant_time.2: MS_DURATION
132 | constant.1: UINT | REAL
133 | constant_int.1: UINT
134 | UINT: /[0-9]+/
135 | REAL: /[0-9][.]?[0-9]*/
136 | MS_DURATION: UINT
137 | //NUMBER: /[+-]?[0-9]+/
138 |
139 | statlist: statement*
140 |
141 | statement:
142 | | immediate_assignment "_LINEBREAK_"
143 | | if_statement "_LINEBREAK_"
144 | | while_statement "_LINEBREAK_"
145 | | repeat_statement "_LINEBREAK_"
146 | | macro
147 | | macro_assignment
148 |
149 |
150 | // ********************************************************************************
151 | // Assignments
152 | // ********************************************************************************
153 | immediate_assignment.1: variable("["constant_int"]")* "=" _expr ";"
154 |
155 | macro_assignment: variable "=" _expr
156 |
157 |
158 | // ********************************************************************************
159 | // selection statement
160 | // ********************************************************************************
161 | if_statement: "if(" _expr "){" statlist "}else{" statlist "}"
162 |
163 | if_statement_short: "(" _expr "?" _expr ":" _expr ")"
164 |
165 |
166 |
167 | // ********************************************************************************
168 | // iteration statements
169 | // ********************************************************************************
170 | while_statement: "while(" _expr "){" "_LINEBREAK_" statlist "pause;" "_LINEBREAK_" statlist "}"
171 | //statlist_while: statement* "pause;" "_LINEBREAK_" statement -> statlist
172 |
173 | repeat_statement: "do:" "_LINEBREAK_" statlist "pause;" "_LINEBREAK_" statlist "if(!(" _expr ")){" "_LINEBREAK_" "goto do;" "_LINEBREAK_" "}else{" "_LINEBREAK_" statlist "}"
174 |
175 |
176 | // ********************************************************************************
177 | // Additional Terminals and_op rules
178 | // ********************************************************************************
179 | variable: NAME
180 |
181 |
182 | // ********************************************************************************
183 | // Lark statements
184 | // ********************************************************************************
185 | MULTI_LINE_COMMENT: /\(\*.*?\*\)/s
186 | SINGLE_LINE_COMMENT: /\s*/ "//" /[^\n]/*
187 |
188 | %ignore WS
189 | %ignore MULTI_LINE_COMMENT
190 | %ignore SINGLE_LINE_COMMENT
191 | %import common.WS
192 | NAME: /[_]?(?!(true|false|BOOL|INT|REAL|ARRAY\b))[a-zA-Z0-9_]\w*/
193 | MACRO_NAME: /[_]?(?!(true|false|BOOL|INT|REAL|ARRAY\b))[a-zA-Z_]\w*/
--------------------------------------------------------------------------------
/plcrex/data/grammars/st_grammar.lark:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // POU Declaration List
3 | // ********************************************************************************
4 | ?start: type pou (idcl | vdcl )* statlist? end_type -> module
5 | pou: NAME -> name
6 |
7 | type: TYPE
8 | TYPE: "PROGRAM" | "FUNCTION_BLOCK"
9 |
10 | end_type: END_TYPE
11 | END_TYPE: "END_PROGRAM" | "END_FUNCTION_BLOCK"
12 |
13 |
14 | // ********************************************************************************
15 | // Interface/Variable Declaration List
16 | // ********************************************************************************
17 | idcl: (var_input | var_output | var_in_out)* -> idcl
18 |
19 | vdcl: var_local -> vdcl
20 |
21 | dcllist: declaration*
22 |
23 | declaration:
24 | | variable ":" datatype ";"
25 | | variable ":" datatype ":=" _expr ";"
26 | | variable ":" array ";"
27 |
28 | var_input: "VAR_INPUT" dcllist "END_VAR"
29 |
30 | var_output: "VAR_OUTPUT" dcllist "END_VAR"
31 |
32 | var_in_out: "VAR_IN_OUT" dcllist "END_VAR"
33 |
34 | var_local: "VAR" dcllist "END_VAR"
35 |
36 |
37 | // ********************************************************************************
38 | // Datatypes
39 | // ********************************************************************************
40 | datatype: TYPE_BOOL | TYPE_INT | TYPE_REAL | TYPE_TIME | macro_name
41 |
42 | TYPE_BOOL: "BOOL"
43 | TYPE_INT: "INT"
44 | TYPE_REAL: "REAL"
45 | TYPE_TIME: "TIME"
46 | array: "ARRAY" "[1.." constant_int "] OF" datatype
47 | macro_name: MACRO_NAME
48 |
49 |
50 | // ********************************************************************************
51 | // Functions/User-POUs
52 | // ********************************************************************************
53 | macro:
54 | | MACRO_NAME "." macro_out
55 | | MACRO_NAME "(" macro_assignment ("," macro_assignment)* ");"
56 | | MACRO_NAME "(" _expr ("," _expr )* ");"
57 | macro_out: MACRO_NAME
58 |
59 |
60 | // ********************************************************************************
61 | // Arithmetic operators
62 | // ********************************************************************************
63 | multiply_with.1: _expr "*" _expr | "MUL(" _expr "," _expr ")"
64 | divide_by.1: _expr "/" _expr | "DIV(" _expr "," _expr ")"
65 | modulo.1: _expr "MOD" _expr | "MOD(" _expr "," _expr ")"
66 | adding.1: _expr "+" _expr | "ADD(" _expr "," _expr ")"
67 | subtracting.1: _expr "-" _expr | "SUB(" _expr "," _expr ")"
68 | expt.1: "EXPT(" _expr "," _expr ")"
69 | unaryminus.1: "-" _expr
70 |
71 |
72 | // ********************************************************************************
73 | // Boolean operators
74 | // ********************************************************************************
75 | not_op: "NOT" _expr
76 | and_op: _expr "AND" _expr | "AND(" _expr "," _expr ")"
77 | xor_op: _expr "XOR" _expr | "XOR(" _expr "," _expr ")"
78 | or_op: _expr "OR" _expr | "OR(" _expr "," _expr ")"
79 |
80 |
81 | // ********************************************************************************
82 | // Numeric operators
83 | // ********************************************************************************
84 | less_or_equal.3: _expr "<=" _expr | "LE(" _expr "," _expr ")"
85 | greater_or_equal.3: _expr ">=" _expr | "GE(" _expr "," _expr ")"
86 | less_than.1: _expr "<" _expr | "LT(" _expr "," _expr ")"
87 | greater_than.1: _expr ">" _expr | "GT(" _expr "," _expr ")"
88 |
89 |
90 | // ********************************************************************************
91 | // Equality
92 | // ********************************************************************************
93 | equality: _expr "=" _expr | "EQ(" _expr "," _expr ")"
94 | inequality.2: _expr "<>" _expr | "NE(" _expr "," _expr ")"
95 |
96 | // ********************************************************************************
97 | // General expressions
98 | // ********************************************************************************
99 | _expr:
100 | | equality
101 | | variable ("[" constant_int "]")*
102 | | multiply_with
103 | | divide_by
104 | | modulo
105 | | adding
106 | | subtracting
107 | | "(" _expr ")"
108 | | expt
109 | | constant
110 | | constant_time
111 | | not_op
112 | | and_op
113 | | xor_op
114 | | or_op
115 | | inequality
116 | | less_or_equal
117 | | greater_or_equal
118 | | less_than
119 | | greater_than
120 | | false
121 | | true
122 | | unaryminus
123 | | if_statement_short
124 |
125 | false: FALSE
126 | FALSE: "FALSE"
127 | true: TRUE
128 | TRUE: "TRUE"
129 |
130 |
131 | // ********************************************************************************
132 | // Statementlist
133 | // ********************************************************************************
134 | constant_time.2: "t#" MS_DURATION "s"
135 | constant.1: UINT | REAL
136 | constant_int.1: UINT
137 | UINT: /[0-9]+/
138 | REAL: /[0-9][.]?[0-9]*/
139 | MS_DURATION: UINT
140 | //NUMBER: /[+-]?[0-9]+/
141 |
142 | statlist: statement*
143 |
144 | statement:
145 | | immediate_assignment
146 | | if_statement
147 | | while_statement
148 | | repeat_statement
149 | | macro
150 | | macro_assignment
151 |
152 |
153 | // ********************************************************************************
154 | // Assignments
155 | // ********************************************************************************
156 | immediate_assignment.1: variable("["constant_int"]")* ":=" _expr ";"
157 |
158 | macro_assignment: variable ":=" _expr
159 |
160 |
161 | // ********************************************************************************
162 | // selection statement
163 | // ********************************************************************************
164 | if_statement: "IF" _expr "THEN" statlist "ELSE" statlist "END_IF;"
165 |
166 | if_statement_short: "SEL(" _expr "," _expr "," _expr ")"
167 |
168 |
169 |
170 | // ********************************************************************************
171 | // iteration statements
172 | // ********************************************************************************
173 | while_statement: "WHILE" _expr "DO" statlist "END_WHILE;"
174 |
175 | repeat_statement: "REPEAT" statlist "UNTIL" _expr "END_REPEAT;"
176 |
177 |
178 | // ********************************************************************************
179 | // Additional Terminals and_op rules
180 | // ********************************************************************************
181 | variable: NAME
182 |
183 |
184 | // ********************************************************************************
185 | // Lark statements
186 | // ********************************************************************************
187 | MULTI_LINE_COMMENT: /\(\*.*?\*\)/s
188 | SINGLE_LINE_COMMENT: /\s*/ "//" /[^\n]/*
189 |
190 | %ignore WS
191 | %ignore MULTI_LINE_COMMENT
192 | %ignore SINGLE_LINE_COMMENT
193 | %import common.WS
194 | NAME: /[_]?(?!(TRUE|FALSE|BOOL|INT|REAL|ARRAY\b))[a-zA-Z0-9_]\w*/
195 | MACRO_NAME: /[_]?(?!(BOOL|INT|REAL|ARRAY\b))[a-zA-Z_]\w*/
--------------------------------------------------------------------------------
/plcrex/data/grammars/qrz_grammar.lark:
--------------------------------------------------------------------------------
1 | // ********************************************************************************
2 | // POU Declaration List
3 | // ********************************************************************************
4 | ?start:
5 | | ("import" NAME ".*;")* type pou "("")" "{" (vdcl | statlist)* "}" -> module
6 | | ("import" NAME ".*;")* type pou "(" idcl ")" "{" (vdcl | statlist)* "}" -> module
7 | pou: NAME -> name
8 |
9 | type: TYPE
10 | TYPE: "module"
11 |
12 |
13 | // ********************************************************************************
14 | // Interface/Variable Declaration List
15 | // ********************************************************************************
16 | idcl: (var_input | var_output | var_in_out) ("," var_input | "," var_output | "," var_in_out)* -> idcl
17 |
18 | vdcl: var_local -> vdcl
19 |
20 | dcllist: declaration
21 |
22 | declaration:
23 | | variable ";"
24 |
25 | var_input: datatype "?" variable
26 |
27 | var_output: datatype "!" variable
28 |
29 | var_in_out: datatype variable
30 |
31 | var_local:
32 | | datatype dcllist
33 | | array datatype dcllist
34 |
35 |
36 | // ********************************************************************************
37 | // Datatypes
38 | // ********************************************************************************
39 | datatype: TYPE_BOOL | TYPE_INT | TYPE_REAL | TYPE_TIME | macro_name
40 |
41 | TYPE_BOOL: "bool"
42 | TYPE_INT: "int"
43 | TYPE_REAL: "real"
44 | TYPE_TIME: "nat"
45 | array: "[" constant_int "]"
46 | macro_name: MACRO_NAME
47 |
48 |
49 | // ********************************************************************************
50 | // Functions/User-POUs
51 | // ********************************************************************************
52 | macro:
53 | | MACRO_NAME "." macro_out
54 | | MACRO_NAME ":" NAME "(" _expr ("," _expr)* ");"
55 | macro_out: MACRO_NAME
56 |
57 |
58 | // ********************************************************************************
59 | // Arithmetic operators
60 | // ********************************************************************************
61 | multiply_with: _expr "*" _expr
62 | divide_by: _expr "/" _expr
63 | modulo: _expr "%" _expr
64 | adding: _expr "+" _expr
65 | subtracting: _expr "-" _expr
66 | expt: "exp(" _expr "," _expr ")"
67 | unaryminus: "-" _expr
68 |
69 |
70 | // ********************************************************************************
71 | // Boolean operators
72 | // ********************************************************************************
73 | not_op: "!(" _expr ")"
74 | and_op: _expr "and" _expr
75 | xor_op: _expr "xor" _expr
76 | or_op: _expr "or" _expr
77 |
78 |
79 | // ********************************************************************************
80 | // Numeric operators
81 | // ********************************************************************************
82 | less_or_equal.1: _expr "<=" _expr
83 | greater_or_equal.1: _expr ">=" _expr
84 | less_than: _expr "<" _expr
85 | greater_than: _expr ">" _expr
86 |
87 |
88 | // ********************************************************************************
89 | // Equality
90 | // ********************************************************************************
91 | equality: _expr "==" _expr | "EQ(" _expr "," _expr ")"
92 | inequality.1: _expr "!=" _expr | "NE(" _expr "," _expr ")"
93 |
94 | // ********************************************************************************
95 | // General expressions
96 | // ********************************************************************************
97 | _expr:
98 | | equality
99 | | variable ("[" constant_int "]")*
100 | | multiply_with
101 | | divide_by
102 | | modulo
103 | | adding
104 | | subtracting
105 | | "(" _expr ")"
106 | | expt
107 | | constant
108 | | not_op
109 | | and_op
110 | | xor_op
111 | | or_op
112 | | inequality
113 | | less_or_equal
114 | | greater_or_equal
115 | | less_than
116 | | greater_than
117 | | false
118 | | true
119 | | unaryminus
120 | | if_statement_short
121 |
122 | false: FALSE
123 | FALSE: "false"
124 | true: TRUE
125 | TRUE: "true"
126 |
127 |
128 | // ********************************************************************************
129 | // Statementlist
130 | // ********************************************************************************
131 | constant.1: UINT | MS_DURATION | REAL
132 | constant_int.1: UINT
133 | UINT: /[0-9]+/
134 | REAL: /[0-9][.]?[0-9]*/
135 | MS_DURATION: "t#"UINT"s"
136 | //NUMBER: /[+-]?[0-9]+/
137 |
138 | statlist: statement*
139 |
140 | statement:
141 | | immediate_assignment
142 | | if_statement
143 | | while_statement
144 | | repeat_statement
145 | | macro
146 | | pause_statement
147 | | next_statement
148 |
149 | // ********************************************************************************
150 | // Next
151 | // ********************************************************************************
152 | next_statement: "next(" variable("["constant_int"]")* ")" "=" _expr ";"
153 |
154 | // ********************************************************************************
155 | // Pause
156 | // ********************************************************************************
157 | pause_statement: PAUSE ";"
158 | PAUSE: "pause"
159 |
160 | // ********************************************************************************
161 | // Assignments
162 | // ********************************************************************************
163 | immediate_assignment: variable("["constant_int"]")* "=" _expr ";"
164 |
165 |
166 | // ********************************************************************************
167 | // selection statement
168 | // ********************************************************************************
169 | if_statement: "if(" _expr "){" statlist "}else{" statlist "}"
170 |
171 | if_statement_short: "(" _expr "?" _expr ":" _expr ")"
172 |
173 |
174 |
175 | // ********************************************************************************
176 | // iteration statements
177 | // ********************************************************************************
178 | while_statement: "while(" _expr "){" statlist "pause;" "}"
179 |
180 | repeat_statement: "do{" statlist "pause;" "}" "while(!(" _expr "));"
181 |
182 |
183 | // ********************************************************************************
184 | // Additional Terminals and_op rules
185 | // ********************************************************************************
186 | variable: NAME
187 |
188 |
189 | // ********************************************************************************
190 | // Lark statements
191 | // ********************************************************************************
192 | MULTI_LINE_COMMENT: /\(\*.*?\*\)/s
193 | SINGLE_LINE_COMMENT: /\s*/ "//" /[^\n]/*
194 |
195 | %ignore WS
196 | %ignore MULTI_LINE_COMMENT
197 | %ignore SINGLE_LINE_COMMENT
198 | %import common.WS
199 | NAME: /[_]?(?!(and|or|xor|pause|true|false|int|real\b))[a-zA-Z0-9_]\w*/
200 | MACRO_NAME: /[_]?(?!(and|or|xor|pause|true|false|int|real\b))[a-zA-Z_]\w*/
--------------------------------------------------------------------------------