yacc / bison语法:两条规则之间的区别是什么?

时间:2014-04-07 15:03:38

标签: grammar bison yacc parser-generator

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

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

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

规则1和2之间有什么区别?

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

1 个答案:

答案 0 :(得分:1)

如上所述,语法不明确,因为NotRec将匹配0个或更多T_NOTT_MINUS个令牌,因此如果您有Expr没有此类令牌在Term之前,它可以与规则1或规则2匹配。

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

的任何有限字符串

如果删除Expr: Term规则,则可以在不更改语法的情况下消除歧义。

如果您将此语法与yacc或bison一起使用,则由于模糊性,您将获得转移/减少冲突。使用shift的默认冲突解决方案将在不改变语言的情况下解决歧义 - 只要在您遗漏的语法部分中没有其他冲突使用这些令牌。对于没有Expr / T_NOT指令的任何T_MINUS,它将使用规则1;对于具有一个或多个此类令牌的任何Expr,它将使用规则2。这相当于将NotRec规则更改为

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

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