I am trying to write a ST ( structured text ) compiler that follows the IEC 61131-3 spec. It is Pascal like.
I am an experienced programmer but a new at writing compilers. When I compile my test code for a case statement
CASE A OF 0: B:=0; 1: B:=1; 2: B:=2; END_CASE
The parser ends up wind up in the wrong state. The code compiles OK to where the '.' is
CASE A OF 0: B:=0; . 1: B:=1; 2: B:=2; END_CASE
The 0: B:=0; is a case_element and it should reduce but it doesn't so instead of working on the next case_element ( 1: B:= 1; ) it thinks it is starting another statement.
The syntax does not use a break keyword to indicate the end of a case element. This is what is giving me problems. Here are my rules that are pertinent to my problem.
Code:
stmt:
| CASE expr OF case_element_list END_CASE { $$ = opr(CASE,2,$2,$4); }
| CASE expr OF case_element_list ELSE stmt_list END_CASE { $$ = opr(CASE,3,$2,$4,$6); }
;
case_element_list:
case_element { $$ = $1; }
| case_element_list case_element { $$ = opr(';', 2, $1, $2); }
;
case_element:
INTEGER ':' stmt_list { $$ = opr(':',2,$1,$3); }
;
stmt_list:
stmt { $$ = $1; }
| stmt_list stmt { $$ = opr(';', 2, $1, $2); }
;
After the OF the parser enter state 39 as expected and process to state 56 and 66 but when it gets to state 74 it doesn't reduce.
The ':' should match a expr that causes the state machine to go to state 14.
Relevant parts of the parser debug file
State 74 conflicts: 1 shift/reduce
state 39
12 stmt: CASE expr OF . case_element_list END_CASE
13 | CASE expr OF . case_element_list ELSE stmt_list END_CASE
INTEGER shift, and go to state 56
case_element_list go to state 57
case_element go to state 58
state 56
20 case_element: INTEGER . ':' stmt_list
':' shift, and go to state 66
state 66
20 case_element: INTEGER ':' . stmt_list
INTEGER shift, and go to state 4
VARIABLE shift, and go to state 5
PRINT shift, and go to state 6
WHILE shift, and go to state 7
IF shift, and go to state 8
CASE shift, and go to state 9
'-' shift, and go to state 10
';' shift, and go to state 11
'(' shift, and go to state 12
stmt go to state 53
stmt_list go to state 74
expr go to state 14
state 74
20 case_element: INTEGER ':' stmt_list .
22 stmt_list: stmt_list . stmt
INTEGER shift, and go to state 4
VARIABLE shift, and go to state 5
PRINT shift, and go to state 6
WHILE shift, and go to state 7
IF shift, and go to state 8
CASE shift, and go to state 9
'-' shift, and go to state 10
';' shift, and go to state 11
'(' shift, and go to state 12
INTEGER [reduce using rule 20 (case_element)]
$default reduce using rule 20 (case_element)
stmt go to state 60
expr go to state 14
The run time ooutput of the parser is.
Shifting token ';'
Entering state 52
Reducing stack by rule 7 (line 63):
$1 = token VARIABLE ()
$2 = token ASSIGN ()
$3 = nterm expr ()
$4 = token ';' ()
-> $$ = nterm stmt ()
Stack now 0 2 9 20 39 56 66
Entering state 53
Reducing stack by rule 21 (line 92):
$1 = nterm stmt ()
-> $$ = nterm stmt_list ()
Stack now 0 2 9 20 39 56 66
Entering state 74
Reading a token: --accepting rule at line 49 ("
--accepting rule at line 20 ("1")
Next token is token INTEGER ()
Shifting token INTEGER ()
Entering state 4
Reducing stack by rule 23 (line 97):
$1 = token INTEGER ()
-> $$ = nterm expr ()
Stack now 0 2 9 20 39 56 66 74
Entering state 14
Reading a token: --accepting rule at line 25 ("
Next token is token ':' ()
0: syntax error, unexpected ':' at ':'
Error: popping nterm expr ()
Stack now 0 2 9 20 39 56 66 74
Error: popping nterm stmt_list ()
Stack now 0 2 9 20 39 56 66
Error: popping token ':' ()
Stack now 0 2 9 20 39 56
Error: popping token INTEGER ()
Stack now 0 2 9 20 39
Error: popping token OF ()
Stack now 0 2 9 20
Error: popping nterm expr ()
Stack now 0 2 9
Error: popping token CASE ()
Stack now 0 2
Error: popping nterm function ()
Stack now 0
Cleanup: discarding lookahead token ':' ()
Stack now 0stmt: