У меня проблемы с пониманием сдвига / уменьшения конфликта для грамматики, которая, как я знаю, не имеет двусмысленности. Этот случай относится к типу if else, но это не проблема 'dangling else', поскольку у меня есть обязательные предложения END, разделяющие блоки кода.
Вот грамматика для gppg (это компилятор, похожий на бизон, и это не было эхом):
%output=program.cs
%start program
%token FOR
%token END
%token THINGS
%token WHILE
%token SET
%token IF
%token ELSEIF
%token ELSE
%%
program : statements
;
statements : /*empty */
| statements stmt
;
stmt : flow
| THINGS
;
flow : '#' IF '(' ')' statements else
;
else : '#' END
| '#' ELSE statements '#' END
| elseifs
;
elseifs : elseifs '#' ELSEIF statements else
| '#' ELSEIF statements else
;
Вот вывод конфликта:
// Parser Conflict Information for grammar file "program.y"
Shift/Reduce conflict on symbol "'#'", parser will shift
Reduce 10: else -> elseifs
Shift "'#'": State-22 -> State-23
Items for From-state State 22
10 else: elseifs .
-lookahead: '#', THINGS, EOF
11 elseifs: elseifs . '#' ELSEIF statements else
Items for Next-state State 23
11 elseifs: elseifs '#' . ELSEIF statements else
// End conflict information for parser
Я уже переключился вокруг всего, и я знаю, как его решить, но это решение включает отказ от левой рекурсии на 'elseif' для правой рекурсии.
Я просмотрел всю скудную документацию, которую нашел в Интернете по этому вопросу (я публикую несколько ссылок в конце), и до сих пор не нашел элегантного решения. Я знаю о ANTLR и не хочу сейчас об этом думать. Пожалуйста, ограничьте свое решение парсерами Yacc / Bison.
Я был бы признателен за элегантные решения, мне удалось сделать это, уничтожив правила / * empty * / и продублировав все, что требовало пустого списка, но в большой грамматике, над которой я работаю, это просто заканчивается как «синдром спаргетти грамматики».
Вот несколько ссылок:
http://nitsan.org/~maratb/cs164/bison.html
http://compilers.iecc.com/comparch/article/98-01-079
GPPG, парсер, который я использую
Руководство для зубров