mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-21 20:20:24 +02:00
Improve read error reporting
* module/ice-9/read.scm (read): Issue properly formatted read-errors, as users expect.
This commit is contained in:
parent
71e53d73fe
commit
6353b448cc
1 changed files with 50 additions and 43 deletions
|
@ -134,6 +134,8 @@
|
||||||
(define (peek) (peek-char port))
|
(define (peek) (peek-char port))
|
||||||
(define filename (port-filename port))
|
(define filename (port-filename port))
|
||||||
(define (get-pos) (cons (port-line port) (port-column port)))
|
(define (get-pos) (cons (port-line port) (port-column port)))
|
||||||
|
;; We are only ever interested in whether an object is a char or not.
|
||||||
|
(define (eof-object? x) (not (char? x)))
|
||||||
(define accumulator (open-output-string))
|
(define accumulator (open-output-string))
|
||||||
(define-syntax-rule (accumulate proc)
|
(define-syntax-rule (accumulate proc)
|
||||||
(begin
|
(begin
|
||||||
|
@ -159,8 +161,17 @@
|
||||||
(column . ,(1- column)))))
|
(column . ,(1- column)))))
|
||||||
datum)
|
datum)
|
||||||
|
|
||||||
(define (input-error msg . args)
|
(define (input-error msg args)
|
||||||
(apply error msg args))
|
(scm-error 'read-error #f
|
||||||
|
(format #f "~A:~S:~S: ~A"
|
||||||
|
(or filename "#<unknown port>")
|
||||||
|
(port-line port) (port-column port)
|
||||||
|
msg)
|
||||||
|
args #f))
|
||||||
|
|
||||||
|
(define-syntax-rule (error msg arg ...)
|
||||||
|
(let ((args (list arg ...)))
|
||||||
|
(input-error msg args)))
|
||||||
|
|
||||||
(define (read-semicolon-comment)
|
(define (read-semicolon-comment)
|
||||||
(let ((ch (next)))
|
(let ((ch (next)))
|
||||||
|
@ -237,13 +248,14 @@
|
||||||
(finish-curly-infix
|
(finish-curly-infix
|
||||||
(let lp ((ch (next-non-whitespace)))
|
(let lp ((ch (next-non-whitespace)))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "unexpected end of input while searching for " rdelim))
|
(error "unexpected end of input while searching for: ~A"
|
||||||
|
rdelim))
|
||||||
(cond
|
(cond
|
||||||
((eqv? ch rdelim) '())
|
((eqv? ch rdelim) '())
|
||||||
((or (eqv? ch #\))
|
((or (eqv? ch #\))
|
||||||
(and (eqv? ch #\]) (or (square-brackets?) (curly-infix?)))
|
(and (eqv? ch #\]) (or (square-brackets?) (curly-infix?)))
|
||||||
(and (eqv? ch #\}) (curly-infix?)))
|
(and (eqv? ch #\}) (curly-infix?)))
|
||||||
(input-error "mismatched close paren" ch))
|
(error "mismatched close paren: ~A" ch))
|
||||||
(else
|
(else
|
||||||
(let ((expr (read-expr ch)))
|
(let ((expr (read-expr ch)))
|
||||||
;; Note that it is possible for scm_read_expression to
|
;; Note that it is possible for scm_read_expression to
|
||||||
|
@ -253,7 +265,7 @@
|
||||||
(let* ((tail (read-expr (next-non-whitespace)))
|
(let* ((tail (read-expr (next-non-whitespace)))
|
||||||
(close (next-non-whitespace)))
|
(close (next-non-whitespace)))
|
||||||
(unless (eqv? close rdelim)
|
(unless (eqv? close rdelim)
|
||||||
(input-error "missing close paren" rdelim))
|
(error "missing close paren: ~A" close))
|
||||||
tail)
|
tail)
|
||||||
(cons expr (lp (next-non-whitespace))))))))))
|
(cons expr (lp (next-non-whitespace))))))))))
|
||||||
|
|
||||||
|
@ -278,9 +290,9 @@
|
||||||
((hex-digit ch) => (lambda (digit) (lp (+ (* 16 res) digit))))
|
((hex-digit ch) => (lambda (digit) (lp (+ (* 16 res) digit))))
|
||||||
((eqv? ch #\;) (integer->char res))
|
((eqv? ch #\;) (integer->char res))
|
||||||
(else
|
(else
|
||||||
(input-error "invalid character in escape sequence: ~S" ch)))))))
|
(error "invalid character in escape sequence: ~S" ch)))))))
|
||||||
(else
|
(else
|
||||||
(input-error "invalid character in escape sequence: ~S" ch)))))
|
(error "invalid character in escape sequence: ~S" ch)))))
|
||||||
|
|
||||||
(define (read-fixed-hex-escape len)
|
(define (read-fixed-hex-escape len)
|
||||||
(let lp ((len len) (res 0))
|
(let lp ((len len) (res 0))
|
||||||
|
@ -292,7 +304,7 @@
|
||||||
(lambda (digit)
|
(lambda (digit)
|
||||||
(lp (1- len) (+ (* res 16) digit))))
|
(lp (1- len) (+ (* res 16) digit))))
|
||||||
(else
|
(else
|
||||||
(input-error "invalid character in escape sequence: ~S" ch)))))))
|
(error "invalid character in escape sequence: ~S" ch)))))))
|
||||||
|
|
||||||
(define (read-string rdelim)
|
(define (read-string rdelim)
|
||||||
(accumulate
|
(accumulate
|
||||||
|
@ -302,11 +314,11 @@
|
||||||
(unless (eqv? ch rdelim)
|
(unless (eqv? ch rdelim)
|
||||||
(cond
|
(cond
|
||||||
((eof-object? ch)
|
((eof-object? ch)
|
||||||
(input-error "unexpected end of input while reading string"))
|
(error "unexpected end of input while reading string"))
|
||||||
((eqv? ch #\\)
|
((eqv? ch #\\)
|
||||||
(let ((ch (next)))
|
(let ((ch (next)))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "unexpected end of input while reading string"))
|
(error "unexpected end of input while reading string"))
|
||||||
(case ch
|
(case ch
|
||||||
((#\newline)
|
((#\newline)
|
||||||
(when (hungry-eol-escapes?)
|
(when (hungry-eol-escapes?)
|
||||||
|
@ -341,7 +353,7 @@
|
||||||
(put (read-fixed-hex-escape 8)))
|
(put (read-fixed-hex-escape 8)))
|
||||||
(else
|
(else
|
||||||
(unless (eqv? ch rdelim)
|
(unless (eqv? ch rdelim)
|
||||||
(input-error "invalid character in escape sequence: ~S" ch))
|
(error "invalid character in escape sequence: ~S" ch))
|
||||||
(put ch)))
|
(put ch)))
|
||||||
(lp)))
|
(lp)))
|
||||||
(else
|
(else
|
||||||
|
@ -352,7 +364,7 @@
|
||||||
(let ((ch (next)))
|
(let ((ch (next)))
|
||||||
(cond
|
(cond
|
||||||
((eof-object? ch)
|
((eof-object? ch)
|
||||||
(input-error "unexpected end of input after #\\"))
|
(error "unexpected end of input after #\\"))
|
||||||
((delimiter? ch)
|
((delimiter? ch)
|
||||||
ch)
|
ch)
|
||||||
(else
|
(else
|
||||||
|
@ -414,7 +426,7 @@
|
||||||
((named-char tok C0-control-charnames))
|
((named-char tok C0-control-charnames))
|
||||||
((named-char tok alt-charnames))
|
((named-char tok alt-charnames))
|
||||||
(else
|
(else
|
||||||
(input-error "unknown character name ~a" tok))))))))
|
(error "unknown character name ~a" tok))))))))
|
||||||
|
|
||||||
(define (read-vector)
|
(define (read-vector)
|
||||||
(list->vector (read-parenthesized #\))))
|
(list->vector (read-parenthesized #\))))
|
||||||
|
@ -448,7 +460,7 @@
|
||||||
(define (read-bytevector)
|
(define (read-bytevector)
|
||||||
(define (expect ch)
|
(define (expect ch)
|
||||||
(unless (eqv? (next) ch)
|
(unless (eqv? (next) ch)
|
||||||
(input-error "invalid bytevector prefix" ch)))
|
(error "invalid bytevector prefix" ch)))
|
||||||
(expect #\u)
|
(expect #\u)
|
||||||
(expect #\8)
|
(expect #\8)
|
||||||
(expect #\()
|
(expect #\()
|
||||||
|
@ -479,11 +491,10 @@
|
||||||
(define (read-keyword)
|
(define (read-keyword)
|
||||||
(let ((ch (next-non-whitespace)))
|
(let ((ch (next-non-whitespace)))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "end of input while reading keyword"))
|
(error "end of input while reading keyword"))
|
||||||
(let ((expr (read-expr ch)))
|
(let ((expr (read-expr ch)))
|
||||||
(unless (symbol? expr)
|
(unless (symbol? expr)
|
||||||
(input-error "keyword prefix #: not followed by a symbol: ~a"
|
(error "keyword prefix #: not followed by a symbol: ~a" expr))
|
||||||
expr))
|
|
||||||
(symbol->keyword expr))))
|
(symbol->keyword expr))))
|
||||||
|
|
||||||
(define (read-array ch)
|
(define (read-array ch)
|
||||||
|
@ -507,14 +518,14 @@
|
||||||
(define (read-rank ch)
|
(define (read-rank ch)
|
||||||
(let-values (((ch rank) (read-decimal-integer ch 1)))
|
(let-values (((ch rank) (read-decimal-integer ch 1)))
|
||||||
(when (< rank 0)
|
(when (< rank 0)
|
||||||
(input-error "array rank must be non-negative"))
|
(error "array rank must be non-negative"))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "unexpected end of input while reading array"))
|
(error "unexpected end of input while reading array"))
|
||||||
(values ch rank)))
|
(values ch rank)))
|
||||||
(define (read-tag ch)
|
(define (read-tag ch)
|
||||||
(let lp ((ch ch) (chars '()))
|
(let lp ((ch ch) (chars '()))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "unexpected end of input while reading array"))
|
(error "unexpected end of input while reading array"))
|
||||||
(if (memv ch '(#\( #\@ @\:))
|
(if (memv ch '(#\( #\@ @\:))
|
||||||
(values ch
|
(values ch
|
||||||
(if (null? chars)
|
(if (null? chars)
|
||||||
|
@ -529,9 +540,9 @@
|
||||||
(read-decimal-integer (next) 0)
|
(read-decimal-integer (next) 0)
|
||||||
(values ch #f))))
|
(values ch #f))))
|
||||||
(when (and len (< len 0))
|
(when (and len (< len 0))
|
||||||
(input-error "array length must be non-negative"))
|
(error "array length must be non-negative"))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "unexpected end of input while reading array"))
|
(error "unexpected end of input while reading array"))
|
||||||
(values ch
|
(values ch
|
||||||
(if len
|
(if len
|
||||||
(if (zero? lbnd)
|
(if (zero? lbnd)
|
||||||
|
@ -546,16 +557,16 @@
|
||||||
(values ch alt)))
|
(values ch alt)))
|
||||||
(define (read-elements ch rank)
|
(define (read-elements ch rank)
|
||||||
(unless (eqv? ch #\()
|
(unless (eqv? ch #\()
|
||||||
(input-error "missing '(' in vector or array literal"))
|
(error "missing '(' in vector or array literal"))
|
||||||
(let ((elts (read-parenthesized #\))))
|
(let ((elts (read-parenthesized #\))))
|
||||||
(if (zero? rank)
|
(if (zero? rank)
|
||||||
(begin
|
(begin
|
||||||
;; Handle special print syntax of rank zero arrays; see
|
;; Handle special print syntax of rank zero arrays; see
|
||||||
;; scm_i_print_array for a rationale.
|
;; scm_i_print_array for a rationale.
|
||||||
(when (null? elts)
|
(when (null? elts)
|
||||||
(input-error "too few elements in array literal, need 1"))
|
(error "too few elements in array literal, need 1"))
|
||||||
(unless (null? (cdr elts))
|
(unless (null? (cdr elts))
|
||||||
(input-error "too many elements in array literal, need 1"))
|
(error "too many elements in array literal, need 1"))
|
||||||
(car elts))
|
(car elts))
|
||||||
elts)))
|
elts)))
|
||||||
(let*-values (((ch rank) (read-rank ch))
|
(let*-values (((ch rank) (read-rank ch))
|
||||||
|
@ -563,20 +574,19 @@
|
||||||
((ch shape) (read-shape ch rank))
|
((ch shape) (read-shape ch rank))
|
||||||
((elts) (read-elements ch rank)))
|
((elts) (read-elements ch rank)))
|
||||||
(when (and (pair? shape) (not (eqv? (length shape) rank)))
|
(when (and (pair? shape) (not (eqv? (length shape) rank)))
|
||||||
(input-error
|
(error "the number of shape specifications must match the array rank"))
|
||||||
"the number of shape specifications must match the array rank"))
|
|
||||||
(list->typed-array tag shape elts)))
|
(list->typed-array tag shape elts)))
|
||||||
|
|
||||||
(define (read-number-and-radix ch)
|
(define (read-number-and-radix ch)
|
||||||
(let ((tok (string-append "#" (read-token ch))))
|
(let ((tok (string-append "#" (read-token ch))))
|
||||||
(or (string->number tok)
|
(or (string->number tok)
|
||||||
(input-error "unknown # object"))))
|
(error "unknown # object" tok))))
|
||||||
|
|
||||||
(define (read-extended-symbol)
|
(define (read-extended-symbol)
|
||||||
(define (next-not-eof)
|
(define (next-not-eof)
|
||||||
(let ((ch (next)))
|
(let ((ch (next)))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "end of input while reading symbol"))
|
(error "end of input while reading symbol"))
|
||||||
ch))
|
ch))
|
||||||
(string->symbol
|
(string->symbol
|
||||||
(list->string
|
(list->string
|
||||||
|
@ -610,14 +620,14 @@
|
||||||
;; Have already read "#\n" -- now read "il".
|
;; Have already read "#\n" -- now read "il".
|
||||||
(let ((id (read-mixed-case-symbol #\n)))
|
(let ((id (read-mixed-case-symbol #\n)))
|
||||||
(unless (eq? id 'nil)
|
(unless (eq? id 'nil)
|
||||||
(input-error "unexpected input while reading #nil: ~a" id))
|
(error "unexpected input while reading #nil: ~a" id))
|
||||||
#nil))
|
#nil))
|
||||||
|
|
||||||
(define (read-sharp)
|
(define (read-sharp)
|
||||||
(let* ((ch (next)))
|
(let* ((ch (next)))
|
||||||
(cond
|
(cond
|
||||||
((eof-object? ch)
|
((eof-object? ch)
|
||||||
(input-error "unexpected end of input after #"))
|
(error "unexpected end of input after #"))
|
||||||
((read-hash-procedure ch)
|
((read-hash-procedure ch)
|
||||||
=> (lambda (proc) (proc ch)))
|
=> (lambda (proc) (proc ch)))
|
||||||
(else
|
(else
|
||||||
|
@ -645,7 +655,7 @@
|
||||||
(list 'unsyntax (read-expr (next-non-whitespace)))))
|
(list 'unsyntax (read-expr (next-non-whitespace)))))
|
||||||
((#\n) (read-nil))
|
((#\n) (read-nil))
|
||||||
(else
|
(else
|
||||||
(input-error "Unknown # object: ~S" ch)))))))
|
(error "Unknown # object: ~S" ch)))))))
|
||||||
|
|
||||||
(define (read-number ch)
|
(define (read-number ch)
|
||||||
(let* ((str (read-token ch)))
|
(let* ((str (read-token ch)))
|
||||||
|
@ -702,24 +712,21 @@
|
||||||
;; FIXME: read-sharp should recur if we read a comment
|
;; FIXME: read-sharp should recur if we read a comment
|
||||||
(read-sharp))
|
(read-sharp))
|
||||||
((#\))
|
((#\))
|
||||||
(input-error "unexpected \")\""))
|
(error "unexpected \")\""))
|
||||||
((#\})
|
((#\})
|
||||||
(if (curly-infix?)
|
(if (curly-infix?)
|
||||||
(input-error "unexpected \"}\"")
|
(error "unexpected \"}\"")
|
||||||
(read-mixed-case-symbol ch)))
|
(read-mixed-case-symbol ch)))
|
||||||
((#\])
|
((#\])
|
||||||
(if (square-brackets?)
|
(if (square-brackets?)
|
||||||
(input-error "unexpected \"]\"")
|
(error "unexpected \"]\"")
|
||||||
(read-mixed-case-symbol ch)))
|
(read-mixed-case-symbol ch)))
|
||||||
((#f)
|
|
||||||
;; EOF.
|
|
||||||
the-eof-object)
|
|
||||||
((#\:)
|
((#\:)
|
||||||
(if (eq? (keyword-style) keyword-style-prefix)
|
(if (eq? (keyword-style) keyword-style-prefix)
|
||||||
;; FIXME: Don't skip whitespace here.
|
;; FIXME: Don't skip whitespace here.
|
||||||
(let ((ch (next-non-whitespace)))
|
(let ((ch (next-non-whitespace)))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "unexpected end of input while reading :keyword"))
|
(error "unexpected end of input while reading :keyword"))
|
||||||
(symbol->keyword (read-expr ch)))
|
(symbol->keyword (read-expr ch)))
|
||||||
(read-mixed-case-symbol ch)))
|
(read-mixed-case-symbol ch)))
|
||||||
((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\+ #\- #\.)
|
((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\+ #\- #\.)
|
||||||
|
@ -764,7 +771,7 @@
|
||||||
(let ((ch (next)))
|
(let ((ch (next)))
|
||||||
(cond
|
(cond
|
||||||
((eof-object? ch)
|
((eof-object? ch)
|
||||||
(input-error "unexpected end of input after #!"))
|
(error "unexpected end of input after #!"))
|
||||||
(else
|
(else
|
||||||
(string->symbol
|
(string->symbol
|
||||||
(take-while ch (lambda (ch)
|
(take-while ch (lambda (ch)
|
||||||
|
@ -776,7 +783,7 @@
|
||||||
(let lp ((ch (next)))
|
(let lp ((ch (next)))
|
||||||
(cond
|
(cond
|
||||||
((eof-object? ch)
|
((eof-object? ch)
|
||||||
(input-error "unexpected end of input while looking for !#"))
|
(error "unexpected end of input while looking for !#"))
|
||||||
((eqv? ch #\!)
|
((eqv? ch #\!)
|
||||||
(let ((ch (next)))
|
(let ((ch (next)))
|
||||||
(if (eqv? ch #\#)
|
(if (eqv? ch #\#)
|
||||||
|
@ -828,7 +835,7 @@
|
||||||
;; We have read #|, now looking for |#.
|
;; We have read #|, now looking for |#.
|
||||||
(let ((ch (next)))
|
(let ((ch (next)))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "unterminated `#| ... |#' comment"))
|
(error "unterminated `#| ... |#' comment"))
|
||||||
(cond
|
(cond
|
||||||
((and (eqv? ch #\|) (eqv? (peek) #\#))
|
((and (eqv? ch #\|) (eqv? (peek) #\#))
|
||||||
;; Done.
|
;; Done.
|
||||||
|
@ -856,7 +863,7 @@
|
||||||
(next)
|
(next)
|
||||||
(let ((ch (next-non-whitespace)))
|
(let ((ch (next-non-whitespace)))
|
||||||
(when (eof-object? ch)
|
(when (eof-object? ch)
|
||||||
(input-error "no expression after #; comment"))
|
(error "no expression after #; comment"))
|
||||||
(read-expr ch))
|
(read-expr ch))
|
||||||
(next-non-whitespace))
|
(next-non-whitespace))
|
||||||
((#\|)
|
((#\|)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue