├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── error ├── Makefile └── reporting.ml ├── language ├── Makefile └── st.ml ├── parser ├── Makefile ├── lexer.mll └── parser.mly └── stc.ml /.gitignore: -------------------------------------------------------------------------------- 1 | *.annot 2 | *.cmo 3 | *.cma 4 | *.cmi 5 | *.a 6 | *.o 7 | *.cmx 8 | *.cmxs 9 | *.cmxa 10 | *.bak 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Avinash 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=ocamlopt -annot -g 2 | PARSERLIB=parser.cmxa 3 | LANGUAGELIB=stlang.cmxa 4 | ERRORLIB=error.cmxa 5 | 6 | all: compile 7 | 8 | 9 | compile: 10 | $(MAKE) -e -C error/ all 11 | $(MAKE) -e -C language/ all 12 | $(MAKE) -e -C parser/ all 13 | ocamlfind $(CC) -pp "camlp4o pa_macro.cmo -UDEBUG -USDEBUG" -o \ 14 | systemjc -syntax batteries.syntax -linkpkg -package batteries \ 15 | -package sexplib -I ./language -I ./error -I ./parser \ 16 | $(ERRORLIB) $(LANGUAGELIB) $(PARSERLIB) stc.ml 17 | 18 | clean: 19 | $(MAKE) -e -C language/ clean 20 | $(MAKE) -e -C error/ clean 21 | $(MAKE) -e -C parser/ clean 22 | rm -rf *.ll *.lle *.bc *.s *.dot *.grf *.part* gmon.out TAGS *.mli *.cm* *.o systemjc \ 23 | *.xml *.annot *_spi* *_ver* *.pml.trail 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | st 2 | == 3 | 4 | IEC-61131-3 Structured text parser 5 | -------------------------------------------------------------------------------- /error/Makefile: -------------------------------------------------------------------------------- 1 | LANGDIR=../language 2 | LANGLIB=systemj.cmxa 3 | CC=ocamlopt -annot -g 4 | SRC=reporting.ml 5 | 6 | all: error 7 | $(CC) -a *.cmx -o error.cmxa 8 | 9 | error: 10 | $(CC) -I $(LANGDIR) $(LANGLIB) -c $(SRC) 11 | cp reporting.cmi ../parser/error.cmi 12 | 13 | clean: 14 | rm -rf *.cm* *.a *.o *.annot 15 | -------------------------------------------------------------------------------- /error/reporting.ml: -------------------------------------------------------------------------------- 1 | (* 2 | 3 | Author: Avinash Malik 4 | 5 | Purpose: Error reporting and assoicated things 6 | 7 | Date: Sun Jun 3 17:17:17 IST 2012 8 | 9 | *) 10 | 11 | let get_line_and_column = function 12 | | (x,y) -> ((string_of_int x) ^ "," ^ (string_of_int y) ^ ": ") 13 | -------------------------------------------------------------------------------- /language/Makefile: -------------------------------------------------------------------------------- 1 | OCMLOPTS=-a 2 | OCMALDEBUG=-g 3 | CC=ocamlopt -annot -g 4 | SRC=st.ml 5 | TYPECONV=`ocamlfind query type_conv` 6 | SEXPLIB=`ocamlfind query sexplib` 7 | BATDIR=`ocamlfind query batteries` 8 | 9 | all: stlang.cmxa 10 | 11 | stlang.cmxa: check 12 | $(CC) $(OCMLOPTS) st.cmx -o $@ 13 | 14 | check: 15 | @echo $(TYPECONV) 16 | $(CC) -pp "camlp4o -I $(TYPECONV) -I $(SEXPLIB) \ 17 | pa_type_conv.cma pa_sexp_conv.cma pa_macro.cmo -UDEBUG" -I \ 18 | $(BATDIR) -I $(SEXPLIB) -I ../error -c $(SRC) 19 | clean: 20 | rm -rf *cm* *o *a *mli *.annot 21 | -------------------------------------------------------------------------------- /language/st.ml: -------------------------------------------------------------------------------- 1 | (* 2 | Author: Avinash Malik 3 | The IEC61131-3 Structured text language. 4 | Thu Mar 20 17:22:33 NZDT 2014 5 | *) 6 | 7 | open Sexplib.Std 8 | open Sexplib.Sexp 9 | module L = Batteries.List 10 | module String = Batteries.String 11 | 12 | let (|>) x f = f x 13 | 14 | exception Internal_error of string 15 | 16 | type data_type = 17 | | BM_SINT 18 | | BM_INT 19 | | BM_DINT 20 | | BM_LINT 21 | | BM_USINT 22 | | BM_UINT 23 | | BM_UDINT 24 | | BM_ULINT 25 | | BM_ANY_INT 26 | | BM_BOOL 27 | | BM_BYTE 28 | | BM_WORD 29 | | BM_DWORD 30 | | BM_LWORD 31 | | BM_ANY_BIT 32 | | BM_REAL 33 | | BM_LREAL 34 | | BM_ANY_REAL 35 | | BM_STRING 36 | | BM_TIME 37 | | BM_DATE 38 | | BM_TOD 39 | | BM_DT 40 | | BM_ANY 41 | with sexp 42 | 43 | type op_code = 44 | | EXPR_ADD 45 | | EXPR_SUB 46 | | EXPR_DIV 47 | | EXPR_MOD 48 | | EXPR_AND 49 | | EXPR_NE 50 | | EXPR_EQ 51 | | EXPR_LT 52 | | EXPR_GT 53 | | EXPR_LE 54 | | EXPR_GE 55 | | EXPR_MUL 56 | | EXPR_NOT 57 | | EXPR_OR 58 | | EXPR_POW 59 | | EXPR_UNARY 60 | | EXPR_XOR 61 | | FB_CALL 62 | | FB_DECLARE 63 | | FB_VAR 64 | | FB_VARIABLE 65 | | FB_VARLIST 66 | | FUNC_CALL 67 | | FUNCTION_DECLARE 68 | | LITERAL 69 | | NOOP 70 | | ST_ASSIGNMENT 71 | | ST_CASE 72 | | ST_CASE_ELEMENT 73 | | ST_CASE_LIST 74 | | ST_EXIT 75 | | ST_FOR_LOOP 76 | | ST_IF_ELSIF 77 | | ST_IF_STMT 78 | | ST_REPEAT 79 | | ST_RETURN 80 | | ST_STATEMENT 81 | | ST_WHILE 82 | | TYPE_ARRAY_INITIAL_LIST 83 | | TYPE_ARRAY_SUBRANGELIST 84 | | TYPE_DECLARE 85 | | TYPE_DECLARE_LIST 86 | | TYPE_DECLARE_STRUCT 87 | | TYPE_DEF 88 | | TYPE_SPEC 89 | | TYPE_SPEC_ARRAY 90 | | TYPE_SPEC_ENUM 91 | | TYPE_SPEC_ENUM_LIST 92 | | TYPE_SPEC_SUBRANGE 93 | | TYPE_STRUCT_DECLARE 94 | | TYPE_STRUCT_ELEMENT 95 | | TYPE_STRUCT_INITIALISATION 96 | | TYPE_STRUCT_INITIALISED 97 | | VARIABLE_ARRAY 98 | | VARIABLE_ARRAY_SUBSCRIPT 99 | | VARIABLE_DECLARE 100 | | VARIABLE_DECLARE_LIST 101 | | VARIABLE_EXTERNAL 102 | | VARIABLE_EXTERNAL_LIST 103 | | VARIABLE_GLOBAL 104 | | VARIABLE_GLOBAL_LIST 105 | | VARIABLE_IN_OUT 106 | | VARIABLE_INPUT 107 | | VARIABLE_LIST 108 | |VARIABLE_LOCAL 109 | |VARIABLE_LOCAL_CONSTANT 110 | |VARIABLE_LOCAL_RETAIN 111 | |VARIABLE_LOCATED 112 | |VARIABLE_LOCATEDLIST 113 | |VARIABLE_OUTPUT 114 | |VARIABLE_OUTPUT_RETAIN 115 | |VARIABLE_STRING 116 | |VARIABLE_STRUCT_ELEMENT 117 | with sexp 118 | 119 | type parse_tree_data = 120 | | TREE_LEAF 121 | | LITERAL_INTEGER 122 | | LITERAL_REAL 123 | | LITERAL_STRING 124 | | LITERAL_SUBRANGE 125 | | LITERAL_ID 126 | with sexp 127 | 128 | type leaf_data = 129 | | Int of int 130 | | Real of float 131 | | Array of (int * int) 132 | with sexp 133 | 134 | type parse_leaf = { 135 | mutable t:data_type option; 136 | mutable leaf_type:parse_tree_data option; 137 | mutable leaf:parse_tree option; 138 | mutable leaf_data:leaf_data option; 139 | mutable literal_string:string option; 140 | mutable id:string option; 141 | mutable buff:string option; 142 | } 143 | and parse_tree = { 144 | mutable op:op_code option; 145 | mutable result:parse_leaf option; 146 | mutable n:int; 147 | mutable elements: parse_leaf list; 148 | location:(int * int) option; 149 | } with sexp 150 | 151 | 152 | (* TODO *) 153 | (* let add_variable *) 154 | (* let funcblk_type id *) 155 | (* let add_variables *) 156 | 157 | let add_leaf dest src = 158 | dest.n <- dest.n + 1; 159 | let src_t = (function Some x -> x.t | None -> None ) src.result in 160 | let toadd = {t=src_t;leaf_type=Some TREE_LEAF;leaf=Some src; 161 | leaf_data=None; literal_string=None;id=None; 162 | buff=None} in 163 | dest.elements <- dest.elements @ [toadd] 164 | 165 | let transfer_leaf dest src = 166 | dest.n <- dest.n + src.n; 167 | dest.elements <- dest.elements @ src.elements 168 | 169 | let make_noop = 170 | {op=Some NOOP;result=None;n=0;elements=[];location=None} 171 | 172 | let make_literal_int s = 173 | let result = {t=Some BM_ANY_INT;leaf_type=Some LITERAL_INTEGER;leaf_data=Some (Int (int_of_string s));leaf=None; 174 | literal_string=None; id=None; buff=None} in 175 | {op=Some LITERAL;result=Some result;n=0;elements=[];location=None} 176 | 177 | 178 | let make_literal_real s idt = 179 | let result = {t=Some idt;leaf_type=Some LITERAL_REAL;leaf_data=Some (Real (float_of_string s));leaf=None; 180 | literal_string=None; id=None; buff=None} in 181 | {op=Some LITERAL;result=Some result;n=0;elements=[];location=None} 182 | 183 | let make_literal_string s = 184 | let result = {t=Some BM_STRING;leaf_type=Some LITERAL_STRING;leaf_data=None;leaf=None; 185 | literal_string=Some s; id=None; buff=None} in 186 | {op=Some LITERAL;result=Some result;n=0;elements=[];location=None} 187 | 188 | let make_literal_id s = 189 | let result = {t=None;leaf_type=Some LITERAL_ID;leaf_data=None;leaf=None; 190 | literal_string=None; id=Some s; buff=None} in 191 | {op=Some LITERAL;result=Some result;n=0;elements=[];location=None} 192 | 193 | let make_literal_subrange = function 194 | | (Some rlo, Some rhi) -> 195 | (match (rlo.leaf_data, rhi.leaf_data) with 196 | | (Some (Int lo), Some (Int hi)) -> 197 | let result = {t=None;leaf_type=Some LITERAL_SUBRANGE;leaf_data=Some (Array (lo,hi));leaf=None; 198 | literal_string=None; id=None; buff=None} in 199 | {op=Some LITERAL;result=Some result;n=0;elements=[];location=None} 200 | | _ -> raise (Internal_error "LO/HI of sub-range are not integer types!") 201 | ) 202 | | _ -> raise (Internal_error "Array subranges are not initialized!") 203 | 204 | let concat_leaf src op = 205 | if (match src.op with Some x -> x | None -> raise (Internal_error (("Source parse tree has type Opcode: " 206 | ^ (to_string_hum (sexp_of_parse_tree src)))))) = op then src 207 | else 208 | let ret = {op=Some op;result=None;n=0;elements=[];location=None} in 209 | add_leaf ret src; 210 | ret 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /parser/Makefile: -------------------------------------------------------------------------------- 1 | OCMLOPTS=-a 2 | OCMXALDEBUG=-g 3 | CC=ocamlopt -g 4 | YACC=ocamlyacc 5 | LEX=ocamllex 6 | LANGDIR=../language 7 | 8 | 9 | all: parser 10 | 11 | parser: 12 | $(YACC) -v parser.mly 13 | $(LEX) lexer.mll 14 | $(CC) -I $(LANGDIR) -c parser.mli 15 | $(CC) -c lexer.ml 16 | $(CC) -I $(LANGDIR) -c parser.ml 17 | $(CC) -a lexer.cmx parser.cmx -o parser.cmxa 18 | 19 | clean: 20 | rm -rf *o *cm* parser.mli lexer.mli *output lexer.ml parser.ml language.mli error.mli *.a 21 | -------------------------------------------------------------------------------- /parser/lexer.mll: -------------------------------------------------------------------------------- 1 | { 2 | (* The header *) 3 | open Lexing;; 4 | open Parser;; 5 | } 6 | 7 | rule lexer = parse 8 | | [' ' '\t'] {lexer lexbuf} 9 | | "0---T" {TOF} 10 | | "ADD" {ADD} 11 | | "ACTION" {ACTION} 12 | | "ANDN" {ANDN} 13 | | "AND" {AND} 14 | | "ARRAY" {ARRAY} 15 | | "AT" {AT} 16 | | "BOOL" {BOOL} 17 | | "BY" {BY} 18 | | "BYTE" {BYTE} 19 | | "CALCN" {CALCN} 20 | | "CALC" {CALC} 21 | | "CAL" {CAL} 22 | | "CD" {CD} 23 | | "CLK" {CLK} 24 | | "CONCAT" {CONCAT} 25 | | "CONSTANT" {CONSTANT} 26 | | "CTD" {CTD} 27 | | "CTUD" {CTUD} 28 | | "CTU" {CTU} 29 | | "CU" {CU} 30 | | "DATE_AND_TIME" {DATE_AND_TIME} 31 | | "DATE" {DATE} 32 | | "DINT" {DINT} 33 | | "DIV" {DIV} 34 | | "DO" {DO} 35 | | "DT" {DATE_AND_TIME} 36 | | "DWORD" {DWORD} 37 | | "ELSE" {ELSE} 38 | | "ELSIF" {ELSIF} 39 | | "END_ACTION" {END_ACTION} 40 | | "END_CASE" {END_CASE} 41 | | "END_FOR" {END_FOR} 42 | | "END_FUNCTION_BLOCK" {END_FUNCTION_BLOCK} 43 | | "END_FUNCTION" {END_FUNCTION} 44 | | "END_IF" {END_IF} 45 | | "END_PROGRAM" {END_PROGRAM} 46 | | "END_REPEAT" {END_REPEAT} 47 | | "END_RESOURCE" {END_RESOURCE} 48 | | "END_STEP" {END_STEP} 49 | | "END_STRUCT" {END_STRUCT} 50 | | "END_VAR" {END_VAR} 51 | | "END_WHILE" {END_WHILE} 52 | | "EQ" {EQ} 53 | | "EXIT" {EXIT} 54 | | "EXPT" {EXPT} 55 | | "FALSE" {FALSE} 56 | | "F_EDGE" {F_EDGE} 57 | | "FOR" {FOR} 58 | | "FROM" {FROM} 59 | | "F_TRIG" {F_TRIG} 60 | | "FUNCTION_BLOCK" {FUNCTION_BLOCK} 61 | | "FUNCTION" {FUNCTION} 62 | | "GE" {GE} 63 | | "GT" {GT} 64 | | "IF" {IF} 65 | | "INITIAL_STEP" {INITIAL_STEP} 66 | | "IN" {IN} 67 | | "INSERT" {INSERT} 68 | | "INTERVAL" {INTERVAL} 69 | | "INT" {INT} 70 | | "JMPCN" {JMPCN} 71 | | "JMPC" {JMPC} 72 | | "JMP" {JMP} 73 | | "LD" {LD} 74 | | "LE" {LE} 75 | | "LIMIT" {LIMIT} 76 | | "LINT" {LINT} 77 | | "LREAL" {LREAL} 78 | | "LT" {LT} 79 | | "LWORD" {LWORD} 80 | | "MAX" {MAX} 81 | | "MIN" {MIN} 82 | | "MOD" {MOD} 83 | | "MOVE" {MOVE} 84 | | "MUL" {MUL} 85 | | "MUX" {MUX} 86 | | "NE" {NE} 87 | | "NOT" {NOT} 88 | | "OF" {OF} 89 | | "ON" {ON} 90 | | "ORN" {ORN} 91 | | "OR" {OR} 92 | | "PRIORITY" {PRIORITY} 93 | | "PROGRAM" {PROGRAM} 94 | | "REAL" {REAL} 95 | | "R_EDGE" {R_EDGE} 96 | | "REPEAT" {REPEAT} 97 | | "RESOURCE" {RESOURCE} 98 | | "RETAIN" {RETAIN} 99 | | "RETURN" {RETURN} 100 | | "RS" {RS} 101 | | "R_TRIG" {R_TRIG} 102 | | "SEL" {SEL} 103 | | "SINGLE" {SINGLE} 104 | | "SINT" {SINT} 105 | | "SR" {SR} 106 | | "STEP" {STEP} 107 | | "ST" {ST} 108 | | "STRING" {STRING} 109 | | "STRUCT" {STRUCT} 110 | | "SUB" {SUB} 111 | | "T---0"{TON} 112 | | "THEN" {THEN} 113 | | "TIME_OF_DAY" {TIME_OF_DAY} 114 | | "TIME" {TIME} 115 | | "TOF" {TOF} 116 | | "TON" {TON} 117 | | "TO" {TO} 118 | | "TOD" {TIME_OF_DAY} 119 | | "TP" {TP} 120 | | "TRUE" {TRUE} 121 | | "UDINT" {UDINT} 122 | | "UINT" {UINT} 123 | | "ULINT" {ULINT} 124 | | "UNTIL" {UNTIL} 125 | | "USINT" {USINT} 126 | | "VAR_ACCESS" {VAR_ACCESS} 127 | | "VAR_EXTERNAL" {VAR_EXTERNAL} 128 | | "VAR_GLOBAL" {VAR_GLOBAL} 129 | | "VAR_IN_OUT" {VAR_IN_OUT} 130 | | "VAR_INPUT" {VAR_INPUT} 131 | | "VAR_OUTPUT" {VAR_OUTPUT} 132 | | "VAR" {VAR} 133 | | "WHILE" {WHILE} 134 | | "WITH" {WITH} 135 | | "WORD" {WORD} 136 | | "XORN" {XORN} 137 | | "XOR" {XOR} 138 | | "//"_*'\n' {let () = new_line lexbuf in lexer lexbuf} 139 | | '\n' {let () = new_line lexbuf in lexer lexbuf} 140 | | ['0'-'9']+ {TInt (lexeme lexbuf)} (* an integer *) 141 | | ['0'-'9']+'.'['0'-'9']+ {TFloat (lexeme lexbuf)} (* a floating number *) 142 | | "<>" {OPER_NE} 143 | | "<=" {OPER_LE} 144 | | ">=" {OPER_GE} 145 | | "**" {OPER_EXP} 146 | | ['A'-'Z' 'a'-'z']['A'-'Z' 'a'-'z' '0'-'9' '_']* {IDENTIFIER (lexeme lexbuf)} (* any identifier a letter followed by anything, except a '$' sign*) 147 | | "(*" {comment 1 lexbuf} (* start of a comment *) 148 | | _ {lexer lexbuf} (* leave anything else *) 149 | | eof {TEof} 150 | and comment depth = parse 151 | | "(*" {comment (depth + 1) lexbuf} 152 | | "*)" {if depth = 1 then lexer lexbuf else comment (depth-1) lexbuf} (*Nested comments are allowed*) 153 | | '\n' {let () = new_line lexbuf in comment depth lexbuf} 154 | | _ {comment depth lexbuf} 155 | 156 | { 157 | (* The tail for now do nothing*) 158 | } 159 | -------------------------------------------------------------------------------- /parser/parser.mly: -------------------------------------------------------------------------------- 1 | %{ 2 | (* This is the header *) 3 | (* let _ = Parsing.set_trace true in () *) 4 | let counter = ref 0 5 | let line_nums = Hashtbl.create (1000) 6 | let parse_error s = 7 | let mypos = Parsing.symbol_start_pos() in 8 | print_string (s ^ " (line number: "); 9 | print_int mypos.Lexing.pos_lnum; 10 | print_string (", column number: " ^ (string_of_int (mypos.Lexing.pos_cnum - mypos.Lexing.pos_bol))); 11 | print_endline ")"; 12 | flush stdout 13 | let ln () = 14 | let mypos = Parsing.symbol_start_pos() in 15 | let cnum = (mypos.Lexing.pos_cnum) - (mypos.Lexing.pos_bol) in 16 | (mypos.Lexing.pos_lnum,cnum) 17 | %} 18 | 19 | /* Constructors with an argument */ 20 | %token IDENTIFIER TInt TFloat 21 | 22 | /* Constant constructors */ 23 | %token OPER_NE 24 | %token OPER_LE 25 | %token OPER_GE 26 | %token OPER_EXP 27 | %token ACTION 28 | %token ADD 29 | %token AND 30 | %token ANDN 31 | %token ARRAY 32 | %token AT 33 | %token BOOL 34 | %token BY 35 | %token BYTE 36 | %token CAL 37 | %token CALC 38 | %token CALCN 39 | %token CASE 40 | %token CD 41 | %token CLK 42 | %token CONCAT 43 | %token CONSTANT 44 | %token CTU 45 | %token CTD 46 | %token CTUD 47 | %token CU 48 | %token DATE 49 | %token DATE_AND_TIME 50 | %token DINT 51 | %token DIV 52 | %token DO 53 | %token DWORD 54 | %token END_ACTION 55 | %token END_CASE 56 | %token END_FOR 57 | %token END_FUNCTION 58 | %token END_FUNCTION_BLOCK 59 | %token END_PROGRAM 60 | %token END_REPEAT 61 | %token END_STEP 62 | %token END_RESOURCE 63 | %token END_STRUCT 64 | %token END_TRANSITION 65 | %token END_VAR 66 | %token END_WHILE 67 | %token END_IF 68 | %token ELSE 69 | %token ELSIF 70 | %token EQ 71 | %token EXIT 72 | %token EXPT 73 | %token F_EDGE 74 | %token F_TRIG 75 | %token FALSE 76 | %token FOR 77 | %token FROM 78 | %token FUNCTION 79 | %token FUNCTION_BLOCK 80 | %token GE 81 | %token GT 82 | %token IF 83 | %token IN 84 | %token INSERT 85 | %token INT 86 | %token INITIAL_STEP 87 | %token INTERVAL 88 | %token JMP 89 | %token JMPC 90 | %token JMPCN 91 | %token LD 92 | %token LDN 93 | %token LE 94 | %token LIMIT 95 | %token LT 96 | %token LINT 97 | %token LREAL 98 | %token LWORD 99 | %token MAX 100 | %token MIN 101 | %token MOD 102 | %token MOVE 103 | %token MUL 104 | %token MUX 105 | %token NE 106 | %token NOT 107 | %token OF 108 | %token ON 109 | %token OR 110 | %token ORN 111 | %token PROGRAM 112 | %token PRIORITY 113 | %token PT 114 | %token PV 115 | %token R_EDGE 116 | %token R_TRIG 117 | %token REAL 118 | %token REPEAT 119 | %token RESOURCE 120 | %token RET 121 | %token RETAIN 122 | %token RETC 123 | %token RETCN 124 | %token RETURN 125 | %token RS 126 | %token S1 127 | %token SEL 128 | %token SINGLE 129 | %token SINT 130 | %token SQRT 131 | %token SR 132 | %token ST 133 | %token STEP 134 | %token STRING 135 | %token STRUCT 136 | %token SUB 137 | %token THEN 138 | %token TIME 139 | %token TIME_OF_DAY 140 | %token TO 141 | %token TOF 142 | %token TON 143 | %token TP 144 | %token TRANSITION 145 | %token TRUE 146 | %token UDINT 147 | %token UINT 148 | %token ULINT 149 | %token UNTIL 150 | %token USINT 151 | %token VAR 152 | %token VAR_ACCESS 153 | %token VAR_EXTERNAL 154 | %token VAR_GLOBAL 155 | %token VAR_IN_OUT 156 | %token VAR_INPUT 157 | %token VAR_OUTPUT 158 | %token WHILE 159 | %token WITH 160 | %token WORD 161 | %token XOR 162 | %token XORN 163 | %token TEof 164 | 165 | /* operator associative rules */ 166 | 167 | /* The start of the parsing function */ 168 | %start start 169 | %type start 170 | 171 | %% 172 | /* These are the parsing rules */ 173 | 174 | start: 175 | | TEof {St.make_noop} 176 | | function_block_declaration TEof {$1} 177 | ; 178 | 179 | constant: 180 | | numeric_literal {$1} 181 | | '"' IDENTIFIER '"' {St.make_literal_string $2} 182 | ; 183 | 184 | numeric_literal: 185 | | integer_literal {$1} 186 | | TFloat {St.make_literal_real $1 St.BM_ANY_REAL} /*This is the real_literal, only float type are supported for now!*/ 187 | | TRUE { 188 | let res = {St.t=Some St.BM_BOOL;St.leaf_type=Some St.LITERAL_INTEGER; St.literal_string= Some "1"; St.leaf=None; 189 | St.id=None; St.buff=None; St.leaf_data=None} in 190 | {St.op = Some (St.ST_CASE_ELEMENT); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())}} 191 | | FALSE 192 | { 193 | let res = {St.t=Some St.BM_BOOL;St.leaf_type=Some St.LITERAL_INTEGER; St.literal_string= Some "0"; St.leaf=None; 194 | St.id=None; St.buff=None; St.leaf_data=None} in 195 | {St.op = Some (St.ST_CASE_ELEMENT); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())}} 196 | ; 197 | 198 | integer_literal: 199 | | signed_integer {$1} 200 | ; 201 | 202 | signed_integer: 203 | | TInt {St.make_literal_int $1} 204 | | '+' TInt {St.make_literal_int $2} 205 | | '-' TInt {St.make_literal_int ("-" ^ $2)} 206 | ; 207 | 208 | elementary_type_name: 209 | | numeric_type_name {$1} 210 | | date_type_name {$1} 211 | | STRING { 212 | let res = {St.t=Some St.BM_STRING;St.leaf_type=None; St.literal_string= None; St.leaf=None; 213 | St.id=None; St.buff=None; St.leaf_data=None} in 214 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 215 | } 216 | | TIME { 217 | let res = {St.t=Some St.BM_TIME;St.leaf_type=None; St.literal_string= None; St.leaf=None; 218 | St.id=None; St.buff=None; St.leaf_data=None} in 219 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 220 | } 221 | | bit_string_type_name {$1} 222 | ; 223 | 224 | numeric_type_name: 225 | | integer_type_name {$1} 226 | | real_type_name {$1} 227 | ; 228 | 229 | integer_type_name: 230 | | signed_integer_type_name {$1} 231 | | unsigned_integer_type_name {$1} 232 | ; 233 | 234 | signed_integer_type_name: 235 | | SINT { 236 | let res = {St.t=Some St.BM_SINT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 237 | St.id=None; St.buff=None; St.leaf_data=None} in 238 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 239 | } 240 | | INT { 241 | let res = {St.t=Some St.BM_INT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 242 | St.id=None; St.buff=None; St.leaf_data=None} in 243 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 244 | } 245 | | DINT { 246 | let res = {St.t=Some St.BM_DINT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 247 | St.id=None; St.buff=None; St.leaf_data=None} in 248 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 249 | } 250 | | LINT { 251 | let res = {St.t=Some St.BM_LINT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 252 | St.id=None; St.buff=None; St.leaf_data=None} in 253 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 254 | } 255 | ; 256 | 257 | unsigned_integer_type_name: 258 | | USINT { 259 | let res = {St.t=Some St.BM_USINT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 260 | St.id=None; St.buff=None; St.leaf_data=None} in 261 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 262 | } 263 | | UINT { 264 | let res = {St.t=Some St.BM_UINT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 265 | St.id=None; St.buff=None; St.leaf_data=None} in 266 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 267 | } 268 | | UDINT { 269 | let res = {St.t=Some St.BM_UDINT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 270 | St.id=None; St.buff=None; St.leaf_data=None} in 271 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 272 | } 273 | | ULINT { 274 | let res = {St.t=Some St.BM_ULINT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 275 | St.id=None; St.buff=None; St.leaf_data=None} in 276 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 277 | } 278 | ; 279 | 280 | real_type_name: 281 | | REAL { 282 | let res = {St.t=Some St.BM_REAL;St.leaf_type=None; St.literal_string= None; St.leaf=None; 283 | St.id=None; St.buff=None; St.leaf_data=None} in 284 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 285 | } 286 | | LREAL { 287 | let res = {St.t=Some St.BM_LREAL;St.leaf_type=None; St.literal_string= None; St.leaf=None; 288 | St.id=None; St.buff=None; St.leaf_data=None} in 289 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 290 | } 291 | ; 292 | 293 | date_type_name: 294 | | DATE { 295 | let res = {St.t=Some St.BM_DATE;St.leaf_type=None; St.literal_string= None; St.leaf=None; 296 | St.id=None; St.buff=None; St.leaf_data=None} in 297 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 298 | } 299 | | TIME_OF_DAY { 300 | let res = {St.t=Some St.BM_TOD;St.leaf_type=None; St.literal_string= None; St.leaf=None; 301 | St.id=None; St.buff=None; St.leaf_data=None} in 302 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 303 | } 304 | | DATE_AND_TIME { 305 | let res = {St.t=Some St.BM_DT;St.leaf_type=None; St.literal_string= None; St.leaf=None; 306 | St.id=None; St.buff=None; St.leaf_data=None} in 307 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 308 | } 309 | ; 310 | 311 | bit_string_type_name: 312 | | BOOL { 313 | let res = {St.t=Some St.BM_BOOL;St.leaf_type=None; St.literal_string= None; St.leaf=None; 314 | St.id=None; St.buff=None; St.leaf_data=None} in 315 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 316 | } 317 | | BYTE { 318 | let res = {St.t=Some St.BM_BYTE;St.leaf_type=None; St.literal_string= None; St.leaf=None; 319 | St.id=None; St.buff=None; St.leaf_data=None} in 320 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 321 | } 322 | | WORD { 323 | let res = {St.t=Some St.BM_WORD;St.leaf_type=None; St.literal_string= None; St.leaf=None; 324 | St.id=None; St.buff=None; St.leaf_data=None} in 325 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 326 | } 327 | | DWORD { 328 | let res = {St.t=Some St.BM_DWORD;St.leaf_type=None; St.literal_string= None; St.leaf=None; 329 | St.id=None; St.buff=None; St.leaf_data=None} in 330 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 331 | } 332 | | LWORD { 333 | let res = {St.t=Some St.BM_LWORD;St.leaf_type=None; St.literal_string= None; St.leaf=None; 334 | St.id=None; St.buff=None; St.leaf_data=None} in 335 | {St.op = Some (St.TYPE_DEF); St.elements=[];St.result=Some res;St.n=0;St.location=Some (ln())} 336 | } 337 | ; 338 | 339 | derived_type_name: 340 | | simple_type_name {$1} 341 | ; 342 | 343 | simple_type_name: 344 | | IDENTIFIER {St.make_literal_id $1} 345 | ; 346 | 347 | simple_spec_init: 348 | | simple_specification { 349 | let ret = {St.op = Some (St.TYPE_SPEC); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 350 | let () = St.add_leaf ret $1 in 351 | let () = St.add_leaf ret (St.make_noop) in ret 352 | } 353 | | simple_specification ':' '=' constant { 354 | let ret = {St.op = Some (St.TYPE_SPEC); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 355 | let () = St.add_leaf ret $1 in 356 | let () = St.add_leaf ret $4 in ret 357 | } 358 | ; 359 | 360 | simple_specification: 361 | | elementary_type_name {$1} 362 | | simple_type_name {$1} 363 | ; 364 | 365 | subrange_spec_init: 366 | | subrange_specification { 367 | let ret = {St.op = Some (St.TYPE_SPEC); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 368 | let () = St.add_leaf ret $1 in 369 | let () = St.add_leaf ret (St.make_noop) in ret 370 | } 371 | | subrange_specification ':' '=' signed_integer { 372 | let ret = {St.op = Some (St.TYPE_SPEC); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 373 | let () = St.add_leaf ret $1 in 374 | let () = St.add_leaf ret $4 in ret 375 | } 376 | ; 377 | 378 | subrange_specification: 379 | | integer_type_name '(' subrange ')' { 380 | let ret = {St.op = Some (St.TYPE_SPEC_SUBRANGE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 381 | let () = St.add_leaf ret $1 in 382 | let () = St.add_leaf ret $3 in ret 383 | } 384 | | simple_type_name { 385 | let ret = {St.op = Some (St.TYPE_SPEC_SUBRANGE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 386 | let () = St.add_leaf ret $1 in 387 | let () = St.add_leaf ret (St.make_noop) in ret 388 | } 389 | ; 390 | 391 | subrange: 392 | | signed_integer '.' '.' signed_integer {St.make_literal_subrange ($1.St.result,$4.St.result)} 393 | ; 394 | 395 | enumerated_spec_init: 396 | | simple_type_name ':' '=' simple_type_name { 397 | let ret = {St.op = Some (St.TYPE_SPEC); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 398 | let () = St.add_leaf ret $1 in 399 | let () = St.add_leaf ret $4 in ret 400 | } 401 | | simple_type_name { 402 | let ret = {St.op = Some (St.TYPE_SPEC_ENUM); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 403 | let () = St.add_leaf ret $1 in 404 | let () = St.add_leaf ret (St.make_noop) in ret 405 | } 406 | ; 407 | 408 | enumerated_specification: 409 | | '(' enum_spec_10 ')' { 410 | let ret = {St.op = Some (St.TYPE_SPEC_ENUM); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 411 | let () = St.add_leaf ret $2 in ret 412 | } 413 | | simple_type_name { 414 | let ret = {St.op = Some (St.TYPE_SPEC_ENUM); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 415 | let () = St.add_leaf ret $1 in ret 416 | } 417 | ; 418 | 419 | enum_spec_10: 420 | | simple_type_name { 421 | let ret = {St.op = Some (St.TYPE_SPEC_ENUM_LIST); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 422 | let () = St.add_leaf ret $1 in ret 423 | } 424 | | enum_spec_10 ',' simple_type_name { 425 | let () = St.add_leaf $1 $3 in $1 426 | } 427 | ; 428 | 429 | variable: 430 | | symbolic_variable {$1} 431 | ; 432 | 433 | symbolic_variable: 434 | | simple_type_name {$1} 435 | | multi_element_variable {$1} 436 | ; 437 | 438 | multi_element_variable: 439 | | array_variable {$1} 440 | | structured_variable {$1} 441 | ; 442 | 443 | array_variable: 444 | | subscripted_variable '[' subscript_list ']' { 445 | let ret = {St.op = Some (St.VARIABLE_ARRAY); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 446 | let () = St.add_leaf ret $1 in 447 | let () = St.add_leaf ret $3 in ret 448 | } 449 | ; 450 | 451 | subscripted_variable: 452 | | symbolic_variable {$1} 453 | ; 454 | 455 | subscript_list: 456 | | subscript { 457 | let ret = {St.op = Some (St.VARIABLE_ARRAY_SUBSCRIPT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 458 | let () = St.add_leaf ret $1 in ret 459 | } 460 | | subscript_list ',' subscript {let () = St.add_leaf $1 $3 in $1} 461 | ; 462 | 463 | subscript : 464 | | expression {$1} 465 | ; 466 | 467 | structured_variable: 468 | | symbolic_variable '.' simple_type_name { 469 | let ret = {St.op = Some (St.VARIABLE_STRUCT_ELEMENT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 470 | let () = St.add_leaf ret $1 in 471 | let () = St.add_leaf ret $3 in ret 472 | } 473 | ; 474 | 475 | /* TODO: Put the input declaration unto expressions here*/ 476 | 477 | input_declarations: 478 | | VAR_INPUT input_decl END_VAR {$2} 479 | ; 480 | 481 | input_decl: 482 | | input_declaration ';' { 483 | let ret = {St.op = Some (St.VARIABLE_INPUT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 484 | let () = St.add_leaf ret $1 in ret 485 | } 486 | | input_decl input_declaration ';' { 487 | let () = St.add_leaf $1 $2 in $1 488 | } 489 | ; 490 | 491 | input_declaration: 492 | | var_init_decl {$1} 493 | | edge_declaration {$1} 494 | ; 495 | 496 | edge_declaration: 497 | | var1_list ':' BOOL R_EDGE {$1} 498 | | var1_list ':' BOOL F_EDGE {$1} 499 | ; 500 | 501 | var_init_decl: 502 | | var1_init_decl {$1} 503 | | fb_name_decl {$1} 504 | ; 505 | 506 | varinitdecl: 507 | | var_init_decl ';' { 508 | let ret = {St.op = Some (St.VARIABLE_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 509 | let () = St.add_leaf ret $1 in ret 510 | } 511 | | varinitdecl var_init_decl ';' { 512 | let () = St.add_leaf $1 $2 in $1 513 | } 514 | ; 515 | 516 | var1_init_decl: 517 | | var1_list ':' simple_spec_init { 518 | let ret = {St.op = Some (St.VARIABLE_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 519 | let () = St.add_leaf ret $1 in 520 | let () = St.add_leaf ret $3 in ret 521 | } 522 | | var1_list ':' subrange_spec_init { 523 | let ret = {St.op = Some (St.VARIABLE_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 524 | let () = St.add_leaf ret $1 in 525 | let () = St.add_leaf ret $3 in ret 526 | } 527 | | var1_list ':' enumerated_spec_init { 528 | let ret = {St.op = Some (St.VARIABLE_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 529 | let () = St.add_leaf ret $1 in 530 | let () = St.add_leaf ret $3 in ret 531 | } 532 | ; 533 | 534 | var1_list: 535 | | simple_type_name { 536 | let ret = {St.op = Some (St.VARIABLE_LIST); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 537 | let () = St.add_leaf ret $1 in ret 538 | } 539 | | var1_list ',' simple_type_name { 540 | let () = St.add_leaf $1 $3 in $1 541 | } 542 | ; 543 | 544 | fb_name_decl: 545 | | var1_list ':' function_block_type_name { 546 | let fb_tree = {St.op = Some (St.TYPE_SPEC); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 547 | let () = St.add_leaf fb_tree $3 in 548 | let () = St.add_leaf fb_tree (St.make_noop) in 549 | let ret = {St.op = Some (St.VARIABLE_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 550 | let () = St.add_leaf ret $1 in 551 | let () = St.add_leaf ret fb_tree in 552 | let () = St.add_variables ret $1 $3 0 None in ret 553 | } 554 | ; 555 | 556 | output_declarations: 557 | | VAR_OUTPUT varinitdecl END_VAR { 558 | let ret = {St.op = Some (St.VARIABLE_OUTPUT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 559 | let () = St.transfer_leaf ret $2 in ret 560 | } 561 | | VAR_OUTPUT RETAIN varinitdecl END_VAR { 562 | let ret = {St.op = Some (St.VARIABLE_OUTPUT_RETAIN); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 563 | let () = St.transfer_leaf ret $3 in ret 564 | } 565 | ; 566 | 567 | input_output_declarations: 568 | | VAR_IN_OUT vardecl END_VAR { 569 | let ret = {St.op = Some (St.VARIABLE_IN_OUT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 570 | let () = St.transfer_leaf ret $2 in ret 571 | } 572 | ; 573 | 574 | vardecl: 575 | | var_declaration ';' { 576 | let ret = {St.op = Some (St.VARIABLE_LIST); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 577 | let () = St.add_leaf ret $1 in ret 578 | } 579 | | vardecl var_declaration ';' { 580 | let ret = {St.op = Some (St.VARIABLE_LIST); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 581 | let () = St.add_leaf ret $2 in ret 582 | } 583 | ; 584 | 585 | var_declaration: 586 | | var1_declaration {$1} 587 | | fb_name_decl {$1} 588 | ; 589 | 590 | var1_declaration: 591 | | var1_list ':' simple_specification {$1} 592 | | var1_list ':' subrange_specification {$1} 593 | | var1_list ':' enumerated_specification {$1} 594 | ; 595 | 596 | var_declarations: 597 | | VAR varinitdecl END_VAR { 598 | let ret = {St.op = Some (St.VARIABLE_LOCAL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 599 | let () = St.transfer_leaf ret $2 in ret 600 | } 601 | | VAR CONSTANT varinitdecl END_VAR { 602 | let ret = {St.op = Some (St.VARIABLE_LOCAL_CONSTANT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 603 | let () = St.transfer_leaf ret $3 in ret 604 | } 605 | ; 606 | 607 | retentive_var_declarations: 608 | | VAR RETAIN varinitdecl END_VAR { 609 | let ret = {St.op = Some (St.VARIABLE_LOCAL_RETAIN); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 610 | let () = St.transfer_leaf ret $3 in ret 611 | } 612 | ; 613 | 614 | external_var_declarations: 615 | | VAR_EXTERNAL extdecl END_VAR {$2} 616 | ; 617 | 618 | extdecl: 619 | | external_declaration ';' { 620 | let ret = {St.op = Some (St.VARIABLE_EXTERNAL_LIST); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 621 | let () = St.add_leaf ret $1 in ret 622 | } 623 | | extdecl external_declaration ';' { 624 | let () = St.add_leaf $1 $2 in $1 625 | } 626 | ; 627 | 628 | external_declaration: 629 | | simple_type_name ':' simple_specification { 630 | let ret = {St.op = Some (St.VARIABLE_EXTERNAL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 631 | let () = St.add_leaf ret $1 in 632 | let () = St.add_leaf ret $3 in ret 633 | } 634 | | simple_type_name ':' subrange_specification { 635 | let ret = {St.op = Some (St.VARIABLE_EXTERNAL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 636 | let () = St.add_leaf ret $1 in 637 | let () = St.add_leaf ret $3 in ret 638 | } 639 | | simple_type_name ':' enumerated_specification { 640 | let ret = {St.op = Some (St.VARIABLE_EXTERNAL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 641 | let () = St.add_leaf ret $1 in 642 | let () = St.add_leaf ret $3 in ret 643 | } 644 | ; 645 | 646 | function_name: 647 | | std_func_name1 {$1} 648 | | std_func_name2 {$1} 649 | | simple_type_name {$1} 650 | ; 651 | 652 | std_func_name1: 653 | | MOD {St.make_literal_id "MOD"} 654 | | EXPT {St.make_literal_id "EXPT"} 655 | | MOVE {St.make_literal_id "MOVE"} 656 | ; 657 | 658 | std_func_name2: 659 | | AND {St.make_literal_id "AND" } 660 | | OR {St.make_literal_id "OR" } 661 | | XOR {St.make_literal_id "XOR" } 662 | | ADD {St.make_literal_id "ADD" } 663 | | SUB {St.make_literal_id "SUB" } 664 | | MUL {St.make_literal_id "MUL" } 665 | | DIV {St.make_literal_id "DIV" } 666 | | GT {St.make_literal_id "GT" } 667 | | LT {St.make_literal_id "LT" } 668 | | GE {St.make_literal_id "GE" } 669 | | LE {St.make_literal_id "LE" } 670 | | EQ {St.make_literal_id "EQ" } 671 | | NE {St.make_literal_id "NE" } 672 | ; 673 | 674 | function_declaration: 675 | | function_declare_name input_declarations funcvardecl function_body END_FUNCTION { 676 | let () = St.add_leaf $1 $2 in 677 | let () = St.add_leaf $1 $3 in 678 | let () = St.add_leaf $1 $4 in $1 679 | } 680 | ; 681 | 682 | function_declare_name: 683 | | FUNCTION simple_type_name ':' elementary_type_name { 684 | let ret = {St.op = Some (St.FUNCTION_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 685 | let () = St.add_leaf ret $2 in 686 | let () = St.add_leaf ret $4 in 687 | let () = St.add_variable $2.result.id $4 0 None in ret 688 | } 689 | | FUNCTION simple_type_name ':' derived_type_name { 690 | let ret = {St.op = Some (St.FUNCTION_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 691 | let () = St.add_leaf ret $2 in 692 | let () = St.add_leaf ret $4 in 693 | let () = St.add_variable $2.result.id $4 0 None in ret 694 | } 695 | ; 696 | 697 | funcvardecl: 698 | | VAR function_var_decls END_VAR { 699 | let ret = {St.op = Some (St.VARIABLE_LOCAL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 700 | let () = St.add_leaf ret $2 in 701 | let () = St.add_leaf ret (St.make_literal_int "0") in ret 702 | } 703 | | VAR CONSTANT function_var_decls END_VAR { 704 | let ret = {St.op = Some (St.VARIABLE_LOCAL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 705 | let () = St.add_leaf ret $3 in 706 | let () = St.add_leaf ret (St.make_literal_int "1") in ret 707 | } 708 | ; 709 | 710 | /* Is this correct ?? */ 711 | function_var_decls: 712 | | function_var_decl ';' {$1} 713 | | function_var_decls function_var_decl ';' {$1} 714 | ; 715 | 716 | function_var_decl: 717 | | var1_declaration {$1} 718 | ; 719 | 720 | function_body: 721 | | statement_list {$1} 722 | ; 723 | 724 | function_block_type_name: 725 | | simple_type_name { 726 | $1.op <- St.TYPE_DEF; 727 | let () = $1.result.t <- St.funcblk_type $1.result.id in $1 728 | } 729 | | standard_function_block_name { 730 | $1.op <- ST.TYPE_DEF; 731 | let () = $1.result.t <- St.funcblk_type $1.result.id in $1 732 | } 733 | ; 734 | 735 | standard_function_block_name: 736 | | SR {St.make_literal_id "ST"} 737 | | R_TRIG {St.make_literal_id "R_TRIG"} 738 | | F_TRIG {St.make_literal_id "F_TRIG"} 739 | | CTU {St.make_literal_id "CTU"} 740 | | CTD {St.make_literal_id "CTD"} 741 | | CTUD {St.make_literal_id "CTUD"} 742 | | TP {St.make_literal_id "TP"} 743 | | TON {St.make_literal_id "TON"} 744 | | TOF {St.make_literal_id "TOF"} 745 | ; 746 | 747 | function_block_declaration: 748 | | FUNCTION_BLOCK simple_type_name fb_io_var_decls other_var_decls function_block_body END_FUNCTION_BLOCK 749 | { 750 | let ret = {St.op = Some (St.FB_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 751 | let () = St.add_leaf ret $2 in 752 | let () = St.add_leaf ret $3 in 753 | let () = St.add_leaf ret $4 in 754 | let () = St.add_leaf ret $5 in ret 755 | } 756 | | FUNCTION_BLOCK standard_function_block_name fb_io_var_decls other_var_decls function_block_body END_FUNCTION_BLOCK 757 | { 758 | let ret = {St.op = Some (St.FB_DECLARE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 759 | let () = St.add_leaf ret $2 in 760 | let () = St.add_leaf ret $3 in 761 | let () = St.add_leaf ret $4 in 762 | let () = St.add_leaf ret $5 in ret 763 | } 764 | ; 765 | 766 | fb_io_var_decls: 767 | | {St.make_noop} 768 | | fb_io_var_decls fb_io_var_declarations {St.add_leaf $1 $2; $1} 769 | ; 770 | 771 | other_var_decls: 772 | | {St.make_noop} 773 | | other_var_decls other_var_declarations {St.add_leaf $1 $2; $1} 774 | 775 | fb_io_var_declarations: 776 | | input_declarations {$1} 777 | | output_declarations {$1} 778 | | input_output_declarations {$1} 779 | ; 780 | 781 | other_var_declarations: 782 | | external_var_declarations {$1} 783 | | var_declarations {$1} 784 | | retentive_var_declarations {$1} 785 | ; 786 | 787 | function_block_body: 788 | | statement_list {$1} 789 | ; 790 | 791 | expression: 792 | | xor_expression {$1} 793 | | expression OR xor_expression { 794 | let () = St.concat_leaf $1 (St.EXPR_XOR) in 795 | let () = St.add_leaf $1 $3 in $1 796 | } 797 | ; 798 | 799 | xor_expression: 800 | | xor_expression XOR and_expression { 801 | let () = St.concat_leaf $1 (St.EXPR_XOR) in 802 | let () = St.add_leaf $1 $3 in $1 803 | } 804 | ; 805 | 806 | and_expression: 807 | | and_expression '&' comparison { 808 | let () = St.concat_leaf $1 (St.EXPR_AND) in 809 | let () = St.add_leaf $1 $3 in $1 810 | } 811 | | and_expression AND comparison { 812 | let () = St.concat_leaf $1 (St.EXPR_AND) in 813 | let () = St.add_leaf $1 $3 in $1 814 | } 815 | ; 816 | 817 | comparison: 818 | | equ_expression {$1} 819 | | comparison '=' equ_expression { 820 | let () = St.concat_leaf $1 (St.EXPR_EQ) in 821 | let () = St.add_leaf $1 $3 in $1 822 | } 823 | | comparison OPER_NE equ_expression { 824 | let () = St.concat_leaf $1 (St.EXPR_NE) in 825 | let () = St.add_leaf $1 $3 in $1 826 | } 827 | ; 828 | 829 | equ_expression: 830 | | equ_expression '<' add_expression { 831 | let () = St.concat_leaf $1 (St.EXPR_LT) in 832 | let () = St.add_leaf $1 $3 in $1 833 | } 834 | | equ_expression '>' add_expression { 835 | let () = St.concat_leaf $1 (St.EXPR_GT) in 836 | let () = St.add_leaf $1 $3 in $1 837 | } 838 | | equ_expression OPER_LE add_expression { 839 | let () = St.concat_leaf $1 (St.EXPR_LE) in 840 | let () = St.add_leaf $1 $3 in $1 841 | } 842 | | equ_expression OPER_GE add_expression { 843 | let () = St.concat_leaf $1 (St.EXPR_GE) in 844 | let () = St.add_leaf $1 $3 in $1 845 | } 846 | 847 | ; 848 | 849 | add_expression: 850 | | term {$1} 851 | | add_expression '+' term { 852 | let () = St.concat_leaf $1 (St.EXPR_ADD) in 853 | let () = St.add_leaf $1 $3 in $1 854 | } 855 | | add_expression '-' term { 856 | let () = St.concat_leaf $1 (St.EXPR_SUB) in 857 | let () = St.add_leaf $1 $3 in $1 858 | } 859 | ; 860 | 861 | term: 862 | | power_expression {$1} 863 | | term '*' power_expression { 864 | let () = St.concat_leaf $1 (St.EXPR_MUL) in 865 | let () = St.add_leaf $1 $3 in $1 866 | } 867 | | term '/' power_expression { 868 | let () = St.concat_leaf $1 (St.EXPR_DIV) in 869 | let () = St.add_leaf $1 $3 in $1 870 | } 871 | | term MOD power_expression { 872 | let () = St.concat_leaf $1 (St.EXPR_MOD) in 873 | let () = St.add_leaf $1 $3 in $1 874 | } 875 | ; 876 | 877 | power_expression: 878 | | unary_expression {$1} 879 | | power_expression OPER_EXP unary_expression { 880 | let () = St.concat_leaf $1 (St.EXPR_POW) in 881 | let () = St.add_leaf $1 $3 in $1 882 | } 883 | ; 884 | 885 | unary_expression: 886 | | primary_expression {$1} 887 | | '-' primary_expression { 888 | let ret = {St.op = Some (St.EXPR_UNARY); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 889 | let () = St.add_leaf ret $2 in ret 890 | } 891 | | NOT primary_expression { 892 | let ret = {St.op = Some (St.EXPR_NOT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 893 | let () = St.add_leaf ret $2 in ret 894 | } 895 | ; 896 | 897 | primary_expression: 898 | | constant {$1} 899 | | variable {$1} 900 | | '(' expression ')' {$2} 901 | | function_name '(' ')' { 902 | let ret = {St.op = Some (St.FUNC_CALL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 903 | let () = St.add_leaf ret $1 in 904 | let () = St.add_leaf ret (St.make_noop) in ret 905 | } 906 | | function_name '(' fb_input_assignments ')' { 907 | let ret = {St.op = Some (St.FUNC_CALL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 908 | let () = St.add_leaf ret $1 in 909 | let () = St.add_leaf ret $3 in ret 910 | } 911 | | simple_type_name '.' simple_type_name { 912 | let ret = {St.op = Some (St.FB_VARIABLE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 913 | let () = St.add_leaf ret $1 in 914 | let () = St.add_leaf ret $3 in ret 915 | } 916 | | simple_type_name '.' variable { 917 | let ret = {St.op = Some (St.FB_VARIABLE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 918 | let () = St.add_leaf ret $1 in 919 | let () = St.add_leaf ret $3 in ret 920 | } 921 | ; 922 | 923 | statement_list: 924 | | statement ';' { 925 | let ret = {St.op = Some (St.ST_STATEMENT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 926 | let () = St.add_leaf ret $1 in ret 927 | } 928 | | statement_list statement ';' { 929 | let () = St.add_leaf $1 $2 in $1 930 | } 931 | ; 932 | 933 | statement: 934 | | assignment_statement {$1} 935 | | subprogram_control_statement {$1} 936 | | selection_statement {$1} 937 | | iteration_statement {$1} 938 | ; 939 | 940 | assignment_statement: 941 | | variable ':' '=' expression { 942 | let ret = {St.op = Some (St.ST_ASSIGNMENT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 943 | let () = St.add_leaf ret $1 in 944 | let () = St.add_leaf ret $4 in ret 945 | } 946 | ; 947 | 948 | subprogram_control_statement: 949 | | fb_invocation {$1} 950 | | RETURN {{St.op = Some (St.ST_RETURN); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} } 951 | ; 952 | 953 | fb_invocation: 954 | | simple_type_name '(' ')' { 955 | let ret = {St.op = Some (St.FB_CALL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 956 | let () = St.add_leaf ret $1 in 957 | let () = St.add_leaf ret (St.make_noop) in 958 | let () = St.add_leaf ret (St.make_literal_int "0") in ret 959 | } 960 | | simple_type_name '(' fb_input_assignments ')' { 961 | let ret = {St.op = Some (St.FB_CALL); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 962 | let () = St.add_leaf ret $1 in 963 | let () = St.add_leaf ret $3 in 964 | let () = St.add_leaf ret (St.make_literal_int "0") in ret 965 | } 966 | ; 967 | 968 | fb_input_assignments: 969 | | fb_input_assignment { 970 | let ret = {St.op = Some (St.FB_VARLIST); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 971 | let () = St.add_leaf ret $1 in ret 972 | } 973 | | fb_input_assignments ',' fb_input_assignment { 974 | let () = St.add_leaf $1 $3 in $1 975 | } 976 | ; 977 | 978 | /* Check this later, might give reduce/reduce conflict with assignment statement */ 979 | fb_input_assignment: 980 | | simple_type_name ':' '=' expression { 981 | let ret = {St.op = Some (St.FB_VAR); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 982 | let () = St.add_leaf ret $1 in 983 | let () = St.add_leaf ret $4 in ret 984 | } 985 | | expression { 986 | let ret = {St.op = Some (St.FB_VAR); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 987 | let () = St.add_leaf ret (St.make_noop) in 988 | let () = St.add_leaf ret $1 in ret 989 | } 990 | ; 991 | 992 | selection_statement: 993 | | case_statement {$1} 994 | | if_statement {$1} 995 | ; 996 | 997 | if_statement: 998 | | IF expression THEN statement_list elsif_list END_IF 999 | { 1000 | let ret = {St.op = Some (St.ST_IF_STMT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1001 | let () = St.add_leaf ret $2 in 1002 | let () = St.add_leaf ret $4 in 1003 | let () = St.add_leaf ret $5 in 1004 | let () = St.add_leaf ret (St.make_noop) in ret 1005 | } 1006 | | IF expression THEN statement_list elsif_list ELSE statement_list END_IF 1007 | { 1008 | let ret = {St.op = Some (St.ST_IF_STMT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1009 | let () = St.add_leaf ret $2 in 1010 | let () = St.add_leaf ret $4 in 1011 | let () = St.add_leaf ret $5 in 1012 | let () = St.add_leaf ret $7 in ret 1013 | } 1014 | ; 1015 | 1016 | elsif_list: 1017 | | ELSIF expression THEN statement_list 1018 | { 1019 | let ret = {St.op = Some (St.ST_IF_ELSIF); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1020 | let () = St.add_leaf ret $2 in 1021 | let () = St.add_leaf ret $4 in ret 1022 | } 1023 | | elsif_list ELSIF expression THEN statement_list 1024 | { 1025 | let () = St.add_leaf $1 $3 in 1026 | let () = St.add_leaf $1 $5 in $1 1027 | } 1028 | ; 1029 | 1030 | case_statement: 1031 | | CASE expression OF case_elements END_CASE { 1032 | let ret = {St.op = Some (St.ST_CASE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1033 | let () = St.add_leaf ret $2 in 1034 | let () = St.add_leaf ret (St.make_noop) in 1035 | let () = St.add_leaf ret $4 in ret 1036 | } 1037 | | CASE expression OF case_elements ELSE statement_list END_CASE 1038 | { 1039 | let ret = {St.op = Some (St.ST_CASE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1040 | let () = St.add_leaf ret $2 in 1041 | let () = St.add_leaf ret $4 in 1042 | let () = St.add_leaf ret $6 in ret 1043 | } 1044 | ; 1045 | 1046 | case_elements: 1047 | | case_list ':' statement_list { 1048 | let ret = {St.op = Some (St.ST_CASE_ELEMENT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())}in 1049 | let () = St.add_leaf ret $1 in 1050 | let () = St.add_leaf ret $3 in ret 1051 | } 1052 | | case_elements case_list ':' statement_list {St.add_leaf $1 $2; St.add_leaf $1 $4} 1053 | ; 1054 | 1055 | case_list: 1056 | | subrange { 1057 | let ret = {St.op = Some (St.ST_CASE_LIST); St.elements=[$1];St.result=None;St.n=0;St.location=Some (ln())} in 1058 | let () = St.add_leaf ret $1 in ret 1059 | } 1060 | | signed_integer { 1061 | let ret = {St.op = Some (St.ST_CASE_LIST); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1062 | let () = St.add_leaf ret $1 in ret 1063 | } 1064 | | case_list ',' subrange {St.add_leaf $1 $3} 1065 | | case_list ',' signed_integer {St.add_leaf $1 $3} 1066 | ; 1067 | 1068 | iteration_statement: 1069 | | for_statement {$1} 1070 | | while_statement {$1} 1071 | | repeat_statement {$1} 1072 | | exit_statement {$1} 1073 | ; 1074 | 1075 | for_statement: 1076 | | FOR simple_type_name ':' '=' expression TO expression DO statement_list END_FOR 1077 | { 1078 | let lit_int = {St.t=Some St.BM_ANY_INT;St.leaf_type=St.LITERAL_INTEGER;St.leaf=None;St.literal_string=Some "1";St.id=None;St.buff=None} in 1079 | let ret = {St.op = Some (St.ST_FOR_LOOP); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1080 | let () = St.add_leaf ret $2 in 1081 | let () = St.add_leaf ret $5 in 1082 | let () = St.add_leaf ret $7 in 1083 | let () = St.add_leaf ret lit_int in 1084 | let () = St.add_leaf ret $9 in 1085 | ret 1086 | } 1087 | | FOR simple_type_name ':' '=' expression TO expression BY expression DO statement_list END_FOR 1088 | { 1089 | let ret = {St.op = Some (St.ST_FOR_LOOP); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1090 | let () = St.add_leaf ret $2 in 1091 | let () = St.add_leaf ret $5 in 1092 | let () = St.add_leaf ret $7 in 1093 | let () = St.add_leaf ret $9 in 1094 | let () = St.add_leaf ret $11 in 1095 | ret 1096 | } 1097 | ; 1098 | 1099 | while_statement: 1100 | | WHILE expression DO statement_list END_WHILE 1101 | { 1102 | let ret = {St.op = Some (St.ST_WHILE); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1103 | let () = St.add_leaf ret $2 in 1104 | let () = St.add_leaf ret $4 in 1105 | ret 1106 | } 1107 | ; 1108 | 1109 | repeat_statement: 1110 | | REPEAT statement_list UNTIL expression END_REPEAT 1111 | { 1112 | let ret = {St.op = Some (St.ST_REPEAT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())} in 1113 | let () = St.add_leaf ret $2 in 1114 | let () = St.add_leaf ret $4 in 1115 | ret 1116 | } 1117 | ; 1118 | 1119 | exit_statement: 1120 | | EXIT {{St.op = Some (St.ST_EXIT); St.elements=[];St.result=None;St.n=0;St.location=Some (ln())}} 1121 | ; 1122 | 1123 | %% 1124 | (* This is the trailer *) 1125 | -------------------------------------------------------------------------------- /stc.ml: -------------------------------------------------------------------------------- 1 | module List = Batteries.List 2 | module Hashtbl = Batteries.Hashtbl 3 | module MyString = Batteries.String 4 | 5 | module SS = Sexplib.Sexp 6 | module SSL = Sexplib.Std 7 | 8 | module PL = PropositionalLogic 9 | open TableauBuchiAutomataGeneration 10 | 11 | let (|>) x f = f x 12 | 13 | let usage_msg = "Usage: stc \nsee -help for more options" in 14 | 15 | let file_name = ref "" in 16 | let speclist = Arg.align [] in 17 | 18 | try 19 | let () = Arg.parse speclist (fun x -> file_name := x) usage_msg in 20 | (* Initialize the error reporting structures *) 21 | let in_chan = open_in !file_name in 22 | let () = print_endline "....Lexing and parsing..." in 23 | let lexbuf = Lexing.from_channel in_chan in 24 | let ast = Parser.ast Lexer.lexer lexbuf in 25 | (* Close the input channel *) 26 | let () = close_in in_chan in 27 | with 28 | | End_of_file -> exit 0 29 | | Sys_error _ -> Arg.usage speclist usage_msg 30 | | _ as s -> raise s 31 | --------------------------------------------------------------------------------