src/lexer-impl.lisp: Don't always skip a token.
[sod] / src / lexer-impl.lisp
index ba1f7c1..f00994a 100644 (file)
@@ -7,7 +7,7 @@
 
 ;;;----- Licensing notice ---------------------------------------------------
 ;;;
-;;; This file is part of the Sensble Object Design, an object system for C.
+;;; This file is part of the Sensible Object Design, an object system for C.
 ;;;
 ;;; SOD is free software; you can redistribute it and/or modify
 ;;; it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
 
    Usable in `format''s ~/.../ command."
   (declare (ignore colonp atsignp))
-  (cond ((null char) (write-string "<eof>" stream))
+  (cond ((null char) (write-string "<end-of-file>" stream))
        ((and (graphic-char-p char) (char/= char #\space))
         (format stream "`~C'" char))
        (t (format stream "<~(~:C~)>" char))))
       (return (values token-types nil consumedp)))
     (scanner-step scanner)))
 
-(defun parse-error-recover (scanner parser recover)
+(defun parse-error-recover (scanner parser recover
+                           &key ignore-unconsumed force-progress)
   "This is the implementation of the `error' parser."
   (multiple-value-bind (result win consumedp) (funcall parser)
-    (cond ((or win (and (not consumedp) (scanner-at-eof-p scanner)))
-          ;; If we succeeded then there's nothing for us to do here.  On the
-          ;; other hand, if we failed, didn't consume any tokens, and we're
-          ;; at end-of-file, then there's not much hope of making onward
-          ;; progress, so in this case we propagate the failure rather than
-          ;; trying to recover.  And we assume that the continuation will
-          ;; somehow arrange to report the problem, and avoid inundating the
-          ;; user with error reports.
+    (cond ((or win
+              (and (not consumedp)
+                   (or ignore-unconsumed
+                       (scanner-at-eof-p scanner))))
+          ;; If we succeeded, or if we didn't consume any tokens and the
+          ;; caller's OK with that, then there's nothing for us to do here.
+          ;; On the other hand, if we failed, didn't consume any tokens, and
+          ;; we're at end-of-file, then there's not much hope of making
+          ;; onward progress, so in this case we propagate the failure
+          ;; rather than trying to recover.  And we assume that the
+          ;; continuation will somehow arrange to report the problem, and
+          ;; avoid inundating the user with error reports.
           (values result win consumedp))
          (t
           ;; Now we have to do some kind of sensible error recovery.  The
@@ -80,8 +85,8 @@
           ;; current token.  Finally, if we are at EOF then our best bet is
           ;; simply to propagate the current failure back to the caller, but
           ;; we handled that case above.
-          (syntax-error scanner result :continuep t)
-          (unless consumedp (scanner-step scanner))
+          (syntax-error scanner result)
+          (when (and force-progress (not consumedp)) (scanner-step scanner))
           (funcall recover)))))
 
 ;;;--------------------------------------------------------------------------
          (cond-parse (:consumedp cp :expected exp)
            ((satisfies whitespace-char-p) (parse :whitespace))
            ((scan-comment char-scanner))
-           (t (if cp (lexer-error char-scanner exp cp) (return)))))
+           (t (if cp (lexer-error char-scanner exp) (return)))))
 
        ;; Now parse something.
        (cond-parse (:consumedp cp :expected exp)
          ;; must make progress on every call.
          (t
           (assert cp)
-          (lexer-error char-scanner exp cp)
+          (lexer-error char-scanner exp)
           (scanner-token scanner)))))))
 
 ;;;----- That's all, folks --------------------------------------------------