chiark / gitweb /
src/lexer-proto.lisp (lexer-error): Fix spin from bad `format' string.
[sod] / src / lexer-proto.lisp
index e72152e2c9d1afafd1576c3a7e8067670d198317..1850326747a8982cdf7981f2330f9c1d26467117 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
@@ -40,6 +40,9 @@ (defclass sod-token-scanner (token-scanner)
 ;;;--------------------------------------------------------------------------
 ;;; Indicators and error messages.
 
+(defvar *indicator-map* (make-hash-table)
+  "Hash table mapping indicator objects to human-readable descriptions.")
+
 (export 'define-indicator)
 (defun define-indicator (indicator description)
   "Associate an INDICATOR with its textual DESCRIPTION.
@@ -56,6 +59,7 @@ (defun syntax-error (scanner expected &key (continuep t))
                 (format nil "~/sod::show-char/" type)
                 (case type
                   (:id (format nil "<identifier~@[ `~A'~]>" value))
+                  (:int "<integer-literal>")
                   (:string "<string-literal>")
                   (:char "<character-literal>")
                   (:eof "<end-of-file>")
@@ -78,7 +82,7 @@ (export 'lexer-error)
 (defun lexer-error (char-scanner expected consumedp)
   "Signal a continuable lexical error."
   (cerror* "Lexical error: ~
-           expected ~{~#[<bug>~;~A~;~A or ~A~;:~A, ~]~} ~
+           expected ~{~#[<bug>~;~A~;~A or ~A~:;~A, ~]~} ~
            but found ~/sod::show-char/~
            ~@[ at ~A~]"
           (mapcar (lambda (exp)
@@ -95,9 +99,48 @@ (defun lexer-error (char-scanner expected consumedp)
                (scanner-current-char char-scanner))
           (and consumedp (file-location char-scanner))))
 
+(export 'skip-until)
+(defparse skip-until (:context (context token-scanner-context)
+                     (&key (keep-end nil keep-end-p))
+                     &rest token-types)
+  "Discard tokens until we find one listed in TOKEN-TYPES.
+
+   If KEEP-END is true then retain the found token for later; otherwise
+   discard it.  KEEP-END defaults to true if multiple TOKEN-TYPES are given;
+   otherwise false.  If end-of-file is encountered then the indicator list is
+   simply the list of TOKEN-TYPES; otherwise the result is `nil'."
+  `(skip-until ,(parser-scanner context)
+              (list ,@token-types)
+              :keep-end ,(if keep-end-p keep-end
+                             (> (length token-types) 1))))
+
+(export 'error)
+(defparse error (:context (context token-scanner-context)
+                (&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
+   then, it's not especially brilliant.
+
+   If the SUB parser succeeds then just propagate its result: it's like we
+   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.
+
+   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)
+                       (parser () ,recover)
+                       :ignore-unconsumed ,ignore-unconsumed))
+
 ;;;--------------------------------------------------------------------------
 ;;; Lexical analysis utilities.
 
+(export 'scan-comment)
 (defun scan-comment (char-scanner)
   "Scan a comment (either `/* ... */' or `// ...') from CHAR-SCANNER.