Бизон: дополнительные токены в одном правиле - PullRequest
10 голосов
/ 19 апреля 2010

Я использую 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 ...
 } 

Но Бизон дал мне ошибку.

Спасибо

Ответы [ 3 ]

10 голосов
/ 19 апреля 2010

Короче говоря, нет. Bison имеет дело только с грамматикой LALR (1), что означает, что он использует только один символ предвкушения. Вам нужно что-то вроде этого:

statement: T_CLASS T_IDENT extension_list '{' ...

extension_list: 
              | T_EXTENDS T_IDENT_LIST
              ;

Есть и другие генераторы синтаксических анализаторов, которые работают с более общими грамматиками. Если память служит, некоторые из них поддерживают дополнительные элементы относительно напрямую, как вы просите.

1 голос
/ 19 апреля 2010

Почему бы вам просто не разделить их с помощью оператора выбора (|)?

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?), Чтобы делать то, что вы хотите сделать ..

0 голосов
/ 19 апреля 2010

Я думаю, что самое большее, что вы можете сделать, это

statement : T_CLASS T_IDENT  '{' T_CLASS_MEMBERS '}'
    | T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST  '{' T_CLASS_MEMBERS '}' {
}
...