Hello I'm using bison for a compiler for study purposes, i got the next code:
if :
if2
|
if1;
if2:
SE expressao {$1 = (struct lbs *) newlblrec(); $1->for_jmp_false = reserve_loc(); $1->label = label; label+=2;} ENTAO
comandos
SENAO {$1->for_goto = reserve_loc(); back_patch($1->for_jmp_false, JMP_FALSE, $1->label);}
comandos
FIMSE {back_patch($1->for_goto, GOTO, $1->label开发者_如何学JAVA+1);}
|
SE expressao error {yyerrok; errors++; yyerror("Entao nao encontrado no se");}
comandos
SENAO
comandos
FIMSE ;
if1:
SE expressao {$1 = (struct lbs *) newlblrec(); $1->for_jmp_false = reserve_loc(); $1->label = label++;} ENTAO
comandos
FIMSE {back_patch($1->for_jmp_false, JMP_FALSE, $1->label); gen_code(LABEL,$1->label);}
|
SE expressao error {yyerrok; errors++; yyerror("Entao nao encontrado no se");}
comandos
FIMSE;
This code only generates the rule 'if2', when it found the "FIMSE" (this indicates that the command is a simple if) before the "SENAO" (in this case is a if else command) it's raises an error, this only happen when i put the C code to generate the intermediate code. My question is: Why? How can i fix this?
When the parser receives SE
and expressao
, in your augmented form, it then immediately needs to make a choice which action to perform (because you asked that the action happens at that point. Without the annotation, it can first push ENTAO
and commandos
, and then make a decision to reduce.
In essence, an action inside the RHS is translated into one that has the action at the end, with another non-terminal. So
foo: bar { action1 } foobar
foo: bar { action2 } baz
is translated into
foo: helper1 foobar
foo: helper2 baz
helper1: bar { action1 }
helper2: bar { action2 }
As a consequence, these actions produce a reduce-reduce conflict in your grammar.
There are two approaches:
- put the action at the end.
- refactor the grammar so that the action is actually the same one in both alternatives.
精彩评论