У меня есть файл: 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
в каждой строке файла, соответствующей каждому выражению выше.
Из другого ответа здесь, в Stackoverflow, я попытался сделать это:
* (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")
но я получаю тот же результат, что и в предыдущем примере.
Я хочу иметь возможность использовать каждую строку/выражение в качестве входных данных для parse-exp
- вот так:
(parse-exp '(+ 3 3))
или
(parse-exp '(let ((n 3)) (+ n 1)))
и так далее.
Как мне это сделать?
Спасибо.
То, что вы ищете, это read
вместо read-line
, которое читается как выражение (и используется интерпретаторами 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-выражение из потока.read-from-string
читает s-выражение из строкиprint
, prin1
и pprint
печатает s-выражение. Последний довольно печатает это.eval
оценивает s-выражение.with-open-file
— это макрос, который открывает и закрывает файл как потокwith-input-from-string
— это макрос, который создает поток, чтобы можно было читать из этой строки