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

Time:05-14

I have a file: test.lisp with this content:

(  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))))

I am trying to read the file like this:

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

which gives me the apparent correct output:

(  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))))

I want to call my function parse-exp on each line of the file corresponding to each expression above.

From a different answer here on Stackoverflow I tried to do this:

* (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))))")

which converts each line to a string and its not in the format that I want.

I also tried doing this:

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

but I get the same output as the previous example.

I want to be able to use each line/expression as input to parse-exp - like this:

(parse-exp '( 3 3)) or (parse-exp '(let ((n 3)) ( n 1))) and so on.

How do I do this?

Thanks.

CodePudding user response:

What you search for is read instead of read-line which reads expression-wise (and is used by lisp interpreters).

(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.

If you want the expressions to be strings instead of list of symbols, use (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))))")
  • Related