reader: repair readtable re-mapping of #
comment forms
Thanks to @LiberalArtist for the bug report and examples.
This commit is contained in:
parent
bad64945e7
commit
ef4eb585d7
|
@ -115,7 +115,9 @@ The possible combinations for @racket[key], @racket[mode], and
|
||||||
@item{@racket[(code:line _char _like-char _readtable)] --- causes
|
@item{@racket[(code:line _char _like-char _readtable)] --- causes
|
||||||
@racket[_char] to be parsed in the same way that @racket[_like-char]
|
@racket[_char] to be parsed in the same way that @racket[_like-char]
|
||||||
is parsed in @racket[_readtable], where @racket[_readtable] can be
|
is parsed in @racket[_readtable], where @racket[_readtable] can be
|
||||||
@racket[#f] to indicate the default readtable. Mapping a character to
|
@racket[#f] to indicate the default readtable. (The mapping of
|
||||||
|
@racket[_char] does not apply after @litchar{#}, which is configured
|
||||||
|
separately via @racket['dispatch-macro].) Mapping a character to
|
||||||
the same actions as @litchar{|} in the default reader means that the
|
the same actions as @litchar{|} in the default reader means that the
|
||||||
character starts quoting for symbols, and the same character
|
character starts quoting for symbols, and the same character
|
||||||
terminates the quote; in contrast, mapping a character to the same
|
terminates the quote; in contrast, mapping a character to the same
|
||||||
|
|
|
@ -388,6 +388,57 @@
|
||||||
(try #\[ #\] #\( #\))
|
(try #\[ #\] #\( #\))
|
||||||
(try #\{ #\} #\[ #\]))
|
(try #\{ #\} #\[ #\]))
|
||||||
|
|
||||||
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Check that comment forms can be redirecteed by a readtable
|
||||||
|
|
||||||
|
(let ([readstr (lambda (s)
|
||||||
|
(read (open-input-string s)))])
|
||||||
|
(define readtable
|
||||||
|
(make-readtable #f
|
||||||
|
#\$ #\; #f
|
||||||
|
#\* #\| #f
|
||||||
|
#\? #\! #f))
|
||||||
|
|
||||||
|
(parameterize ([current-readtable readtable])
|
||||||
|
(test 'x readstr "$this\nx")
|
||||||
|
;; char mapping doesn't affect `#...`
|
||||||
|
(err/rt-test (readstr "#$datum x") exn:fail:read?)
|
||||||
|
(err/rt-test (readstr "#* ??? *# x") exn:fail:read?)
|
||||||
|
(err/rt-test (readstr "#?/other\nx") exn:fail:read?)))
|
||||||
|
|
||||||
|
(let ([readstr (lambda (s)
|
||||||
|
(read (open-input-string s)))])
|
||||||
|
(define saw #f)
|
||||||
|
|
||||||
|
(define ((comment->x msg) ch in src line col pos)
|
||||||
|
(test #f equal? saw msg) ; only once
|
||||||
|
(set! saw msg)
|
||||||
|
'x)
|
||||||
|
|
||||||
|
(define readtable0
|
||||||
|
(make-readtable #f
|
||||||
|
#\; 'terminating-macro (comment->x "line")
|
||||||
|
#\; 'dispatch-macro (comment->x "s-exp")
|
||||||
|
#\| 'dispatch-macro (comment->x "block")
|
||||||
|
#\! 'dispatch-macro (comment->x "unix")))
|
||||||
|
|
||||||
|
(define readtable
|
||||||
|
(make-readtable readtable0
|
||||||
|
#\$ #\; readtable0
|
||||||
|
#\* #\| readtable0
|
||||||
|
#\? #\! readtable0))
|
||||||
|
|
||||||
|
(parameterize ([current-readtable readtable])
|
||||||
|
(for ([str '(";this" "$this" "#;datum" "#$datum" "#|a block|#" "#* x *#" "#!/usr/bin/env racket" "#?/other")]
|
||||||
|
[kind '("line" "line" "s-exp" error "block" error "unix" error)])
|
||||||
|
(cond
|
||||||
|
[(eq? kind 'error)
|
||||||
|
(err/rt-test (readstr str) exn:fail:read?)]
|
||||||
|
[else
|
||||||
|
(set! saw #f)
|
||||||
|
(test 'x readstr str)
|
||||||
|
(test kind values saw)]))))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(report-errs)
|
(report-errs)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
readtable-mapping
|
readtable-mapping
|
||||||
current-readtable
|
current-readtable
|
||||||
readtable-effective-char
|
readtable-effective-char
|
||||||
|
readtable-effective-char/#
|
||||||
effective-char
|
effective-char
|
||||||
readtable-handler
|
readtable-handler
|
||||||
readtable-dispatch-handler
|
readtable-dispatch-handler
|
||||||
|
@ -136,6 +137,13 @@
|
||||||
[(char? target) target]
|
[(char? target) target]
|
||||||
[else #\x])) ; return some non-special character
|
[else #\x])) ; return some non-special character
|
||||||
|
|
||||||
|
;; Similar to `readtable-effective-char`, but for a character after
|
||||||
|
;; `#` to detect whether it has the usual meaning
|
||||||
|
(define (readtable-effective-char/# rt c)
|
||||||
|
(cond
|
||||||
|
[(and rt (hash-ref (readtable-dispatch-ht rt) c #f)) #f]
|
||||||
|
[else c]))
|
||||||
|
|
||||||
(define (effective-char c config)
|
(define (effective-char c config)
|
||||||
(readtable-effective-char (read-config-readtable config) c))
|
(readtable-effective-char (read-config-readtable config) c))
|
||||||
|
|
||||||
|
|
|
@ -43,13 +43,13 @@
|
||||||
(result-special-comment)
|
(result-special-comment)
|
||||||
(skip-loop #f))]
|
(skip-loop #f))]
|
||||||
[(and (char=? #\# ec)
|
[(and (char=? #\# ec)
|
||||||
(eqv? #\| (peek-char/special in config 0 source)))
|
(eqv? #\| (readtable-effective-char/# rt (peek-char/special in config 0 source))))
|
||||||
(skip-pipe-comment! c in config)
|
(skip-pipe-comment! c in config)
|
||||||
(if (read-config-keep-comment? config)
|
(if (read-config-keep-comment? config)
|
||||||
(result-special-comment)
|
(result-special-comment)
|
||||||
(skip-loop #f))]
|
(skip-loop #f))]
|
||||||
[(and (char=? #\# ec)
|
[(and (char=? #\# ec)
|
||||||
(eqv? #\! (peek-char/special in config 0 source))
|
(eqv? #\! (readtable-effective-char/# rt (peek-char/special in config 0 source)))
|
||||||
(let ([c3 (peek-char/special in config 1 source)])
|
(let ([c3 (peek-char/special in config 1 source)])
|
||||||
(or (eqv? #\space c3)
|
(or (eqv? #\space c3)
|
||||||
(eqv? #\/ c3))))
|
(eqv? #\/ c3))))
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
(result-special-comment)
|
(result-special-comment)
|
||||||
(skip-loop #f))]
|
(skip-loop #f))]
|
||||||
[(and (char=? #\# ec)
|
[(and (char=? #\# ec)
|
||||||
(eqv? #\; (peek-char/special in config 0 source)))
|
(eqv? #\; (readtable-effective-char/# rt (peek-char/special in config 0 source))))
|
||||||
(consume-char in #\;)
|
(consume-char in #\;)
|
||||||
(define v (read-one #f in config))
|
(define v (read-one #f in config))
|
||||||
(when (eof-object? v)
|
(when (eof-object? v)
|
||||||
|
|
|
@ -52860,6 +52860,10 @@ static const char *startup_source =
|
||||||
"(let-values(((target_0)(hash-ref(readtable-char-ht rt_0) c_0 #f)))"
|
"(let-values(((target_0)(hash-ref(readtable-char-ht rt_0) c_0 #f)))"
|
||||||
"(if(not target_0)(let-values() c_0)(if(char? target_0)(let-values() target_0)(let-values() '#\\x)))))))"
|
"(if(not target_0)(let-values() c_0)(if(char? target_0)(let-values() target_0)(let-values() '#\\x)))))))"
|
||||||
"(define-values"
|
"(define-values"
|
||||||
|
"(readtable-effective-char/#)"
|
||||||
|
"(lambda(rt_0 c_0)"
|
||||||
|
"(begin(if(if rt_0(hash-ref(readtable-dispatch-ht rt_0) c_0 #f) #f)(let-values() #f)(let-values() c_0)))))"
|
||||||
|
"(define-values"
|
||||||
"(effective-char)"
|
"(effective-char)"
|
||||||
"(lambda(c_0 config_0)"
|
"(lambda(c_0 config_0)"
|
||||||
"(begin"
|
"(begin"
|
||||||
|
@ -53152,6 +53156,8 @@ static const char *startup_source =
|
||||||
"(if(if(char=? '#\\# ec_0)"
|
"(if(if(char=? '#\\# ec_0)"
|
||||||
"(eqv?"
|
"(eqv?"
|
||||||
" '#\\|"
|
" '#\\|"
|
||||||
|
"(readtable-effective-char/#"
|
||||||
|
" rt_0"
|
||||||
"(let-values(((in_1) in_0)((skip-count_0) 0)((source_1) source_0))"
|
"(let-values(((in_1) in_0)((skip-count_0) 0)((source_1) source_0))"
|
||||||
"(let-values(((c_1)"
|
"(let-values(((c_1)"
|
||||||
"(peek-char-or-special"
|
"(peek-char-or-special"
|
||||||
|
@ -53159,7 +53165,7 @@ static const char *startup_source =
|
||||||
" skip-count_0"
|
" skip-count_0"
|
||||||
" 'special"
|
" 'special"
|
||||||
" source_1)))"
|
" source_1)))"
|
||||||
"(if(eq? c_1 'special)(special1.1 'special) c_1))))"
|
"(if(eq? c_1 'special)(special1.1 'special) c_1)))))"
|
||||||
" #f)"
|
" #f)"
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
"(begin"
|
"(begin"
|
||||||
|
@ -53170,6 +53176,8 @@ static const char *startup_source =
|
||||||
"(if(if(char=? '#\\# ec_0)"
|
"(if(if(char=? '#\\# ec_0)"
|
||||||
"(if(eqv?"
|
"(if(eqv?"
|
||||||
" '#\\!"
|
" '#\\!"
|
||||||
|
"(readtable-effective-char/#"
|
||||||
|
" rt_0"
|
||||||
"(let-values(((in_1) in_0)"
|
"(let-values(((in_1) in_0)"
|
||||||
"((skip-count_0) 0)"
|
"((skip-count_0) 0)"
|
||||||
"((source_1) source_0))"
|
"((source_1) source_0))"
|
||||||
|
@ -53179,7 +53187,7 @@ static const char *startup_source =
|
||||||
" skip-count_0"
|
" skip-count_0"
|
||||||
" 'special"
|
" 'special"
|
||||||
" source_1)))"
|
" source_1)))"
|
||||||
"(if(eq? c_1 'special)(special1.1 'special) c_1))))"
|
"(if(eq? c_1 'special)(special1.1 'special) c_1)))))"
|
||||||
"(let-values(((c3_0)"
|
"(let-values(((c3_0)"
|
||||||
"(let-values(((in_1) in_0)"
|
"(let-values(((in_1) in_0)"
|
||||||
"((skip-count_0) 1)"
|
"((skip-count_0) 1)"
|
||||||
|
@ -53206,6 +53214,8 @@ static const char *startup_source =
|
||||||
"(if(if(char=? '#\\# ec_0)"
|
"(if(if(char=? '#\\# ec_0)"
|
||||||
"(eqv?"
|
"(eqv?"
|
||||||
" '#\\;"
|
" '#\\;"
|
||||||
|
"(readtable-effective-char/#"
|
||||||
|
" rt_0"
|
||||||
"(let-values(((in_1) in_0)"
|
"(let-values(((in_1) in_0)"
|
||||||
"((skip-count_0) 0)"
|
"((skip-count_0) 0)"
|
||||||
"((source_1) source_0))"
|
"((source_1) source_0))"
|
||||||
|
@ -53215,7 +53225,7 @@ static const char *startup_source =
|
||||||
" skip-count_0"
|
" skip-count_0"
|
||||||
" 'special"
|
" 'special"
|
||||||
" source_1)))"
|
" source_1)))"
|
||||||
"(if(eq? c_1 'special)(special1.1 'special) c_1))))"
|
"(if(eq? c_1 'special)(special1.1 'special) c_1)))))"
|
||||||
" #f)"
|
" #f)"
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
"(let-values((()(begin(consume-char in_0 '#\\;)(values))))"
|
"(let-values((()(begin(consume-char in_0 '#\\;)(values))))"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user