LR (k) в LR (1) преобразование грамматики

Меня смущает следующая цитата из Википедии:

Другими словами, если язык был достаточно разумным, чтобы позволить эффективный однопроходный синтаксический анализатор, он мог быть описан грамматикой LR (k). И эту грамматику всегда можно было механически преобразовать в эквивалентную (но более крупную) грамматику LR (1). Таким образом, метод синтаксического анализа LR (1) теоретически был достаточно мощным, чтобы обрабатывать любой разумный язык. На практике естественная грамматика для многих языков программирования близка к LR (1).

Это означает, что генератор синтаксического анализатора, такой как bison, очень мощный (поскольку он может обрабатывать LR(k) грамматики), если можно преобразовать грамматику LR(k) в грамматику LR(1). Существуют ли примеры этого или рецепт, как это сделать? Я хотел бы знать это, поскольку у меня есть конфликт сдвига / уменьшения в моей грамматике, но я думаю, что это потому, что это LR(2) грамматика, и я хотел бы преобразовать ее в LR(1) грамматику. Дополнительный вопрос: C++ необоснованный язык, поскольку я читал, что созданные bison парсеры не могут его проанализировать.


person user1095108    schedule 19.12.2013    source источник


Ответы (1)


Ссылки на алгоритм общего назначения для поиска покрывающей LR(1) грамматики для LR(k) грамматики см. В Реальные LR (k ›1) грамматики?

Алгоритм общего назначения производит довольно большие грамматики; на самом деле, я почти уверен, что полученный КПК будет такого же размера, как и КПК LR(k). Однако в отдельных случаях можно найти более простые решения. Однако применяется общий принцип: вам нужно отложить решение о сдвиге / сокращении путем безоговорочного сдвига до тех пор, пока решение не будет принято с помощью одного лексемы упреждающего просмотра.

Один пример: Является ли грамматика лямбда-выражений C # LALR (1)?

Не зная более подробной информации о вашей грамматике, я ничем не могу больше помочь.

Что касается C ++, то вещи, которые затрудняют синтаксический анализ, - это препроцессор и некоторые угловые случаи при синтаксическом анализе (и лексировании) экземпляров шаблонов. Тот факт, что синтаксический анализ выражения зависит от «типа» (а не от типа) символа (в контексте, в котором этот символ встречается), усложняет точный синтаксический анализ с помощью bison. [1] «Неразумно» - это оценочное суждение, которое мне не нравится; конечно, поддержка инструментов (таких как точные раскраски синтаксиса и завершители табуляции) была бы простой с другой грамматикой, но свидетельства того, что написать (или даже прочитать) хороший код C ++ не так уж и сложно.


Примечания:

[1] Классический сложный синтаксический анализ, который также применяется к C, - это (a)*b, который представляет собой приведение разыменования, если a представляет тип, а в противном случае - умножение. Если бы вы написали это в контексте: c/(a)*b, было бы ясно, что AST не может быть построен, не зная, является ли он отливкой или продуктом, поскольку это влияет на форму AST,

Еще одна проблема, более специфичная для C ++: x<y>(z) (или x<y<z>>(3)), которые анализируют (и, возможно, токенизируют) по-разному, в зависимости от того, называет x шаблон или нет.

person rici    schedule 19.12.2013