解析Emacs Lisp

rej*_*eep 13 emacs parsing elisp

我在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:
  ...
Run Code Online (Sandbox Code Playgroud)

我并不关心密钥(int,string,...).我想要的价值.因此对于上面的文件int具有值"1,2,3,...",字符串"和,或者,然后,当"和文本"Lorem ..."(不包括破折号).

我正在考虑两种不同的解决方案,但我没有使用哪种解决方案.我是不是该:

  1. 创建一个循环遍历所有行的简单解析器,并为每一行匹配一些正则表达式,然后将我想要的部分分组?

  2. 用词法分析器和解析器做一个更复杂的解析器?

现在文件非常简单,我想我不需要像第二个选项那样做一些事情.但是这些文件可能会有点复杂,所以我想让它更容易扩展.

你怎么解决这个问题?

Dal*_*und 14

你是否已经熟悉递归下降解析器?用你最喜欢的编程语言(包括Emacs Lisp)手工编写它们相对容易.对于非常简单的解析,您通常可以使用looking-atsearch-forward.这些也将构成任何令牌化例程的基础,这些例程将由递归下降解析器或任何其他样式的解析器调用.

[2009年2月11日]我在下面的emacs lisp中添加了一个示例递归下降解析器.它解析简单的算术表达式,包括加法,减法,乘法,除法,取幂和带括号的子表达式.现在,它假设所有令牌都在全局变量中*tokens*,但如果您修改gettok并且peektok必要时可以让它们遍历缓冲区.要按原样使用它,只需尝试以下操作:

(setq *token* '( 3 ^ 5 ^ 7 + 5 * 3 + 7 / 11))
(rdh/expr)
=> (+ (+ (^ 3 (^ 5 7)) (* 5 3)) (/ 7 11))
Run Code Online (Sandbox Code Playgroud)

解析代码如下.

(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")))))
Run Code Online (Sandbox Code Playgroud)


Ale*_*Ott 5

对于解析器来说,从CEDET项目查看语义库


Tre*_*son 5

您可以在Emacs Wiki上找到一个相对简单的解析器:ParserCompiler

Emacs的Parser Compiler在纯elisp中创建递归下降解析器.

该项目的目标是创建一个既有创新又实用的Parser编译器.这是由Mike Mattie创建的原创作品 - codermattie@gmail.com

解析器由宏编译,将解析器定义DSL转换为纯elisp.语法目前支持PEG语法类.