Основной проблемой, приводящей к конфликтам, является ваша обработка commands
. Ваше намерение состоит в том, чтобы определить commands
как ноль или более command
с, что записывается следующим образом:
commands: %empty
| commands command
Если бы вы хотели настаивать на наличии хотя бы одной команды, вы бы написали:
commands: command
| commands command
Смешивание двух форм не будет работать, так как синтаксический анализатор не будет знать, начинать ли последовательность command
s с нуля (%empty
) или с одного command
. Вы должны попытаться точно понять, почему это приводит к двусмысленности; Вы найдете несколько примеров подобных проблем на этом сайте. Например, см. этот вопрос .
Это вызывает 21 сдвиг / уменьшение конфликтов. Конфликты уменьшения / уменьшения являются результатом любопытных постановок:
switch_block: switch_stm commands
if_block: if_stm commands
Операторы
if
и switch
представляют собой отдельные элементы command
внутри последовательности commands
; все, что следует за оператором switch
или if
, будет следующим command
в commands
. Определение switch_block
для включения следующих команд совершенно неоднозначно: фактически, это говорит о том, что следующий command
все еще может быть частью switch_block
, или это может быть command
после switch_block
.
Выше я специально рассмотрел вопрос, который вы задали: конфликт таблиц анализа в вашей грамматике. Существуют и другие проблемы с вашей грамматикой и лексическими спецификациями, и я настоятельно рекомендую вам изучить любые материалы, которые вам дали о зубре / гибкости, и / или прочитать инструкции bison и flex . .
В качестве руководства по чтению руководств или других материалов я бы посоветовал вам сосредоточиться как минимум на двух вещах:
Обработка семантических значений. Никогда не требуется, чтобы синтаксическое ключевое слово имело свое собственное представление в качестве семантического значения; действительно, синтаксические ключевые слова редко требуют семантических значений вообще. Если токен требует, чтобы его семантическое значение было его представлением, вы должны помнить, что yytext
является указателем на личный буфер данных, который вам не принадлежит и который будет изменен без предупреждения. Поэтому требуется копирование.
Встраиваемые языки, такие как ваш вариант PHP, включают два разных лексических контекста. У вас есть внешний, по сути не интерпретируемый контекст, и встроенный контекст, который содержится между @
и @end;
. (F) lex предоставляет начальные условия , чтобы помочь справиться с такого рода встраиванием. В руководстве есть несколько примеров, и на этом сайте еще много информации.