开发者

How do I compare precedence of tokens with different associativity in yacc?

开发者 https://www.devze.com 2023-03-24 10:03 出处:网络
%left TOKEN1 %left TOKEN2 %right TOKEN3 In the above example,TOKEN2 has higher precedence than TOKEN1, but what about TOKEN3?
%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;
0

精彩评论

暂无评论...
验证码 换一张
取 消