我在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解析器生成器。
答案 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)
这个基本问题是您没有INC
和DEC
令牌的优先权,所以它不知道如何解决涉及INC
或前瞻的歧义DEC
。如果你添加
%right INC DEC
在优先级列表的末尾(你希望一元优先级更高,后缀高于前缀),它会修复它,你甚至可以删除所有PREINC
/ POSTINC
事情,因为它是无关紧要的。
答案 4 :(得分:-1)
preincrement和postincrement运算符具有nonassoc,因此定义在优先级部分和规则中使用%prec