首页 > 解决方案 > 为具有适当优先级(包括括号)的二进制表达式创建语法

问题描述

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

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

标签: parsingbisonyacc

解决方案


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

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

%left '+' '-'
%left '*' '/'

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

如果你错过了一些边缘情况,那么 Yacc 通常会抱怨这是“冲突”。存在创建与您的意图相反的明确语法的风险,但如果没有诊断,歧义不会通过。


推荐阅读