indicator)
(export 'syntax-error)
-(defun syntax-error (scanner expected &key (continuep t))
+(defun syntax-error (scanner expected &key (continuep t) location)
"Signal a (maybe) continuable syntax error."
(labels ((show-token (type value)
(if (characterp type)
((eq (car thing) :id)
(format nil "`~A'" (cadr thing)))
(t (format nil "<? ~S>" thing)))))
- (funcall (if continuep #'cerror* #'error)
+ (funcall (if continuep #'cerror*-with-location #'error-with-location)
+ (or location scanner)
"Syntax error: ~
expected ~{~#[<bug>~;~A~;~A or ~A~:;~A, ~]~} ~
but found ~A"
(show-token (token-type scanner) (token-value scanner)))))
(export 'lexer-error)
-(defun lexer-error (char-scanner expected)
+(defun lexer-error (char-scanner expected &key location)
"Signal a continuable lexical error."
- (cerror* "Lexical error: ~
- expected ~{~#[<bug>~;~A~;~A or ~A~:;~A, ~]~} ~
- but found ~/sod::show-char/"
+ (cerror*-with-location (or location char-scanner)
+ "Lexical error: ~
+ ~:[unexpected~;~
+ expected ~:*~{~#[~;~A~;~A or ~A~:;~
+ ~@{~A, ~#[~;or ~A~]~}~]~} ~
+ but found~] ~
+ ~/sod::show-char/"
(mapcar (lambda (exp)
(typecase exp
(character (format nil "~/sod::show-char/" exp))
(export 'error)
(defparse error (:context (context token-scanner-context)
- (&key ignore-unconsumed)
+ (&key ignore-unconsumed force-progress)
sub &optional (recover t))
"Try to parse SUB; if it fails then report an error, and parse RECOVER.
`(parse-error-recover ,(parser-scanner context)
(parser () ,sub)
(parser () ,recover)
- :ignore-unconsumed ,ignore-unconsumed))
+ :ignore-unconsumed ,ignore-unconsumed
+ :force-progress ,force-progress))
;;;--------------------------------------------------------------------------
;;; Lexical analysis utilities.
The result isn't interesting."
(with-parser-context (character-scanner-context :scanner char-scanner)
- (parse (or (and "/*"
- (and (skip-many ()
- (and (skip-many () (not #\*))
- (label "*/" (skip-many (:min 1) #\*)))
- (not #\/))
- #\/))
- (and "//"
- (skip-many () (not #\newline))
- (? #\newline))))))
+ (let ((start (file-location char-scanner)))
+ (parse (or (and "/*"
+ (lisp (let ((state nil))
+ (loop (cond ((scanner-at-eof-p char-scanner)
+ (lexer-error char-scanner
+ (list "*/"))
+ (info-with-location
+ start "Comment started here")
+ (return (values nil t t)))
+ ((char= (scanner-current-char
+ char-scanner)
+ #\*)
+ (setf state '*)
+ (scanner-step char-scanner))
+ ((and (eq state '*)
+ (char= (scanner-current-char
+ char-scanner)
+ #\/))
+ (scanner-step char-scanner)
+ (return (values nil t t)))
+ (t
+ (setf state nil)
+ (scanner-step char-scanner)))))))
+ (and "//"
+ (skip-many () (not #\newline))
+ (? #\newline)))))))
;;;----- That's all, folks --------------------------------------------------