在 Common Lisp (SBCL) 中,你如何解析文件?

In Common Lisp (SBCL) how do you parse a file?

我有一个文件:test.lisp,内容如下:

(+ 3 3)

(let ((n 3)) (+ n 1))

(let ((n 4))
  (+ n 1))

(defun d (f)
  (let ((n 3)
    (f 4)
    (g 3))
    (if (= n 0)
    (+ n f g)
      (* n f g))))

我正在尝试这样读取文件:

  (let ((in (open dd)))
   (when in 
    (loop for line = (read-line in nil)
     while line do (format t "~a~%" line))
     (close in)))

这给了我明显正确的输出:

(+ 3 3)

(let ((n 3)) (+ n 1))

(let ((n 4))
  (+ n 1))

(defun d (f)
  (let ((n 3)
    (f 4)
    (g 3))
    (if (= n 0)
    (+ n f g)
      (* n f g))))

我想在对应于上面每个表达式的文件的每一行调用我的函数parse-exp

根据 Whosebug 上的不同答案,我尝试这样做:

* (defun get-file (filename)
   (let ((in (open filename)))
    (loop for line = (read-line in nil)
     while line
     collect line)))
GET-FILE
* (get-file dd)
("(+ 3 3)" "" "(let ((n 3)) (+ n 1))" "" "(let ((n 4))" "  (+ n 1))" ""
 "(defun d (f)" "  (let ((n 3)" "   (f 4)" "    (g 3))" "    (if (= n 0)"
 "  (+ n f g)" "      (* n f g))))")

它将每一行转换为字符串,但不是我想要的格式。

我也试过这样做:

(uiop:read-file-lines "file.txt")

但我得到了与前面示例相同的输出。

我希望能够使用每个 line/expression 作为 parse-exp 的输入——像这样:

(parse-exp '(+ 3 3))(parse-exp '(let ((n 3)) (+ n 1))) 等等。

我该怎么做?

谢谢。

您搜索的是 read,而不是 read-line,它显示为 expression-wise(并且由 lisp 解释器使用)。

(with-open-file (stream "test1.lisp")
  (loop for expr = (read stream nil 'eof)
    until (eq expr 'eof)
    collect expr))
;; ((+ 3 3) (LET ((N 3)) (+ N 1)) (LET ((N 4)) (+ N 1))
;; (DEFUN D (F) (LET ((N 3) (F 4) (G 3)) (IF (= N 0) (+ N F G) (* N F G)))))
;; every element is an expression.

如果您希望表达式是字符串而不是符号列表,请使用 (format nil "~a" ...):

(with-open-file (stream "test1.lisp")
  (loop for expr = (read stream nil 'eof)
    until (eq expr 'eof)
    collect (format nil "~a" expr)))
;; ("(+ 3 3)" "(LET ((N 3)) (+ N 1))" "(LET ((N 4)) (+ N 1))"
;;  "(DEFUN D (F) (LET ((N 3) (F 4) (G 3)) (IF (= N 0) (+ N F G) (* N F G))))")

Common Lisp 有一堆函数来处理这个问题:

  • read 从流中读取 s-expression。
  • read-from-string 从字符串
  • 中读取 s-expression
  • printprin1pprint 打印一个 s-expression。后者打印得很漂亮。
  • eval 计算 s-expression.
  • with-open-file 是一个打开和关闭文件作为流的宏
  • with-input-from-string 是一个创建流的宏,因此可以从该字符串中读取