野牛:单一规则中的可选令牌

时间:2010-04-19 17:31:39

标签: grammar bison flex-lexer

我正在使用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给了我一个错误。

由于

3 个答案:

答案 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 '}' {
}