GLS Parser Combinator или Generator в/для C или С++

Существует ли какая-либо существующая реализация алгоритма GLL либо в виде комбинаторов парсеров (предпочтительнее), либо как генератор синтаксического анализа для C или С++?

Мои требования заключаются в том, что вывод представляет собой общий пакетный пар синтаксического разбора (SPPF), который я позже могу устранить с помощью семантических и/или контекстных правил. Существуют и другие алгоритмы синтаксического анализа, такие как GLR, которые могут справляться с общими контекстно-свободными грамматиками, однако все генераторы парсеров GLR я мог бы найти либо вернуть первое успешное дерево синтаксического анализа, либо потерпеть неудачу, если какая-либо неопределенность останется в конце.

Ответы

Ответ 1

Что делать, если вы попробуете GLL Combinators? Хотя он использует Scala, вы можете написать для него "тонкие" обертки с помощью JNI.

Комбинаторы GLL - это структура, предназначенная для реализации алгоритма синтаксического анализа GLL (Scott and Johnstone, LDTA 2009) в функциональной манере. Более конкретно, каркас использует комбинаторы атомного парсера для составления грамматик, которые затем оценивается с использованием алгоритма GLL. Структура обеспечивает синтаксис для этого задача, которая почти идентична заданной структуре комбинатора парсеров в Scala. Например, мы можем отобразить классическую грамматику круглых скобок, используя Комбинаторы GLL:

lazy val expr: Parser[Any] = (
    "(" ~ expr ~ ")"
  | ""
)

Как следует из аннотации типа, expr будет ссылаться на экземпляр типа Parser[Any]. То есть, атомный синтаксический анализатор, который потребляет некоторый ввод и возвращает значение типа Any. Мы можем вызвать этот синтаксический анализатор на вход Stringследующим образом:

expr("((()))")

Это вернет значение типа Stream[Result[Any]]. Result[A] ADT определяемый как один из следующих (для некоторого типа A):

  • Success[A] - представляет успешный синтаксический анализ и содержит результирующее значение.
  • Failure - представляет неудачный синтаксический анализ и содержит соответствующее сообщение об ошибке а также остальную часть потока синтаксического анализа (символы, которые не были потребляются).

Если какой-либо результат будет успешным (т.е. экземпляр Success[A]), то никаких сбоев будут возвращены. Таким образом, возвращенный Stream будет полностью однородным, содержащие либо Success, либо Failure, но не оба. A Stream является вместо одного значения, чтобы допускать двусмысленность в грамматике (см. ниже).

Стоит упомянуть, что GLL является формой рекурсивного спуска разбора. В нем есть все преимущества традиционного рекурсивного спуска, включая интуитивно понятный поток управления, произвольное позиционирование семантических действий и превосходная ошибка Сообщения. Фактически, это факт, что GLL - это рекурсивный спуск, который позволяет для реализации с использованием атомных комбинаторов. Другие алгоритмы, которые разделяют те же возможности, что и GLL (такие как GLR, Earley Parsing и т.д.), в основном несовместимые с моделью комбинатора из-за их крайне неинтуитивного контроля течь. При анализе GLL поток управления следует за сигналом грамматики, как это происходит в традиционных комбинаторах парсеров или в любой другой форме рекурсивного спуска.