如何修复YACC从后增量运算符中移位/减少冲突?

时间:2009-05-20 20:24:08

标签: parsing yacc bison shift-reduce-conflict lalr

我在YACC(实际上是Bison)写了一个语法,我有一个转移/减少问题。它包括后缀增量和减量运算符。这是语法的精简版本:

%token NUMBER ID INC DEC

%left      '+' '-'
%left      '*' '/'
%right     PREINC
%left      POSTINC

%%

expr: NUMBER
|     ID
|     expr '+' expr
|     expr '-' expr
|     expr '*' expr
|     expr '/' expr
|     INC expr %prec PREINC
|     DEC expr %prec PREINC
|     expr INC %prec POSTINC
|     expr DEC %prec POSTINC
|     '(' expr ')'
;

%%

Bison告诉我有12个移位/减少冲突,但如果我注释掉后缀增量和减少的行,它就可以正常工作。有谁知道如何解决这个冲突?在这一点上,我正在考虑转向LL(k)解析器生成器,这使得它更容易,但LALR语法似乎总是更自然地编写。我也在考虑GLR,但我不知道有什么好的C / C ++ GLR解析器生成器。

5 个答案:

答案 0 :(得分:3)

如果您在选项部分指定%glr-parser,Bison / Yacc可以生成GLR解析器。

答案 1 :(得分:2)

试试这个:

%token NUMBER ID INC DEC

%left       '+' '-'
%left       '*' '/'
%nonassoc   '++' '--'
%left       '('
%%

expr: NUMBER
|     ID
|     expr '+' expr
|     expr '-' expr
|     expr '*' expr
|     expr '/' expr
|     '++' expr 
|     '--' expr 
|     expr '++'
|     expr '--'
|     '(' expr ')'
;

%%

关键是将后缀运算符声明为非关联。否则你就可以

++var++--

还需要优先考虑括号,以最小化移位/减少警告

答案 2 :(得分:0)

我想定义更多项目。你不应该需要%left,%right,%prec stuff。

simple_expr: NUMBER
 | INC simple_expr
 | DEC simple_expr
 | '(' expr ')'
;

term: simple_expr
 | term '*' simple_expr
 | term '/' simple_expr
;

expr: term
 | expr '+' term
 | expr '-' term
;

使用这种方法。

答案 3 :(得分:0)

这个基本问题是您没有INCDEC令牌的优先权,所以它不知道如何解决涉及INC或前瞻的歧义DEC。如果你添加

%right INC DEC

在优先级列表的末尾(你希望一元优先级更高,后缀高于前缀),它会修复它,你甚至可以删除所有PREINC / POSTINC事情,因为它是无关紧要的。

答案 4 :(得分:-1)

preincrement和postincrement运算符具有nonassoc,因此定义在优先级部分和规则中使用%prec

使这些运算符的优先级更高