Shift/Reduce 变量声明冲突
Shift/Reduce conflict in variable declaration
我正在使用 bison 编写类 C 语法的解析器,但我在变量声明中遇到问题。
我的变量可以是简单变量、数组或结构,所以我可以有一个像 a.b[3].c.
这样的变量
我有以下规则:
var : NAME /* NAME is a string */
| var '[' expr ']'
| var '.' var
;
这给我带来了 shift/reduce 冲突,但我想不出解决这个问题的方法。
如何重写语法或使用 Bison 优先级来解决问题?
我不知道您为什么希望 .
和 []
运算符具有关联性,但是这样的事情可能会启发您。
y
%union{}
%token NAME
%start var
%left '.'
%left '['
%%
var:
NAME
| var '[' expr ']'
| var '.' var
此外,由于var
可能出现在expr
中,因此语法可能存在其他问题。
当然可以通过优先级声明来解决这种 shift-reduce 冲突,但在我看来,这只会让语法更难阅读。最好让语法反映语言的语义。
A var
(有些人可能称之为左值或引用)要么是简单标量变量的名称,要么是从 var
命名复杂值和选择器,成员名称或数组索引。换句话说:
var : NAME
| var selector
;
selector: '.' NAME
| '[' expression ']'
;
这使得a.b[3].c
的含义很清楚,例如;语义由解析树描述:
a.b[3].c
+----+----+
| |
a.b[3] .c
+---+--+
| |
a.b [3]
+-+-+
| |
a .b
没有必要创建selector
规则;将这两个规则放在一起是微不足道的。如果你不觉得上面写的更清楚,下面的也行:
var: NAME
| var '.' NAME
| var '[' expression ']'
;
我正在使用 bison 编写类 C 语法的解析器,但我在变量声明中遇到问题。
我的变量可以是简单变量、数组或结构,所以我可以有一个像 a.b[3].c.
这样的变量我有以下规则:
var : NAME /* NAME is a string */
| var '[' expr ']'
| var '.' var
;
这给我带来了 shift/reduce 冲突,但我想不出解决这个问题的方法。
如何重写语法或使用 Bison 优先级来解决问题?
我不知道您为什么希望 .
和 []
运算符具有关联性,但是这样的事情可能会启发您。
y
%union{}
%token NAME
%start var
%left '.'
%left '['
%%
var:
NAME
| var '[' expr ']'
| var '.' var
此外,由于var
可能出现在expr
中,因此语法可能存在其他问题。
当然可以通过优先级声明来解决这种 shift-reduce 冲突,但在我看来,这只会让语法更难阅读。最好让语法反映语言的语义。
A var
(有些人可能称之为左值或引用)要么是简单标量变量的名称,要么是从 var
命名复杂值和选择器,成员名称或数组索引。换句话说:
var : NAME
| var selector
;
selector: '.' NAME
| '[' expression ']'
;
这使得a.b[3].c
的含义很清楚,例如;语义由解析树描述:
a.b[3].c
+----+----+
| |
a.b[3] .c
+---+--+
| |
a.b [3]
+-+-+
| |
a .b
没有必要创建selector
规则;将这两个规则放在一起是微不足道的。如果你不觉得上面写的更清楚,下面的也行:
var: NAME
| var '.' NAME
| var '[' expression ']'
;