read: character constants
This commit is contained in:
parent
3c0508211f
commit
dfa320abb7
57
read.scm
57
read.scm
|
@ -593,6 +593,13 @@
|
||||||
(port 'restore-mutable! mutable))
|
(port 'restore-mutable! mutable))
|
||||||
(readtable:next toplevel #f port)))
|
(readtable:next toplevel #f port)))
|
||||||
|
|
||||||
|
;;; ;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;; Handling hash messages
|
||||||
|
;;;
|
||||||
|
;;; A "hash message" is any identifier that immediately follows a "#".
|
||||||
|
;;; This can be a constant, a part of a constant (like for numbers), or
|
||||||
|
;;; a directive (like #!FOLD-CASE).
|
||||||
|
|
||||||
;;; String map from constants to procedures with formal arguments
|
;;; String map from constants to procedures with formal arguments
|
||||||
;;; (TOPLEVEL PORT)
|
;;; (TOPLEVEL PORT)
|
||||||
;;; with TOPLEVEL being the current toplevel table and PORT being the
|
;;; with TOPLEVEL being the current toplevel table and PORT being the
|
||||||
|
@ -600,7 +607,7 @@
|
||||||
;;;
|
;;;
|
||||||
;;; Each one must return something. Directives that return nothing must
|
;;; Each one must return something. Directives that return nothing must
|
||||||
;;; call the toplevel again.
|
;;; call the toplevel again.
|
||||||
(define read:hash-constants
|
(define read:hash-messages
|
||||||
(smap:insert-many
|
(smap:insert-many
|
||||||
'()
|
'()
|
||||||
(cons "true" (lambda unused #t))
|
(cons "true" (lambda unused #t))
|
||||||
|
@ -619,21 +626,60 @@
|
||||||
(port 'fold-case! #f)
|
(port 'fold-case! #f)
|
||||||
(readtable:act toplevel (port 'read) #f port)))))
|
(readtable:act toplevel (port 'read) #f port)))))
|
||||||
|
|
||||||
(define read:read-hash-constants
|
(define read:read-hash-messages
|
||||||
(lambda (_ char acc port)
|
(lambda (_ char acc port)
|
||||||
(let ((ident (readtable:read-ident #f char #f port)))
|
(let ((ident (readtable:read-ident #f char #f port)))
|
||||||
(let ((container (smap:search read:hash-constants
|
(let ((container (smap:search read:hash-messages
|
||||||
(ident 'value))))
|
(ident 'value))))
|
||||||
|
;; TODO: check if the hash message starts a number.
|
||||||
(if (null? container)
|
(if (null? container)
|
||||||
(error 'read-hash-constants 'unknown-constant
|
(error 'read-hash-messages 'unknown-constant
|
||||||
(ident 'value))
|
(ident 'value))
|
||||||
((map:val container) acc port))))))
|
((map:val container) acc port))))))
|
||||||
|
|
||||||
|
;;; ;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;; Characters
|
||||||
|
;;;
|
||||||
|
;;; For completeness, this adds a few more newline characters that are C
|
||||||
|
;;; escape sequences but are not standard Scheme.
|
||||||
|
|
||||||
|
(define read:named-characters
|
||||||
|
(smap:insert-many
|
||||||
|
'()
|
||||||
|
(cons "null" (integer->char 0))
|
||||||
|
(cons "alarm" (integer->char #x7))
|
||||||
|
(cons "backspace" (integer->char #x8))
|
||||||
|
(cons "tab" (integer->char #x9))
|
||||||
|
(cons "newline" (integer->char #xA))
|
||||||
|
(cons "vertical-tab" (integer->char #xB))
|
||||||
|
(cons "form-feed" (integer->char #xC))
|
||||||
|
(cons "return" (integer->char #xD))
|
||||||
|
(cons "escape" (integer->char #x1B))
|
||||||
|
(cons "space" (integer->char #x20))
|
||||||
|
(cons "delete" (integer->char #x7F))))
|
||||||
|
|
||||||
|
(define readtable:character
|
||||||
|
(lambda (_ char __ port)
|
||||||
|
(let ((char (port 'read)))
|
||||||
|
(let ((ident (readtable:read-ident #f char #f port)))
|
||||||
|
(let ((container (smap:search read:named-characters
|
||||||
|
(ident 'value))))
|
||||||
|
(display (ident 'value))
|
||||||
|
(newline)
|
||||||
|
(cond
|
||||||
|
((and (null? container)
|
||||||
|
(= (string-length (ident 'value)) 1))
|
||||||
|
(string-ref (ident 'value) 0))
|
||||||
|
((null? container) (error 'character 'unknown-character ident))
|
||||||
|
(else (map:val container))))))))
|
||||||
|
|
||||||
(define readtable:hash
|
(define readtable:hash
|
||||||
(readtable:process
|
(readtable:process
|
||||||
(readtable:empty/default read:read-hash-constants)
|
(readtable:empty/default read:read-hash-messages)
|
||||||
|
;; TODO: add whitespace to fail
|
||||||
(list readtable:update #\| (readtable:jump/next readtable:block-comment))
|
(list readtable:update #\| (readtable:jump/next readtable:block-comment))
|
||||||
(list readtable:update #\; readtable:datum-comment)
|
(list readtable:update #\; readtable:datum-comment)
|
||||||
|
(list readtable:update #\\ readtable:character)
|
||||||
(list readtable:update-list readtable:digits ; Datum labels
|
(list readtable:update-list readtable:digits ; Datum labels
|
||||||
(lambda (_ char toplevel port)
|
(lambda (_ char toplevel port)
|
||||||
(readtable:act readtable:datum-label-next
|
(readtable:act readtable:datum-label-next
|
||||||
|
@ -747,3 +793,4 @@
|
||||||
(read-all "#!no-fold-case #!fold-case #!NO-FOLD-CASE #false")
|
(read-all "#!no-fold-case #!fold-case #!NO-FOLD-CASE #false")
|
||||||
(read-all "#!fold-case #TRUE")
|
(read-all "#!fold-case #TRUE")
|
||||||
(read-all "#u8(x y z w)")
|
(read-all "#u8(x y z w)")
|
||||||
|
(read-all "#\\newline")
|
||||||
|
|
Loading…
Reference in New Issue