我有一个简单的玩具程序,正在使用它来处理二进制表达式。我希望正常的优先级规则适用于首先评估括号,表达式,mult / div等的括号中的表达式。我设置了以下代码,它似乎可以正常工作,但我对此感到有些困惑。
%left '+' '-'
%left '*' '/'
%%
start: e { printf("%d", $1);}
e: e '+' e { $$ = $1 + $3; }
| e '-' e { $$ = $1 - $3; }
| e '*' e { $$ = $1 * $3; }
| e '/' e { $$ = $1 / $3; }
| '(' e ')' { $$ = $2; }
| NUMBER { $$ = $1; }
;
例如,如果我输入2 *(4 + 4),它将被正确地评估为2 * 8而不是8 +4。我不确定为什么这样做。我想确保我对此的理解是正确的。当解析器遇到2 * (4 + 4)
时,它首先解析2 *
,然后看到另一个e
规则,即(4 + 4)
。然后,它评估4 + 4
,然后将该值向上传递,所以现在我们在2 * 4
了?
如果我确保添加优先规则,这是定义二进制操作规则的一种好方法吗?还是我错过了一些边缘案例(玩了很多,到目前为止还没有找到错误的答案)?
答案 0 :(得分:1)
2 * (4 + 4)
的评估结果为2 * 8
,因为这是这些标记可以匹配您的语法规则模式的唯一方法。您的语法规则没有将2 * ( 4
部分与+ 4
分开的任何短语结构来识别(4 + 4)
。语法中'(' e ')'
可能唯一匹配的模式是%left '+' '-'
%left '*' '/'
模式。这方面与优先级规则没有任何关系。
算术运算符之间的关联性和优先级由以下几行建立:
{{1}}
同一行中的项目具有相同的优先级;以后的行具有更高的优先级。
如果您错过了一些紧急情况,那么Yacc通常会抱怨为“冲突”。可能会产生与您的意图背道而驰的明确语法,但是歧义不会在没有诊断的情况下消失。