Yacc 我是否被迫使用%glr解析器?

Yacc 我是否被迫使用%glr解析器?,yacc,bison,Yacc,Bison,我一直在避免换档/减少错误。现在我想我终于遇到了我的对手 Int[] a a[0] = 1 问题是int[]被定义为 Type OptSquareBrackets 而[0]定义为 Var | Var '[' expr ']' Var和Type都定义为Var,它是任何有效变量[a-zA-Z][a-zA-Z0-9.]。除了添加一个虚拟令牌(例如**Decl**Type OptSquareBrackets)之外,还有没有一种方法可以写入此令牌以避免冲突?从这条规则中,我得到一个shift/red

我一直在避免换档/减少错误。现在我想我终于遇到了我的对手

Int[] a
a[0] = 1
问题是int[]被定义为

Type OptSquareBrackets
而[0]定义为

Var | Var '[' expr ']'

Var和Type都定义为Var,它是任何有效变量
[a-zA-Z][a-zA-Z0-9.]
。除了添加一个虚拟令牌(例如
**Decl**Type OptSquareBrackets
)之外,还有没有一种方法可以写入此令牌以避免冲突?从这条规则中,我得到一个shift/reduce和一个reduce/reduce警告。

您能定义一个新的令牌吗

VarLBracket [a-zA-Z][a-zA-Z0-9_]*\[
并因此定义声明

Type | VarLBracket ']';
并将分配目标定义为

Var | VarLBracket expr ']';

从技术上讲,这个问题源于试图将语法与实际上在语法上没有差异的语义联系起来

ISTM指出,您只需要一个描述类型和表达式的语法结构。区分代码和语法,尤其是在实际上没有语法差异的情况下。Yacc被称为编译器生成器,但它一点也不正确。它只会生成解析器


话虽如此,将
[]
识别为终端符号可能是解决问题和继续工作的更简单方法。Yacc不太擅长含糊不清的语法,它需要尽早决定遵循哪条路径。

使用[]创建一个Lex规则,因为[]仅用于声明中,其他地方使用[var]

是错误的,但它接近解决方案。为[]定义单独的令牌,因为在其他地方它不是[],而是[var]