chiark / gitweb /
Refactoring more or less complete. Maybe I should test it.
[sod] / src / lexer-impl.lisp
index f4745909a5233786e6568cc2b8266654edd28c42..6fc6fccd09bc0be756b719dfdd4ec3e96b4106bc 100644 (file)
@@ -52,6 +52,41 @@ (defun show-char (stream char &optional colonp atsignp)
         (format stream "`~C'" char))
        (t (format stream "<~(~:C~)>" char))))
 
+(defun skip-until (scanner token-types &key keep-end)
+  "This is the implementation of the `skip-until' parser."
+  (do ((consumedp nil t))
+      ((member (token-type scanner) token-types)
+       (unless keep-end (scanner-step scanner))
+       (values nil t (or keep-end consumedp)))
+    (when (scanner-at-eof-p scanner)
+      (return (values token-types nil consumedp)))
+    (scanner-step scanner)))
+
+(defun parse-error-recover (scanner parser recover)
+  "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.
+          (values result win consumedp))
+         (t
+          ;; Now we have to do some kind of sensible error recovery.  The
+          ;; important thing to do here is to make sure that we make some
+          ;; progress.  If we consumed any tokens then we're fine, and we'll
+          ;; just try the provided recovery strategy.  Otherwise, if we're
+          ;; not at EOF, then we can ensure progress by discarding the
+          ;; 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))
+          (funcall recover)))))
+
 ;;;--------------------------------------------------------------------------
 ;;; Token scanning.