Spec-Zone.ru › Elisp

Грамматики разбора выражений

Emacs Lisp предоставляет несколько инструментов для разбора и сопоставления текста: от регулярных выражений (см. Регулярные выражения) до полноценных парсеров грамматик слева направо (так называемых LL) (см. Разработка парсеров Bovine). Грамматики разбора выражений (PEG) — ещё один способ разбора текста, обеспечивающий большую структурированность и возможность композиции по сравнению с регулярными выражениями, но менее сложный, чем контекстно-свободные грамматики.

Грамматика разбора выражений (PEG) описывает формальный язык как набор правил распознавания строк этого языка. В Emacs парсер PEG определяется списком именованных правил, каждое из которых сопоставляет текстовые шаблоны и/или содержит ссылки на другие правила. Разбор запускается функцией peg-run или макросом peg-parse (см. ниже) и разбирает текст после точки в текущем буфере, используя заданный набор правил.

Каждое правило в PEG называется выражением разбора (PEX). Его можно задать строковым литералом, диапазоном или набором символов в стиле регулярных выражений, специальной конструкцией PEG, похожей на вызов функции Emacs Lisp, ссылкой на другое правило или комбинацией этих вариантов. Грамматика представляется в виде дерева правил, в котором одно из правил обычно считается «корневым» или «входным». Например:

((number sign digit (* digit))
 (sign   (or "+" "-" ""))
 (digit  [0-9]))

После определения грамматики можно использовать для разбора текста после точки в текущем буфере несколькими способами. Макрос peg-parse — самый простой из них:

Макрос: peg-parse &rest pexs

Сопоставляет pexs с текстом в точке.

(peg-parse
  (number sign digit (* digit))
  (sign   (or "+" "-" ""))
  (digit  [0-9]))

Этот макрос прост, но негибок: правила необходимо записывать непосредственно в исходном коде. Большую гибкость можно получить, комбинируя другие функции и макросы.

Макрос: with-peg-rules rules &rest body

Выполняет body с активным набором rules — списком выражений PEX. Внутри BODY разбор запускается вызовом peg-run.

Функция: peg-run peg-matcher &optional failure-function success-function

Эта функция принимает один аргумент peg-matcher — результат вызова peg (см. ниже) для именованного правила, обычно входного правила более крупной грамматики.

По завершении разбора вызывается либо failure-function, либо success-function — в зависимости от того, завершился ли разбор успешно. Если задана success-function, она должна быть функцией, получающей в качестве единственного аргумента анонимную функцию, которая выполняет все действия, накопленные в стеке во время разбора. По умолчанию эта анонимная функция просто выполняется. Если разбор завершается неудачей, функция, заданная в failure-function, вызывается со списком выражений PEG, сопоставление которых не удалось во время разбора. По умолчанию этот список отбрасывается.

Аргумент peg-matcher, передаваемый в peg-run, создаётся вызовом peg:

Макрос: peg &rest pexs

Преобразует pexs в единый peg-matcher, который можно передать в peg-run.

Приведённый выше пример peg-parse разворачивается в набор вызовов этих функций и в полном виде может быть записан так:

(with-peg-rules
    ((number sign digit (* digit))
     (sign   (or "+" "-" ""))
     (digit  [0-9]))
  (peg-run (peg number)))

Такой подход позволяет явно управлять «входной точкой» разбора и комбинировать правила из разных источников.

Отдельные правила также можно определять с помощью синтаксиса, более похожего на defun, используя макрос define-peg-rule:

Макрос: define-peg-rule name args &rest pexs

Определяет name как правило PEG, принимающее args и сопоставляющее pexs с текстом в точке.

Например:

(define-peg-rule digit ()
  [0-9])

Аргументы можно передавать правилам с помощью правила PEG funcall (см. Определения PEX).

Другой вариант — определить именованный набор правил с помощью define-peg-ruleset:

Макрос: define-peg-ruleset name &rest rules

Определяет name как идентификатор для rules.

(define-peg-ruleset number-grammar
  ;; `digit' here references the definition above.
  (number () sign digit (* digit))
  (sign () (or "+" "-" "")))

Правила и наборы правил, определённые таким образом, можно указывать по имени в последующих вызовах peg-run или with-peg-rules:

(with-peg-rules number-grammar
  (peg-run (peg number)))

По умолчанию вызовы peg-run или peg-parse не создают вывод: разбор лишь перемещает точку. Чтобы вернуть разобранные строки или выполнить с ними другие действия, правила могут содержать действия; см. Действия при разборе.

  • Определения PEX
  • Действия при разборе
  • Написание правил PEG

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Parsing-Expression-Grammars.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API