~ chicken-core (chicken-5) 55ad083b47dc281ed31ce218433d847cc6eeba59
commit 55ad083b47dc281ed31ce218433d847cc6eeba59
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Wed Aug 18 05:43:31 2010 -0400
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Wed Aug 18 05:43:31 2010 -0400
generalized symbol escape syntax
diff --git a/library.scm b/library.scm
index ae11f74b..0025ba58 100644
--- a/library.scm
+++ b/library.scm
@@ -2382,24 +2382,37 @@ EOF
(r-token) )
(define (r-symbol)
- (let ((s (resolve-symbol
- (if (char=? (##sys#peek-char-0 port) #\|)
- (r-xtoken)
- (r-token) ) ) ) )
+ (let ((s (resolve-symbol (r-xtoken))))
(info 'symbol-info s (##sys#port-line port)) ) )
(define (r-xtoken)
- (if (char=? #\| (read-unreserved-char-0 port))
- (let loop ((c (##sys#read-char-0 port)) (lst '()))
- (cond ((eof-object? c)
- (##sys#read-error port "unexpected end of `| ... |' symbol"))
- ((char=? c #\\)
- (let ((c (##sys#read-char-0 port)))
- (loop (##sys#read-char-0 port) (cons c lst)) ) )
- ((char=? c #\|)
- (##sys#reverse-list->string lst) )
- (else (loop (##sys#read-char-0 port) (cons c lst))) ) )
- (##sys#read-error port "missing \'|\'") ) )
+ (let loop ((esc #f) (lst '()))
+ (let ((c (##sys#peek-char-0 port)))
+ (cond ((eof-object? c)
+ (if esc
+ (##sys#read-error
+ port
+ "unexpected end of file while reading token delimited by `| ... |'")
+ (##sys#reverse-list->string lst)))
+ ((and (not esc)
+ (or (char-whitespace? c)
+ (memq c terminating-characters)))
+ (##sys#reverse-list->string lst))
+ (else
+ (let ((c ((if esc read-unreserved-char-0 ##sys#read-char-0) port)))
+ (case c
+ ((#\|) (loop (not esc) lst))
+ ((#\\)
+ (let ((c (##sys#read-char-0 port)))
+ (if (eof-object? c)
+ (##sys#read-error
+ port
+ "unexpected end of file while reading escaped character")
+ (loop esc (cons c lst)))))
+ (else
+ (loop
+ esc
+ (cons (if (or esc csp) c (char-downcase c)) lst))))))))))
(define (r-char)
;; Code contributed by Alex Shinn
@@ -2465,7 +2478,10 @@ EOF
(set! tok (##sys#substring tok 0 namespace-max-id-len)) )
(##sys#setbyte p 0 i)
(##sys#intern-symbol
- (string-append p (##sys#substring tok 0 i) (##sys#substring tok (fx+ i 1) toklen)) ) ]
+ (string-append
+ p
+ (##sys#substring tok 0 i)
+ (##sys#substring tok (fx+ i 1) toklen)) ) ]
[else (loop (fx+ i 1))] ) ) ) )
(define (resolve-symbol tok)
@@ -2594,10 +2610,12 @@ EOF
(let ((a (assq (string->symbol tok) read-marks)))
(if a
((##sys#slot a 1) port)
- (##sys#read-error port "invalid `#!' token" tok) ) ) ] ) ) ) ) ) )
+ (##sys#read-error
+ port
+ "invalid `#!' token" tok) ) ) ] ) ) ) ) ) )
(else (##sys#user-read-hook dchar port)) ) ) ) ) ) )
- ((#\( #;#\)) (r-list #\( #\)))
- ((#;#\( #\)) (##sys#read-char-0 port) (container c))
+ ((#\() (r-list #\( #\)))
+ ((#\)) (##sys#read-char-0 port) (container c))
((#\") (r-string #\"))
((#\.) (r-number #f))
((#\- #\+) (r-number #f))
@@ -2608,9 +2626,9 @@ EOF
(reserved-character c))
(else
(case c
- ((#\[ #;#\]) (r-list #\[ #\]))
- ((#\{ #;#\}) (r-list #\{ #\}))
- ((#;#\[ #\] #;#\{ #\}) (##sys#read-char-0 port) (container c))
+ ((#\[) (r-list #\[ #\]))
+ ((#\{) (r-list #\{ #\}))
+ ((#\] #\}) (##sys#read-char-0 port) (container c))
(else (r-symbol) ) ) ) ) ) ) ) ) )
(readrec) ) ) ) )
diff --git a/manual/Non-standard read syntax b/manual/Non-standard read syntax
index d8e57e88..85095ae4 100644
--- a/manual/Non-standard read syntax
+++ b/manual/Non-standard read syntax
@@ -4,6 +4,17 @@
== Non-standard read syntax
+=== Escapes in symbols
+
+{{| ... |}} may be used to escape a sequence of characters when reading a symbol.
+{{\X}} escapes a single character in a symbols name:
+
+ (symbol->string '|abc def|) => "abc def"
+ (symbol->string '|abc||def|) => "abcdef"
+ (symbol->string '|abc|xyz|def|) => "abcxyzdef"
+ (symbol->string '|abc\|def|) => "abc|def"
+ (symbol->string 'abc\ def) => "abc def"
+
=== Multiline Block Comment
#| ... |#
diff --git a/tests/library-tests.scm b/tests/library-tests.scm
index ee851334..b5494c52 100644
--- a/tests/library-tests.scm
+++ b/tests/library-tests.scm
@@ -79,3 +79,24 @@
(lambda ()
(write (string->symbol "3"))))
read)))
+
+
+;;; escaped symbol syntax
+
+(assert (string=? "abc" (symbol->string '|abc|)))
+(assert (string=? "abcdef" (symbol->string '|abc||def|)))
+(assert (string=? "abcxyzdef" (symbol->string '|abc|xyz|def|)))
+(assert (string=? "abc|def" (symbol->string '|abc\|def|)))
+(assert (string=? "abc|def" (symbol->string '|abc\|def|)))
+(assert (string=? "abc" (symbol->string '|abc:|))) ; keyword
+(assert (string=? "abc" (symbol->string '|abc|:))) ; keyword
+(assert (string=? ":abc" (symbol->string ':|abc|)))
+(assert (string=? ":abc" (symbol->string '|:abc|)))
+(assert (string=? "abc" (symbol->string 'abc)))
+(assert (string=? "a c" (symbol->string 'a\ c)))
+(assert (string=? "aBc" (symbol->string 'aBc)))
+
+(parameterize ((case-sensitive #f))
+ (assert (string=? "abc" (symbol->string (with-input-from-string "aBc" read))))
+ (assert (string=? "aBc" (symbol->string (with-input-from-string "|aBc|" read))))
+ (assert (string=? "aBc" (symbol->string (with-input-from-string "a\\Bc" read)))))
Trap