How do I compare precedence of tokens with different associativity in yacc?
%left TOKEN1
%left TOKEN2
%right TOKEN3
In the above example,TOKEN2
has higher precedence than TOKEN1
, but what about TOKEN3
?
Is i开发者_如何学运维t guaranteed that TOKEN3
has higher precedence than TOKEN2
or not?
This declares TOKEN3 to have higher precedence that TOKEN2, but by your comments you may be misunderstanding what 'higher precedence' means to yacc/bison.
In yacc/bison, all that precedence matters for is resolving shift/reduce conflicts -- whenever there's a shift reduce conflict, the parser generator compares the precedence of the token to be shifted with the precedence of the rule to be reduced and does whichever one has the higher precedence (if they're the same, then %left favors the reduce while %right favors the shift). That's all. In particular, precedence has NO EFFECT on reduce/reduce conflicts.
So in the case of something like a dangling else, the precedence of the ELSE token will be compared with the precedence of the if-with-no-else production. If the latter has higher precedence it will be reduced, which is the reverse of what most languages (and common sense) dictate. It will also fail to work with an LALR(1) parser (though it will work with an LR(1) parser) due to the way that states get combined.
edit
You can follow Aymanadou's recommendation to attempt to make things work, but it won't work at all in yacc (due to it being LALR(1)) and won't really work even an LR(1) parser. To understand why (and to see why it REALLY makes no sense), consider the input
if (a) if (b) c else d else e
Note that d
can be an arbitratily large {}-enclosed block. Now if you associate the first else
with the first if
(which is what will happen without arbitrary lookahead), when the parser gets to the second else
, it won't have an if
to match up with and you'll get a syntax error. With an LALR(1) parser, because of state merging, this problem crops up even with just
if (a) b else c
In this case, if you give else lower precedence, it will reduce if (a) b
as a an if-with-no-else statement, leaving the dangling else to cause a syntax error.
If you actually want to do what you say, you need to use a parsing method that can either do arbitrary lookahead (such as with backtracking), or can non-deterministicly parse alternatives to deal with ambiguities (such as GLR). But doing this will generally result in a langauge that is not understandable by human readers, as the meaning of small piece of code can depend on stuff that appears much later in the code.
You can set explicit precedences will may be help you
IF ELSE example
%nonassoc LOWER_THAN_ELSE
%nonassoc ELSE
%%
stmt : IF expr stmt %prec LOWER_THAN_ELSE ;
| IF expr stmt ELSE stmt;
精彩评论