я использую Бизона GNU 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 работает только с грамматиками LALR (1), что означает, что он использует только один символ просмотра вперед. Что вам нужно, это что-то вроде этого:
statement: T_CLASS T_IDENT extension_list '{' ...
extension_list:
| T_EXTENDS T_IDENT_LIST
;
Есть и другие генераторы парсеров, которые работают с более общими грамматиками. Если память не изменяет, некоторые из них поддерживают необязательные элементы относительно напрямую, как вы просите.
Я думаю, самое большее, что вы можете сделать, это
statement : T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}'
| T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' {
}
Почему бы вам просто не разделить их с помощью оператора выбора ( |
)?
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?), чтобы делать то, что вы хотите сделать ..
{{1 }}