Spec-Zone.ru › Elisp

Написание правил PEG

При написании правил PEG следует учитывать, что они жадные. Правила, которые могут потреблять переменное количество текста, всегда будут потреблять максимально возможное количество, даже если из-за этого правило, которое иначе могло бы совпасть, впоследствии завершится неудачей — возврата нет. Например, это правило никогда не завершится успешно:

(forest (+ "tree" (* [blank])) "tree" (eol))

PEX (+ "tree" (* [blank])) потребит все повторения слова «tree», не оставив ни одного для совпадения с последним «tree».

В таких ситуациях нужного результата можно добиться с помощью предикатов и защитных условий — а именно выражений not, if и guard, — чтобы ограничить поведение. Например:

(forest (+ "tree" (* [blank])) (not (eol)) "tree" (eol))

Операторы if и not принимают выражение разбора и интерпретируют его как логическое значение, не перемещая точку. Содержимое оператора guard вычисляется как обычный Lisp (а не как PEX) и должно возвращать логическое значение. Значение nil приводит к неудаче сопоставления.

Ещё одно потенциально неожиданное поведение: разбор перемещает точку настолько далеко, насколько это возможно, даже если в итоге разбор завершается неудачей. Это правило:

(end-game "game" (eob))

при запуске в буфере, в котором после точки находится текст «game over», переместит точку сразу за «game», а затем остановит разбор, вернув nil. Успешный разбор всегда возвращает t или контексты стека разбора.

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/Writing-PEG-Rules.html

Spec-Zone.ru

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