chiark / gitweb /
src/lexer-*.lisp: Add option to `error' to ignore non-consuming failure.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 17 Nov 2015 20:27:44 +0000 (20:27 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 17 Nov 2015 20:33:51 +0000 (20:33 +0000)
Maybe you're using `error' somewhere where a totally missing thing is
OK: the new :ignore-unconsumed option lets you tell it that this isn't a
problem.

src/lexer-impl.lisp
src/lexer-proto.lisp

index ffc8446f41450961c77c417825786a4077c39970..7e953ef8608ae69ab4aaf99c20f7d7013ed3596a 100644 (file)
@@ -59,17 +59,21 @@ (defun skip-until (scanner token-types &key keep-end)
       (return (values token-types nil consumedp)))
     (scanner-step scanner)))
 
       (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)
   "This is the implementation of the `error' parser."
   (multiple-value-bind (result win consumedp) (funcall parser)
   "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
           (values result win consumedp))
          (t
           ;; Now we have to do some kind of sensible error recovery.  The
index 7ed7924c8590fe970db50a27afeb235c523e8749..d6d33cbf4b24f7a42bf7bb7804a525fc97a46c56 100644 (file)
@@ -116,7 +116,8 @@ (defparse skip-until (:context (context token-scanner-context)
 
 (export 'error)
 (defparse error (:context (context token-scanner-context)
 
 (export 'error)
 (defparse error (:context (context token-scanner-context)
-                (&key) sub &optional (recover t))
+                (&key ignore-unconsumed)
+                sub &optional (recover t))
   "Try to parse SUB; if it fails then report an error, and parse RECOVER.
 
    This is the main way to recover from errors and continue parsing.  Even
   "Try to parse SUB; if it fails then report an error, and parse RECOVER.
 
    This is the main way to recover from errors and continue parsing.  Even
@@ -126,10 +127,15 @@ (defparse error (:context (context token-scanner-context)
    were never here.  Otherwise, try to recover in a sensible way so we can
    continue parsing.  The details of this recovery are subject to change, but
    the final action is generally to invoke the RECOVER parser and return its
    were never here.  Otherwise, try to recover in a sensible way so we can
    continue parsing.  The details of this recovery are subject to change, but
    the final action is generally to invoke the RECOVER parser and return its
-   result."
+   result.
+
+   If IGNORE-UNCONSUMED evaluates non-nil, then just propagate a failure of
+   SUB if it didn't consume input.  (This makes it suitable for use where the
+   parser containing `error' might be optional.)"
   `(parse-error-recover ,(parser-scanner context)
                        (parser () ,sub)
   `(parse-error-recover ,(parser-scanner context)
                        (parser () ,sub)
-                       (parser () ,recover)))
+                       (parser () ,recover)
+                       :ignore-unconsumed ,ignore-unconsumed))
 
 ;;;--------------------------------------------------------------------------
 ;;; Lexical analysis utilities.
 
 ;;;--------------------------------------------------------------------------
 ;;; Lexical analysis utilities.