Jump to content

Парсер-комбинатор

В компьютерном программировании комбинатор парсеров — это функция высшего порядка , которая принимает несколько парсеров на вход и возвращает новый синтаксический анализатор на выходе. В этом контексте синтаксический анализатор — это функция, принимающая строки в качестве входных данных и возвращающая некоторую структуру в качестве выходных данных, обычно дерево синтаксического анализа или набор индексов, представляющих места в строке, где синтаксический анализ успешно остановлен. Комбинаторы синтаксических анализаторов реализуют стратегию рекурсивного спуска , которая упрощает модульное кусочное построение и тестирование. Этот метод анализа называется комбинаторным анализом .

Парсеры, использующие комбинаторы, широко использовались при создании прототипов компиляторов и процессоров для предметно-ориентированных языков, таких как интерфейсы естественного языка к базам данных, где сложные и разнообразные семантические действия тесно интегрированы с синтаксической обработкой. В 1989 году Ричард Фрост и Джон Лаунбери продемонстрировали [1] использование комбинаторов парсеров для создания интерпретаторов естественного языка . Грэм Хаттон также использовал функции высшего порядка для базового синтаксического анализа в 1992 году. [2] и монадический анализ в 1996 году. [3] С.Д. Свирстра также продемонстрировал практические аспекты синтаксических комбинаторов в 2001 году. [4] В 2008 году Фрост, Хафиз и Каллаган [5] описал набор комбинаторов парсеров в Haskell , которые решают давнюю проблему размещения левой рекурсии и работают как полноценный инструмент нисходящего синтаксического анализа в полиномиальном времени и пространстве.

Основная идея

[ редактировать ]

В любом языке программирования, который имеет первоклассные функции , комбинаторы синтаксических анализаторов могут использоваться для объединения базовых анализаторов для создания анализаторов для более сложных правил. Например, правило продукции контекстно -свободной грамматики (CFG) может иметь одну или несколько альтернатив, и каждая альтернатива может состоять из последовательности нетерминалов и/или терминалов, или альтернатива может состоять из один нетерминал или терминал или пустая строка. Если для каждой из этих альтернатив доступен простой анализатор, можно использовать комбинатор анализаторов для объединения каждого из этих анализаторов, возвращая новый анализатор, который может распознавать любую или все альтернативы.

В языках, поддерживающих перегрузку операторов , комбинатор парсеров может принимать форму инфиксного оператора , используемого для объединения разных парсеров в единое правило. Таким образом, комбинаторы парсеров позволяют определять парсеры во встроенном стиле, в коде, который по структуре аналогичен правилам формальной грамматики. Таким образом, реализации можно рассматривать как исполняемые спецификации со всеми вытекающими отсюда преимуществами, такими как удобочитаемость.

Комбинаторы

[ редактировать ]

Чтобы обсуждение было относительно простым, мы обсуждаем комбинаторы синтаксических анализаторов только с точки зрения распознавателей . Если входная строка имеет длину #input и доступ к его членам осуществляется через индекс jраспознаватель — это анализатор, который возвращает на выходе набор индексов, представляющих индексы, на которых анализатор успешно завершил распознавание последовательности токенов, начинающихся с индекса j. Пустой набор результатов указывает на то, что распознавателю не удалось распознать какую-либо последовательность, начинающуюся с индекса. j.

  • The empty Распознаватель распознает пустую строку. Этот анализатор всегда завершается успешно, возвращая одноэлементный набор, содержащий входной индекс:
  • Распознаватель term x распознает терминал x. Если токен по индексу j во входной строке есть x, этот синтаксический анализатор возвращает одноэлементный набор, содержащий j + 1; в противном случае он возвращает пустой набор.

Даны два распознавателя p и q, мы можем определить два основных комбинатора синтаксического анализатора: один для сопоставления альтернативных правил и один для правил упорядочивания:

  • «Альтернативный» комбинатор синтаксического анализатора ⊕ применяет каждый из распознавателей к одному и тому же индексу. j и возвращает объединение конечных индексов распознавателей:
  • Комбинатор «последовательность» ⊛ применяет первый распознаватель. p к входному индексу j, и для каждого конечного индекса применяется второй распознаватель q с этим в качестве стартового индекса. Он возвращает объединение индексов завершения, возвращаемых всеми вызовами q:

Может существовать несколько различных способов анализа строки с завершением по одному и тому же индексу, что указывает на неоднозначную грамматику . Простые распознаватели не признают этих двусмысленностей; каждый возможный индекс окончания указывается в наборе результатов только один раз. Для получения более полного набора результатов более сложный объект, например дерево разбора необходимо вернуть .

Рассмотрим весьма неоднозначную контекстно-свободную грамматику , s ::= ‘x’ s s | ε. Используя определенные ранее комбинаторы, мы можем модульно определить исполняемые обозначения этой грамматики на современном функциональном языке (например, Haskell ) как s = term ‘x’ <*> s <*> s <+> empty. Когда распознаватель s применяется по индексу 2 входной последовательности x x x x x он вернет набор результатов {2,3,4,5}, что указывает на наличие совпадений, начинающихся с индекса 2 и заканчивающихся любым индексом от 2 до 5 включительно.

Недостатки и решения

[ редактировать ]

Комбинаторы синтаксических анализаторов, как и все анализаторы рекурсивного спуска , не ограничиваются контекстно-свободными грамматиками и, таким образом, не выполняют глобального поиска неоднозначностей в LL( k ) синтаксическом анализе First k и Follow k наборов . Таким образом, неоднозначности не известны до момента выполнения, если и до тех пор, пока входные данные не вызовут их. В таких случаях анализатор рекурсивного спуска может по умолчанию (возможно, неизвестный разработчику грамматики) выбрать один из возможных неоднозначных путей, что приводит к семантической путанице (алиасингу) при использовании языка. Это приводит к ошибкам пользователей неоднозначных языков программирования, о которых не сообщается во время компиляции и которые возникают не в результате человеческой ошибки, а из-за неоднозначной грамматики. Единственное решение, которое устраняет эти ошибки, — это устранить двусмысленности и использовать контекстно-свободную грамматику.

Простые реализации комбинаторов синтаксического анализатора имеют некоторые недостатки, которые характерны для синтаксического анализа сверху вниз. Наивный комбинаторный анализ требует экспоненциального времени и пространства при анализе неоднозначной контекстно-свободной грамматики. В 1996 году Фрост и Шидловски продемонстрировали, как мемоизацию с комбинаторами синтаксического анализатора, чтобы уменьшить временную сложность до полиномиальной. можно использовать [6] Позже Фрост использовал монады для создания комбинаторов для систематического и правильного объединения мемо-таблиц в ходе вычислений. [7]

сверху вниз Как и любой рекурсивный анализ спуска , обычные комбинаторы синтаксического анализатора (например, комбинаторы, описанные выше) не завершаются при обработке леворекурсивной грамматики (например, s ::= s <*> term ‘x’|empty). Алгоритм распознавания, который учитывает неоднозначные грамматики с помощью прямых леворекурсивных правил, описан Фростом и Хафизом в 2006 году. [8] Алгоритм ограничивает постоянно растущий леворекурсивный анализ, налагая ограничения на глубину. Этот алгоритм был расширен до полного алгоритма синтаксического анализа для обеспечения как косвенной, так и прямой левой рекурсии за полиномиальное время , а также для создания компактных представлений полиномиального размера потенциально экспоненциального числа деревьев синтаксического анализа для весьма неоднозначных грамматик Фростом, Хафизом и Каллаганом в 2007. [9] Этот расширенный алгоритм учитывает косвенную левую рекурсию, сравнивая ее «вычисленный контекст» с «текущим контекстом». Те же авторы также описали свою реализацию набора комбинаторов парсеров, написанных на языке программирования Haskell и основанных на том же алгоритме. [5] [10]

Примечания

[ редактировать ]
  1. ^ Фрост и Лаунбери 1989 .
  2. ^ Хаттон 1992 .
  3. ^ Хаттон, Грэм; Мейер, Эрик. «Монадические парсеры-комбинаторы» (PDF) . Университет Ноттингема . Проверено 13 февраля 2023 г. {{cite journal}}: Для цитирования журнала требуется |journal= ( помощь )
  4. ^ Свирстра 2001 .
  5. ^ Перейти обратно: а б Фрост, Хафиз и Каллаган 2008 .
  6. ^ Фрост и Шидловски 1996 .
  7. ^ Мороз 2003 .
  8. ^ Фрост и Хафиз 2006 .
  9. ^ Фрост, Хафиз и Каллаган 2007 .
  10. ^ см . X исполняемые характеристики грамматр - SAIGA


Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 59acec7cf8ef080be9f1dc4979573112__1718857980
URL1:https://arc.ask3.ru/arc/aa/59/12/59acec7cf8ef080be9f1dc4979573112.html
Заголовок, (Title) документа по адресу, URL1:
Parser combinator - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)