diff --git a/lib/srfi/38.scm b/lib/srfi/38.scm index eaa6dce1..bbbb18ad 100644 --- a/lib/srfi/38.scm +++ b/lib/srfi/38.scm @@ -144,6 +144,20 @@ (error "unterminated #| comment") (skip-comment in depth))))) +;; returns #f if a trailing # was consumed +(define (skip-whitespace-and-sexp-comments in read) + (skip-whitespace in) + (cond + ((eqv? #\# (peek-char in)) + (read-char in) + (cond ((eqv? #\; (peek-char in)) + (read-char in) + (read in) + (skip-whitespace-and-sexp-comments in read)) + (else #f))) + (else + #t))) + (define delimiters '(#\; #\" #\| #\( #\) #\{ #\} #\space #\tab #\newline #\return)) @@ -338,10 +352,16 @@ (cond ((memv (peek-char in) delimiters) (let ((tail (read-one))) - (skip-whitespace in) - (if (eqv? #\) (peek-char in)) - (begin (read-char in) (append (reverse res) tail)) - (error "expected end of list after dot")))) + (cond + ((and (skip-whitespace-and-sexp-comments + in (lambda (in) (read-one))) + (eqv? #\) (peek-char in))) + (read-char in) + (append (reverse res) tail)) + ((eof-object? (peek-char in)) + (error "unterminated dotted list")) + (else + (error "expected end of list after dot"))))) ((char-numeric? (peek-char in)) (lp (cons (read-float-tail in) res))) (else (lp (cons (string->symbol (read-name #\. in)) res))))) diff --git a/tests/r7rs-tests.scm b/tests/r7rs-tests.scm index 0d8497ed..88a6289e 100644 --- a/tests/r7rs-tests.scm +++ b/tests/r7rs-tests.scm @@ -1940,6 +1940,24 @@ (test 'def (read (open-input-string "#| abc |# def"))) (test 'ghi (read (open-input-string "#| abc #| def |# |# ghi"))) (test 'ghi (read (open-input-string "#; ; abc\n def ghi"))) +(test '(abs -16) (read (open-input-string "(#;sqrt abs -16)"))) +(test '(a d) (read (open-input-string "(a #; #;b c d)"))) +(test '(a e) (read (open-input-string "(a #;(b #;c d) e)"))) +(test '(a . c) (read (open-input-string "(a . #;b c)"))) +(test '(a . b) (read (open-input-string "(a . b #;c)"))) + +(define (test-read-error str) + (test-assert + (guard (exn (else #t)) + (read (open-input-string str)) + #f))) + +(test-read-error "(#;a . b)") +(test-read-error "(a . #;b)") +(test-read-error "(a #;. b)") +(test-read-error "(#;x #;y . z)") +(test-read-error "(#; #;x #;y . z)") +(test-read-error "(#; #;x . z)") (test #\a (read (open-input-string "#\\a"))) (test #\space (read (open-input-string "#\\space")))