我正在使用GNU Bison 2.4.2为我正在研究的新语言编写语法,我有一个问题。 当我指定规则时,让我们说:
statement : T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}' {
// create a node for the statement ...
}
如果我对规则有变化,例如
statement : T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' {
// create a node for the statement ...
}
其中(来自弹性扫描仪规则):
"class" return T_CLASS;
"extends" return T_EXTENDS;
[a-zA-Z\_][a-zA-Z0-9\_]* return T_IDENT;
(而T_IDENT_LIST是逗号分隔标识符的规则)。
有没有办法只在一个规则中指定所有这些,将“T_EXTENDS T_IDENT_LIST”设置为可选? 我已经尝试了
T_CLASS T_IDENT (T_EXTENDS T_IDENT_LIST)? '{' T_CLASS_MEMBERS '}' {
// create a node for the statement ...
}
但是Bison给了我一个错误。
由于
答案 0 :(得分:10)
长话短说不。 Bison只处理LALR(1)语法,这意味着它只使用一个前瞻符号。你需要的是这样的:
statement: T_CLASS T_IDENT extension_list '{' ...
extension_list:
| T_EXTENDS T_IDENT_LIST
;
还有其他解析器生成器可以使用更通用的语法。如果内存服务,其中一些支持可选元素,就像你要求的那样。
答案 1 :(得分:1)
为什么不用选择(|
)运算符来分割它们?
statement:
T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}'
| T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}'
我认为你不能仅仅因为这是一个LALR(1)自下而上的解析器,你需要一些不同的东西,如LL(k)(ANTLR?)来做你想做的事情。
答案 2 :(得分:0)
我认为你能做的最多就是
statement : T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}'
| T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' {
}