我的目标是为小语言创建解析器。它目前给我一个班次/减少错误。
我的CFG在某个地方很模糊,但我无法弄明白
prog: PROGRAM beg {$$ = "program" $2;}
| PROGRAM stmt beg {$$ = "program" $2 $3;}
beg: BEG stmt END {$$ = "begin" $2 "end";}
| BEG END {$$ = "begin" "end";}
stmt: beg {$$ = $1;}
| if_stmt {$$ = $1;}/*
| IF expr THEN stmt {$$ = $1 $2 $3 $4;}*/
| WHILE expr beg {$$ = "while" $2 $3;}
| VAR COLEQUALS arithexpr SEMI {$$ = $1 ":=" $3 ";";}
| VAR COLON INTEGER SEMI {$$ = $1 ":" "integer" ";";} /*Declaring an integer */
| VAR COLON REAL SEMI {$$ $1 ":" "real" ";";} /*declaring a real */
if_stmt: IF expr THEN stmt {$$ = "if" $2 "then" $4;}
| IF expr THEN stmt ELSE stmt {$$ = "if" $2 "then" $4 "else" $6;}
expr: NOT VAR {$$ = "!" $2;}
| VAR GREATERTHAN arithexpr {$$ = $1 ">" $3;}
| VAR LESSTHAN arithexpr {$$ = $1 "<" $3;}
| VAR GREATERTHANEQUALTO arithexpr {$$ = $1 ">=" $3;}
| VAR LESSTHANEQUALTO arithexpr {$$ = $1 "<=" $3;}
| VAR EQUALS arithexpr {$$ = $1 "==" $3;}
| VAR NOTEQUALS arithexpr {$$ = $1 "!=" $3;}
| arithexpr AND arithexpr {$$ = $1 "&&" $3;}
| arithexpr OR arithexpr {$$ = $1 "||" $3;}
arithexpr: arithexpr PLUS term {$$ = $1 + $3;}
| arithexpr MINUS term {$$ = $1 - $3;}
| term {$$ = $1;}
term: term TIMES factor {$$ = $1 * $3;}
| term DIVIDE factor {$$ = $1 / $3;}
| factor {$$ = $1;}
factor: VAL {$$ = $1;}
答案 0 :(得分:1)
“错误”来自if
_ stmt的else
部分中的歧义:stmt
可以是if_stmt,并且如果else部分属于哪个,则不清楚,例如如果你写:
if y1 then if y2 then x=1 else x=2
然后,else部分可以属于第一个if或第二个。
此问题已多次在变体中提出,只需搜索if then else shift reduce
对于诊断(发现你也是if then else shift reduce
问题的受害者)你可以告诉bison产生一个输出文件
bison -r all myparser.y
将生成一个文件myparser.output,您可以在其中找到您的案例:
State 50 conflicts: 1 shift/reduce
....
state 50
11 if_stmt: IF expr THEN stmt . [ELSE, BEG, END]
12 | IF expr THEN stmt . ELSE stmt
ELSE shift, and go to state 60
ELSE [reduce using rule 11 (if_stmt)]
$default reduce using rule 11 (if_stmt)
state 51
...
对此的一个解决方案是引入一个块语句,并将这些语句作为if和else部分中的语句:
stmt: ...
| blk_stmt
blk_stmt: BEGIN stmt END
if_stmt: IF expr THEN blk_stmt
| IF expr THEN blk_stmt ELSE blk_stmt
对于修改过的c语言意味着只有
if x1 then {if x2 then {y=1}} else {y=2}
是可能的({
代表BEGIN-token,}
代表END-token,从而解决歧义。