GLL Parser Combinator или генератор в / для C или C++
Существует ли какая-либо существующая реализация алгоритма GLL, либо в форме комбинаторов синтаксического анализа (предпочтительно), либо в качестве генератора синтаксического анализатора для C или C++?
Мои требования состоят в том, чтобы выходные данные представляли собой общий упакованный лес анализа (SPPF), который позже я могу устранить неоднозначность, используя семантические и / или контекстные правила. Существуют и другие алгоритмы синтаксического анализа, такие как GLR, которые могут справиться с общими контекстно-свободными грамматиками, однако все генераторы синтаксического анализатора GLR, которые я смог найти, либо возвращают первое успешное дерево синтаксического анализа, либо завершаются неудачей, если в конце сохраняется неопределенность.
1 ответ
Что если вы попробуете GLL Combinators? Хотя он использует Scala, вы можете написать для него "тонкие" оболочки с помощью JNI.
GLL Combinators - это структура, разработанная для функциональной реализации алгоритма синтаксического анализа GLL (Скотт и Джонстон, LDTA 2009). Более конкретно, в фреймворке используются атомарные синтаксические анализаторы для составления грамматик, которые затем оцениваются с использованием алгоритма GLL. Платформа обеспечивает синтаксис для этой задачи, который почти идентичен синтаксису структуры комбинатора синтаксического анализатора, встроенной в Scala. Например, мы можем отобразить классическую "грамматику скобок" с помощью комбинаторов GLL:
lazy val expr: Parser [Any] = ("(" ~ expr ~ ")" | "")Как следует из аннотации типа,
expr
будет ссылаться на экземпляр типаParser[Any]
, То есть атомарный синтаксический анализатор, который потребляет некоторый ввод и возвращает значение типаAny
, Мы можем вызвать этот парсер противString
Ввести следующим образом:выражение ("((()))")Это вернет значение типа
Stream[Result[Any]]
,Result[A]
ADT определяется как одно из следующего (для некоторого типаA
):
Success[A]
- Представляет успешный анализ и содержит результирующее значение.Failure
- Представляет сбой анализа и содержит соответствующее сообщение об ошибке, а также остаток потока анализа (символы, которые не были использованы).Если какой-либо результат успешен (например, экземпляр
Success[A]
), то никакие сбои не будут возвращены. Таким образомStream
возвращается будет полностью однородным, содержащим либоSuccess
или жеFailure
, но не оба.Stream
возвращается, а не одно значение, чтобы допустить неоднозначность в грамматике (см. ниже).Стоит упомянуть, что GLL является формой рекурсивного анализа. Он обладает всеми преимуществами обычного рекурсивного спуска, включая интуитивно понятный поток управления, произвольное позиционирование семантических действий и превосходные сообщения об ошибках. Фактически, это тот факт, что GLL является рекурсивным спуском, что позволяет реализовать его с использованием атомных комбинаторов. Другие алгоритмы, которые имеют те же возможности, что и GLL (такие как GLR, анализ Earley и т. Д.), В корне несовместимы с моделью комбинатора из-за их крайне неинтуитивного потока управления. При разборе GLL поток управления следует за грамматикой, как это происходит в традиционных комбинаторах синтаксического анализа или любой другой форме рекурсивного спуска.