为具有适当优先级(包括括号)的二进制表达式创建语法

时间:2019-06-20 20:04:43

标签: parsing bison yacc

我有一个简单的玩具程序,正在使用它来处理二进制表达式。我希望正常的优先级规则适用于首先评估括号,表达式,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了?

如果我确保添加优先规则,这是定义二进制操作规则的一种好方法吗?还是我错过了一些边缘案例(玩了很多,到目前为止还没有找到错误的答案)?

1 个答案:

答案 0 :(得分:1)

2 * (4 + 4)的评估结果为2 * 8,因为这是这些标记可以匹配您的语法规则模式的唯一方法。您的语法规则没有将2 * ( 4部分与+ 4分开的任何短语结构来识别(4 + 4)。语法中'(' e ')'可能唯一匹配的模式是%left '+' '-' %left '*' '/' 模式。这方面与优先级规则没有任何关系。

算术运算符之间的关联性和优先级由以下几行建立:

{{1}}

同一行中的项目具有相同的优先级;以后的行具有更高的优先级。

如果您错过了一些紧急情况,那么Yacc通常会抱怨为“冲突”。可能会产生与您的意图背道而驰的明确语法,但是歧义不会在没有诊断的情况下消失。