Как в Common Lisp (SBCL) вы анализируете файл?

У меня есть файл: 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))) и так далее.

Как мне это сделать?

Спасибо.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

То, что вы ищете, это 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 — это макрос, который создает поток, чтобы можно было читать из этой строки

Другие вопросы по теме