如何在yacc中比较令牌的优先级与不同的关联性?

时间:2011-08-01 06:27:53

标签: yacc operator-precedence

%left TOKEN1
%left TOKEN2
%right TOKEN3

在上面的例子中,TOKEN2的优先级高于TOKEN1,但是TOKEN3呢?

是否保证TOKEN3的优先级高于TOKEN2

2 个答案:

答案 0 :(得分:1)

这声明TOKEN3具有更高的TOKEN2优先权,但是根据您的评论,您可能会误解“更高的优先级”对yacc / bison的意义。

在yacc / bison中,所有优先级都是解决移位/减少冲突 - 只要存在移位减少冲突,解析器生成器就会将要移位的令牌的优先级与要减少的规则的优先级进行比较。无论哪一个具有更高的优先级(如果它们是相同的,则%左边倾向于减少而%右边倾向于偏移)。就这样。特别是,优先权对减少/减少冲突没有影响。

因此,在类似悬挂的其他内容的情况下,ELSE令牌的优先级将与if-with-no-else生成的优先级进行比较。如果后者具有更高的优先级,它将被减少,这与大多数语言(和常识)所指示的相反。由于状态合并的方式,它也无法使用LALR(1)解析器(尽管它可以与LR(1)解析器一起使用)。

修改

你可以按照Aymanadou的建议尝试使事情有效,但它在yacc中根本不起作用(因为它是LALR(1))并且甚至不能真正地工作LR(1)解析器。要理解为什么(以及为什么它真的没有意义),请考虑输入

if (a) if (b) c else d else e

请注意,d可以是一个任意大的{}封闭块。现在,如果您将第一个else与第一个if相关联(这将是没有任意前瞻的情况),当解析器到达第二个else时,它将没有{ {1}}要与之匹配,您将收到语法错误。使用LALR(1)解析器,由于状态合并,即使只有

,这个问题也会出现
if

在这种情况下,如果你给予其他更低的优先级,它将减少if (a) b else c 作为一个if-with-no-else语句,留下悬挂的else会导致语法错误。

如果你真的想做你说的话,你需要使用一种解析方法,可以做任意预测(例如使用回溯),或者可以非确定性地解析替代方案来处理歧义(例如GLR)。但这样做通常会导致人类读者无法理解的语言,因为小段代码的含义可能取决于代码中稍后出现的内容。

答案 1 :(得分:0)

您可以设置明确的优先级,可能会帮助您

IF ELSE示例

%nonassoc LOWER_THAN_ELSE

%nonassoc ELSE

%%
stmt   :    IF expr stmt %prec LOWER_THAN_ELSE ;
       |    IF expr stmt ELSE stmt;