【问题标题】:yacc/bison grammar: whats the difference between two rules?yacc/bison 语法:两条规则有什么区别?
【发布时间】:2014-04-07 15:03:37
【问题描述】:

我必须编写某种解析器,使用 yacc 和 bison 等工具非常容易。但我有以下问题:

NotRec: /*empty*/
| NotRec T_NOT
| NotRec T_MINUS
;

Expr:
| Term /*1*/
| NotRec Term /*2*/
;

规则 1 和 2 有什么区别?

在我看来NotRec 可以为空(因为它有一个空分支),因此Term 应该与NotRec Term 相同。但如果我删除第一条规则,我会得到不同的结果!

【问题讨论】:

  • 有什么不同的结果?对于第一条规则,语法是模棱两可的,bison 应该警告您存在移位/归约冲突。
  • 不,我没有遇到野牛错误。但是解析器(bison-result)接受不同的输入......
  • 我收到了来自野牛的 shift/reduce 警告。也许有一些你没有提到的东西。请提供一个更完整的例子;见stackoverflow.com/help/mcve
  • 您没有显示Term 的规则,所以这有点推测,但您的规则 1 允许使用 Term 的单项表达式,仅此而已,而规则2 允许Term 前面有NotRec,这似乎是T_NOTT_MINUS 项的可能空序列。此外,正如@rici 所提到的,存在一些歧义(最明显的一个是空字符串可以表示NotRecExpr)...

标签: grammar bison yacc parser-generator


【解决方案1】:

正如所写,语法是模棱两可的,因为 NotRec 将匹配 0 个或多个 T_NOTT_MINUS 标记,所以如果你有一个 ExprTerm 之前没有这样的标记,它可以由规则 1 或规则 2 匹配。

如果您删除 NotRec: /*empty*/ 规则,那么 NotRec 将变得无用,因为它不会匹配任何有限的令牌序列。这会更改语言,删除 T_NOT/T_MINUS 的任何有限字符串。

如果您删除 Expr: Term 规则,则无需更改语言即可消除歧义。

如果您在 yacc 或 bison 中按原样使用此语法,则会由于歧义而产生 shift/reduce 冲突。使用 shift 的默认冲突解决方案将在不更改语言的情况下解决歧义——只要在您遗漏的语法部分中没有这些标记的其他冲突使用。它将对没有 T_NOT/T_MINUS 指令的任何 Expr 使用规则 1,对带有一个或多个此类令牌的任何 Expr 使用规则 2。这相当于将NotRec规则改为

NotRec: T_NOT
      | T_MINUS
      | NotRec T_NOT
      | NotRec T_MINUS
      ;

这使得NotRec 匹配一个或多个令牌,而不是零个或多个。

【讨论】:

    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    相关资源
    最近更新 更多