У меня есть грамматика с конфликтом LR (1), который я не могу решить; Тем не менее, грамматика должна быть однозначной. Сначала я продемонстрирую проблему на упрощенной грамматике с пятью токенами: (
, )
, {}
, ,
и id
.Как преобразовать эту грамматику в LR (1)?
EBNF будет выглядеть следующим образом:
args = (id ',')*
expression = id
| '(' expression ')'
| '(' args ')' '{}'
грамматика однозначна и требует не более двух жетонов опережающего просмотра. Когда (
сдвинут, есть только пять вариантов:
(
→ повторялись.)
→ Уменьшить как'(' args ')'
.id
)
не{}
→ Уменьшить как'(' expression ')'
.id
)
{}
→ Снижение в'(' args ')' '{}'
id
,
→ Снижение в'(' args ')' '{}'
(в конце концов).
Наивный перевод дает следующий результат (и conflicts):
formal_arg: Ident
{}
formal_args: formal_arg Comma formal_args
| formal_arg
| /* nothing */
{}
primary: Ident
| LParen formal_args Curly
| LParen primary RParen
{}
Таким образом, грамматика требует не более трех жетонов опережающего просмотра, чтобы решить. Я знаю, что грамматика LR (3) can be transformed для грамматики LR (1).
Однако я не совсем понимаю, как сделать преобразование в данном конкретном случае. Обратите внимание, что упрощенная грамматика выше - извлечение из larger body of code; в частности, можно ли преобразовать primary
, не касаясь expr
и всего выше?
На самом деле Я пришел к тому же выводу, что и вы. Тем не менее, мой генератор парсера (menhir) имеет правила более высокого порядка, поэтому я могу позволить ему делать ворчание для меня. Я, вероятно, сам отвечу на вопрос (если это сработает для меня), извините, что не принимаю! – whitequark
Самое смешное, что я знаю автора вопроса, с которым вы связались. – whitequark
Я просто пошел с твоей трансформацией, и это работает, хотя требуется набор странных преобразований в грамматику. Потрясающие. – whitequark