在 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
print
、prin1
和 pprint
打印一个 s-expression。后者打印得很漂亮。
eval
计算 s-expression.
with-open-file
是一个打开和关闭文件作为流的宏
with-input-from-string
是一个创建流的宏,因此可以从该字符串中读取
我有一个文件: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
print
、prin1
和pprint
打印一个 s-expression。后者打印得很漂亮。eval
计算 s-expression.with-open-file
是一个打开和关闭文件作为流的宏with-input-from-string
是一个创建流的宏,因此可以从该字符串中读取