【问题标题】:Creating a grammar for binary expressions with proper precedence (including parenthesis)为具有适当优先级(包括括号)的二进制表达式创建语法
【发布时间】:2019-06-21 04:48:26
【问题描述】:

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

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

【问题讨论】:

  • bison 不生成递归下降解析器。即便如此,也很难理解为什么您认为括号可能不起作用。也许你需要问一个更准确的问题。

标签: parsing bison yacc


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 所以基本上按照我构建语法的方式,我内置了括号的优先级。
  • 您构建语法的方式是,每个有括号的规则(到目前为止只有一个)都有一个左括号和一个匹配的右括号。语法中没有语法符号只匹配左括号或右括号。因此,没有歧义。我们知道如果表达式e 包含任何括号,它们是平衡的。这意味着'(' e ')' 没有歧义问题:右括号与同一规则中的左括号一起出现;它不被视为针对 e 内部的任何内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
  • 1970-01-01
  • 1970-01-01
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多