lib/sod-hosted.c (sod_makev): Use two statements rather than tricky expression.
[sod] / src / lexer-impl.lisp
index 48109b1..ccaca5c 100644 (file)
 ;;;--------------------------------------------------------------------------
 ;;; Indicators and error messages.
 
-(defun show-char (stream char &optional colonp atsignp)
-  "Format CHAR to STREAM in a readable way.
-
-   Usable in `format''s ~/.../ command."
-  (declare (ignore colonp atsignp))
-  (cond ((null char) (write-string "<end-of-file>" stream))
+(defun show-char (char)
+  "Format CHAR as a string in a readable way."
+  (cond ((null char) "<end-of-file>")
        ((and (graphic-char-p char) (char/= char #\space))
-        (format stream "`~C'" char))
-       (t (format stream "<~(~:C~)>" char))))
+        (format nil "`~C'" char))
+       (t (format nil "<~(~:C~)>" char))))
 
-(defun skip-until (scanner token-types &key keep-end)
+(defun %skip-until (scanner token-types
+                   &key (keep-end (not (null (cdr token-types)))))
   "This is the implementation of the `skip-until' parser."
   (do ((consumedp nil t))
-      ((member (token-type scanner) token-types)
+      ((let ((type (token-type scanner))
+            (value (token-value scanner)))
+        (some (lambda (spec)
+                (multiple-value-bind (want-type want-value)
+                    (cond ((listp spec) (values (car spec) (cadr spec)))
+                          (t (values spec t)))
+                  (and (eq want-type type)
+                       (or (eq want-value t)
+                           (equal want-value value)))))
+              token-types))
        (unless keep-end (scanner-step scanner))
        (values nil t (or keep-end consumedp)))
     (when (scanner-at-eof-p scanner)
@@ -60,7 +67,7 @@
     (scanner-step scanner)))
 
 (defun parse-error-recover (scanner parser recover
-                           &key ignore-unconsumed force-progress)
+                           &key ignore-unconsumed force-progress action)
   "This is the implementation of the `error' parser."
   (multiple-value-bind (result win consumedp) (funcall parser)
     (cond ((or win
@@ -86,6 +93,7 @@
           ;; simply to propagate the current failure back to the caller, but
           ;; we handled that case above.
           (syntax-error scanner result)
+          (when action (funcall action))
           (when (and force-progress (not consumedp)) (scanner-step scanner))
           (funcall recover)))))
 
               (#\' (case (length contents)
                      (1 (char contents 0))
                      (0 (cerror*-with-location (start-floc)
-                                               "Lexical error: ~
-                                                empty character literal")
+                                               'simple-lexer-error
+                                               :format-control
+                                               "Empty character literal")
                         #\?)
                      (t (cerror*-with-location (start-floc)
-                                               "Lexical error: ~
-                                                too many characters ~
-                                                in literal")
+                                               'simple-lexer-error
+                                               :format-control
+                                               "Too many characters ~
+                                                in character literal")
                         (char contents 0))))))
           (values (etypecase it
                     (character :char)
 
          ;; Some special punctuation sequences are single tokens.
          ("..." (values :ellipsis nil))
+         ("==" (values :eq))
+         ("!=" (values :ne))
+         ("<=" (values :le))
+         (">=" (values :ge))
+         ("&&" (values :and))
+         ("||" (values :or))
+         ("<<" (values :shl))
+         (">>" (values :shr))
 
          ;; Any other character is punctuation.
          (:any (values it nil))