readtable: case folding
This commit is contained in:
parent
3f56b03f1a
commit
6945841d1c
11
README.rst
11
README.rst
|
@ -19,12 +19,12 @@ designed to be used by a severely limited Scheme interpreter, which
|
||||||
* has fixnums only
|
* has fixnums only
|
||||||
* only uses immutable strings
|
* only uses immutable strings
|
||||||
* does not use "load" recursively
|
* does not use "load" recursively
|
||||||
* uses R3RS essental procedures only (with some exceptions)
|
* uses R3RS essential procedures only (with some exceptions)
|
||||||
|
|
||||||
The goal is to have the compiler run under the MiniScheme in ``miniscm``
|
The goal is to have the compiler run under the MiniScheme in ``miniscm``
|
||||||
in DOS, and then run in GLLV to compile itself.
|
in DOS, and then run in GLLV to compile itself.
|
||||||
|
|
||||||
A proper implementation must have
|
A proper implementation must have, in addition to R3RS,
|
||||||
|
|
||||||
* ``open-input-port``, ``read-char``
|
* ``open-input-port``, ``read-char``
|
||||||
* ``open-output-port``, ``write-char``
|
* ``open-output-port``, ``write-char``
|
||||||
|
@ -32,7 +32,6 @@ A proper implementation must have
|
||||||
* ``and``, ``or``
|
* ``and``, ``or``
|
||||||
* ``error``
|
* ``error``
|
||||||
|
|
||||||
If your system supports any macro system at all, ``cond-expand``,
|
Hopefully your implementation has input and output ports (there's no other
|
||||||
``and``, and ``or`` can be implemented. ``error`` can be implemented
|
way to write a compiler). Everything else can be expressed in terms of
|
||||||
as in SRFI-23 : https://srfi.schemers.org/srfi-23/srfi-23.html .
|
macros or R3RS essential procedures.
|
||||||
|
|
||||||
|
|
88
read.scm
88
read.scm
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
;;; ;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; ;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;; Port reader wrapper
|
;;; Port reader wrapper
|
||||||
|
|
||||||
;;; ;;;;;;;;;;;;;;;;;;;;;;;;
|
;;; ;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(define port->read-function
|
(define port->read-function
|
||||||
|
@ -39,38 +40,50 @@
|
||||||
;;; (READ): Read the next character in the stream. Returns #F on EOF.
|
;;; (READ): Read the next character in the stream. Returns #F on EOF.
|
||||||
;;; (PUSH CHAR): Push CHAR such that it will be the next character read
|
;;; (PUSH CHAR): Push CHAR such that it will be the next character read
|
||||||
;;; when (READ) is called.
|
;;; when (READ) is called.
|
||||||
|
;;; (FOLD-CASE?): Returns a boolean if case folding is enabled.
|
||||||
|
;;; (FOLD-CASE! BOOL): Sets the case folding to BOOL.
|
||||||
(define port->read
|
(define port->read
|
||||||
(lambda (read-function filename)
|
(lambda (read-function filename)
|
||||||
(let ((line-number 1)
|
(let ((line-number 1)
|
||||||
(offset 0)
|
(offset 0)
|
||||||
(pushback-buffer '()))
|
(pushback-buffer '())
|
||||||
(let ((update-position
|
(fold-case? #f))
|
||||||
(lambda (ch)
|
(letrec ((update-position!
|
||||||
(cond
|
(lambda (ch)
|
||||||
((or (eof-object? ch) (not ch)) (set! ch #f))
|
(cond
|
||||||
((eqv? ch #\newline)
|
((eqv? ch #\newline)
|
||||||
(set! line-number (+ 1 line-number)) (set! offset 0))
|
(set! line-number (+ 1 line-number)) (set! offset 0))
|
||||||
(offset (set! offset (+ 1 offset))))
|
(offset (set! offset (+ 1 offset))))))
|
||||||
ch)))
|
(process
|
||||||
(lambda (op . args)
|
(lambda (ch)
|
||||||
(cond
|
(update-position! ch)
|
||||||
((eq? op 'pos) (list filename line-number offset))
|
(cond
|
||||||
((eq? op 'read)
|
((or (eof-object? ch) (not ch)) ch)
|
||||||
(update-position
|
(fold-case? (char-downcase ch))
|
||||||
(if (null? pushback-buffer)
|
(else ch))))
|
||||||
(read-function)
|
(port
|
||||||
(let ((ch (car pushback-buffer)))
|
(lambda (op . args)
|
||||||
(set! pushback-buffer (cdr pushback-buffer))
|
(cond
|
||||||
ch))))
|
((eq? op 'pos) (list filename line-number offset))
|
||||||
((eq? op 'push)
|
((eq? op 'read)
|
||||||
(let ((ch (car args)))
|
(process
|
||||||
(if (eqv? ch #\newline)
|
(if (null? pushback-buffer)
|
||||||
(begin
|
(read-function)
|
||||||
(set! line-number (- line-number 1))
|
(let ((ch (car pushback-buffer)))
|
||||||
(set! offset #f))
|
(set! pushback-buffer (cdr pushback-buffer))
|
||||||
(set! offset (- offset 1)))
|
ch))))
|
||||||
(set! pushback-buffer (cons ch pushback-buffer))))
|
((eq? op 'push)
|
||||||
(else (error "read->port: invalid" (cons op args)))))))))
|
(let ((ch (car args)))
|
||||||
|
(if (eqv? ch #\newline)
|
||||||
|
(begin
|
||||||
|
(set! line-number (- line-number 1))
|
||||||
|
(set! offset #f))
|
||||||
|
(set! offset (- offset 1)))
|
||||||
|
(set! pushback-buffer (cons ch pushback-buffer))))
|
||||||
|
((eq? op 'fold-case?) fold-case?)
|
||||||
|
((eq? op 'fold-case!) (set! fold-case? (car args)))
|
||||||
|
(else (error "read->port: invalid" (cons op args)))))))
|
||||||
|
port))))
|
||||||
|
|
||||||
;;; ;;;;;;;;;;;;;;
|
;;; ;;;;;;;;;;;;;;
|
||||||
;;; Character maps
|
;;; Character maps
|
||||||
|
@ -315,10 +328,19 @@
|
||||||
(define readtable:top
|
(define readtable:top
|
||||||
(readtable:update-many-sequence
|
(readtable:update-many-sequence
|
||||||
readtable:empty
|
readtable:empty
|
||||||
|
(cons "#!fold-case"
|
||||||
|
(readtable:exec:new
|
||||||
|
(lambda (table char acc port)
|
||||||
|
(port 'fold-case! #t)
|
||||||
|
'())))
|
||||||
|
(cons "#!no-fold-case"
|
||||||
|
(readtable:exec:new
|
||||||
|
(lambda (table char acc port)
|
||||||
|
(port 'fold-case! #f)
|
||||||
|
'())))
|
||||||
(cons "#t" (readtable:return-value #t))
|
(cons "#t" (readtable:return-value #t))
|
||||||
(cons "#f" (readtable:return-value #f))
|
(cons "#f" (readtable:return-value #f))
|
||||||
(cons "#true" (readtable:return-value #t))
|
(cons "#true" (readtable:return-value #t))))
|
||||||
(cons "#trouble" (readtable:return-value 15))))
|
|
||||||
|
|
||||||
;;; ;;;;;;;;;;;
|
;;; ;;;;;;;;;;;
|
||||||
;;; Test reader
|
;;; Test reader
|
||||||
|
@ -334,8 +356,12 @@
|
||||||
ch)))
|
ch)))
|
||||||
"test")))
|
"test")))
|
||||||
|
|
||||||
(let ((true-reader (%list->read (string->list "#t#false#true"))))
|
(let ((true-reader (%list->read (string->list "#!fold-case#TRUE#!no-fold-case#TRUE"))))
|
||||||
(display (list "first:" (readtable:top (true-reader 'read) #f true-reader)))
|
(display (list "first:" (readtable:top (true-reader 'read) #f true-reader)))
|
||||||
(newline)
|
(newline)
|
||||||
(display (list "second: " (readtable:top (true-reader 'read) #f true-reader)))
|
(display (list "second: " (readtable:top (true-reader 'read) #f true-reader)))
|
||||||
|
(newline)
|
||||||
|
(display (list "third: " (readtable:top (true-reader 'read) #f true-reader)))
|
||||||
|
(newline)
|
||||||
|
(display (list "fourth: " (readtable:top (true-reader 'read) #f true-reader)))
|
||||||
(newline))
|
(newline))
|
||||||
|
|
Loading…
Reference in New Issue