read: factor out improper list reader
This commit is contained in:
parent
75f915d0e5
commit
003d6dde05
76
read.scm
76
read.scm
|
@ -196,6 +196,10 @@
|
||||||
(lambda (oldtable char acc port)
|
(lambda (oldtable char acc port)
|
||||||
(readtable:act newtable char acc port))))
|
(readtable:act newtable char acc port))))
|
||||||
|
|
||||||
|
;;; ;;;;;;;;;;;;;;;;;
|
||||||
|
;;; Identifier reader
|
||||||
|
;;; ;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;;; Push back CHAR and return ACC.
|
;;; Push back CHAR and return ACC.
|
||||||
(define readtable:return-acc-keep-char
|
(define readtable:return-acc-keep-char
|
||||||
(lambda (table char acc port)
|
(lambda (table char acc port)
|
||||||
|
@ -245,6 +249,10 @@
|
||||||
(port 'read) lst port)
|
(port 'read) lst port)
|
||||||
'to-list)))))
|
'to-list)))))
|
||||||
|
|
||||||
|
;;; ;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;; Comments and whitespace reader
|
||||||
|
;;; ;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;;; Add all chars in TO-SKIP to TABLE as skipped characters. Used for
|
;;; Add all chars in TO-SKIP to TABLE as skipped characters. Used for
|
||||||
;;; whitespace.
|
;;; whitespace.
|
||||||
(define readtable:add-all-as-skip
|
(define readtable:add-all-as-skip
|
||||||
|
@ -260,6 +268,14 @@
|
||||||
(readtable:empty/default readtable:skip)
|
(readtable:empty/default readtable:skip)
|
||||||
(list readtable:update #\newline (readtable:return #f))))
|
(list readtable:update #\newline (readtable:return #f))))
|
||||||
|
|
||||||
|
;;; ;;;;;;;;;;;
|
||||||
|
;;; List reader
|
||||||
|
;;;
|
||||||
|
;;; The reader updates the previous readtable to handle ). This means
|
||||||
|
;;; that this read table does not have to handle end-of-line, whitespace,
|
||||||
|
;;; etc.
|
||||||
|
;;; ;;;;;;;;;;;
|
||||||
|
|
||||||
;;; Read the end of an improper list.
|
;;; Read the end of an improper list.
|
||||||
(define readtable:read-improper-cdr
|
(define readtable:read-improper-cdr
|
||||||
(lambda (table acc port)
|
(lambda (table acc port)
|
||||||
|
@ -277,35 +293,14 @@
|
||||||
"improper list has 1 cdr"))
|
"improper list has 1 cdr"))
|
||||||
(list readtable:add-all-as-skip readtable:ASCII-whitespace)
|
(list readtable:add-all-as-skip readtable:ASCII-whitespace)
|
||||||
(list readtable:update %eol
|
(list readtable:update %eol
|
||||||
(lambda dummy acc)))))
|
(lambda dummy 'end-of-list)))))
|
||||||
(readtable:act table (port 'read) acc port)))))
|
(readtable:act table (port 'read) acc port)))))
|
||||||
|
|
||||||
;;; List reader.
|
;;; Generic reader loop for a list. It takes as input the table that has
|
||||||
;;;
|
;;; already been updated with end of list and improper list handlers.
|
||||||
;;; The reader updates the previous readtable to handle ). This means
|
(define readtable:read-list-loop
|
||||||
;;; that this read table does not have to handle end-of-line, whitespace,
|
(lambda (table port)
|
||||||
;;; etc.
|
(let ((acc (linked-list:new)))
|
||||||
(define readtable:read-list
|
|
||||||
(lambda (oldtable char acc port)
|
|
||||||
(let ((acc (linked-list:new))
|
|
||||||
(table (readtable:process
|
|
||||||
oldtable
|
|
||||||
(list readtable:update %eol
|
|
||||||
(readtable:return 'end-of-list))
|
|
||||||
(list readtable:update #\.
|
|
||||||
(lambda (table char acc port)
|
|
||||||
(let ((id (readtable:read-ident
|
|
||||||
table
|
|
||||||
char
|
|
||||||
#f
|
|
||||||
port)))
|
|
||||||
;; todo: list needs a car
|
|
||||||
(if (equal? id ".")
|
|
||||||
(begin
|
|
||||||
(readtable:read-improper-cdr
|
|
||||||
oldtable acc port)
|
|
||||||
'end-of-list)
|
|
||||||
id)))))))
|
|
||||||
(letrec ((loop
|
(letrec ((loop
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(let ((value (readtable:act table
|
(let ((value (readtable:act table
|
||||||
|
@ -318,6 +313,32 @@
|
||||||
(loop)))))))
|
(loop)))))))
|
||||||
(loop)))))
|
(loop)))))
|
||||||
|
|
||||||
|
;;; Readtable for a list, generic to proper and improper list
|
||||||
|
;;; readers.
|
||||||
|
(define readtable:table-for-list
|
||||||
|
(lambda (oldtable on-dot)
|
||||||
|
(readtable:process
|
||||||
|
oldtable
|
||||||
|
(list readtable:update %eol (readtable:return 'end-of-list))
|
||||||
|
(list readtable:update #\.
|
||||||
|
(lambda (table char acc port)
|
||||||
|
(let ((entire-identifier (readtable:read-ident
|
||||||
|
table
|
||||||
|
char
|
||||||
|
#f
|
||||||
|
port)))
|
||||||
|
(if (equal? entire-identifier ".")
|
||||||
|
(on-dot table acc port)
|
||||||
|
entire-identifier)))))))
|
||||||
|
|
||||||
|
;;; Read a proper or improper list.
|
||||||
|
(define readtable:read-list
|
||||||
|
(lambda (oldtable _ __ port)
|
||||||
|
(readtable:read-list-loop (readtable:table-for-list
|
||||||
|
oldtable
|
||||||
|
readtable:read-improper-cdr)
|
||||||
|
port)))
|
||||||
|
|
||||||
;;; Toplevel reader.
|
;;; Toplevel reader.
|
||||||
;;; This is defined as a function so that it dynamically loads each
|
;;; This is defined as a function so that it dynamically loads each
|
||||||
;;; sub-readtable.
|
;;; sub-readtable.
|
||||||
|
@ -366,3 +387,4 @@
|
||||||
(read-all "(a b c def (ghi j) k )")
|
(read-all "(a b c def (ghi j) k )")
|
||||||
(read-all "( a . b )")
|
(read-all "( a . b )")
|
||||||
(read-all "( a .b . c)")
|
(read-all "( a .b . c)")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue