Парсинг в Emacs Lisp - PullRequest
       25

Парсинг в Emacs Lisp

13 голосов
/ 09 февраля 2010

Я пишу парсер в Emacs Lisp. Это парсер для текстовых файлов выглядит так:

rule:
  int: 1, 2, 3, ...
  string: and, or, then, when
  text:
  ----------
  Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque
  in tellus. In pharetra consequat augue. In congue. Curabitur
  pellentesque iaculis eros. Proin magna odio, posuere sed, commodo nec,
  varius nec, tortor.
  ----------
  more: ...

rule:
  ...

Меня не волнует ключ (int, string, ...). Я хочу значение. Поэтому для указанного выше файла int имеет значение "1, 2, 3, ...", строка «и, или, тогда, когда» и текст «Lorem ...» (исключая тире).

Я думаю о двух разных решениях, но не знаю, какое из них использовать. Должен ли я:

  1. создать простой парсер, который перебирает все строки и для каждого строка соответствует некоторому регулярному выражению, а затем группирует части, которые я хочу получить?

  2. сделать более сложный парсер с лексером и парсером?

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

Как бы вы решили это?

Ответы [ 3 ]

14 голосов
/ 09 февраля 2010

Вы уже знакомы с парсерами рекурсивного спуска ? Их относительно легко написать вручную на вашем любимом языке программирования, включая Emacs Lisp. Для очень простого анализа вы часто можете обойтись с помощью looking-at и search-forward. Они также послужат основой для любых токенизирующих подпрограмм, которые будут вызываться вашим анализатором рекурсивного спуска или любым другим стилем синтаксического анализатора.

[11 февраля 2009] Я добавил пример синтаксического анализатора рекурсивного спуска в emacs lisp ниже. Он анализирует простые арифметические выражения, включая сложение, вычитание, умножение, деление, возведение в степень и вложенные выражения в скобках. Прямо сейчас предполагается, что все токены находятся в глобальной переменной *tokens*, но если вы измените gettok и peektok по мере необходимости, вы можете заставить их проходить через буфер. Чтобы использовать его как есть, просто попробуйте следующее:

(setq *token* '( 3 ^ 5 ^ 7 + 5 * 3 + 7 / 11))
(rdh/expr)
=> (+ (+ (^ 3 (^ 5 7)) (* 5 3)) (/ 7 11))

Код разбора следующий.

(defun gettok ()
  (and *token* (pop *token*)))
(defun peektok ()
  (and *token* (car *token*)))

(defun rdh/expr ()
  (rdh/expr-tail (rdh/factor)))

(defun rdh/expr-tail (expr)
  (let ((tok (peektok)))
    (cond ((or (null tok)
           (equal tok ")"))
       expr)
      ((member tok '(+ -))
       (gettok)
       (let ((fac (rdh/factor)))
         (rdh/expr-tail (list tok expr fac))))
      (t (error "bad expr")))))

(defun rdh/factor ()
  (rdh/factor-tail (rdh/term)))

(defun rdh/factor-tail (fac)
  (let ((tok (peektok)))
    (cond ((or (null tok)
           (member tok '(")" + -)))
       fac)
      ((member tok '(* /))
       (gettok)
       (let ((term (rdh/term)))
         (rdh/factor-tail (list tok fac term))))
      (t (error "bad factor")))))

(defun rdh/term ()
  (let* ((prim (rdh/prim))
         (tok (peektok)))
    (cond ((or (null tok)
               (member tok '(")" + - / *)))
           prim)
          ((equal tok '^)
           (gettok)
           (list tok prim (rdh/term)))
          (t (error "bad term")))))

(defun rdh/prim ()
  (let ((tok (gettok)))
    (cond ((numberp tok) tok)
      ((equal tok "(")
       (let* ((expr (rdh/expr))
          (tok (peektok)))
         (if (not (equal tok ")"))
         (error "bad parenthesized expr")
           (gettok)
           expr)))
      (t (error "bad prim")))))
5 голосов
/ 09 февраля 2010

Существует относительно простой парсер, который вы можете найти в Emacs Wiki: ParserCompiler

Создает Parser Compiler для Emacs Парсеры рекурсивного спуска в чистом виде Elisp.

Целью проекта является создание полезный компилятор парсера инновационный и практически полезный. Это оригинальная работа, созданная Майк Мэтти - codermattie@gmail.com

Парсеры скомпилированы макросом, который переводит определение парсера DSL в чистый elisp. Синтаксис поддерживает Класс грамматики PEG в настоящее время.

5 голосов
/ 09 февраля 2010

для парсера смотрите в семантическую библиотеку из CEDET проекта

...