14

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

谢谢

4

3 回答 3

14

长话短说,不。Bison 只处理 LALR(1) 语法,这意味着它只使用一个前瞻符号。你需要的是这样的:

statement: T_CLASS T_IDENT extension_list '{' ...

extension_list: 
              | T_EXTENDS T_IDENT_LIST
              ;

不过,还有其他解析器生成器可以使用更通用的语法。如果没记错的话,它们中的一些会像您要求的那样相对直接地支持可选元素。

于 2010-04-19T17:40:50.093 回答
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?) 来做你想做的事情。

于 2010-04-19T17:43:02.223 回答
0

我认为你能做的最多的是

statement : T_CLASS T_IDENT  '{' T_CLASS_MEMBERS '}'
    | T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST  '{' T_CLASS_MEMBERS '}' {
}
于 2010-04-19T17:41:33.523 回答