X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/e046c3f65a8f7241889fb9b6005aac21e2aad1a8..refs/heads/mdw/progfmt:/src/lexer-impl.lisp diff --git a/src/lexer-impl.lisp b/src/lexer-impl.lisp index 48109b1..ccaca5c 100644 --- a/src/lexer-impl.lisp +++ b/src/lexer-impl.lisp @@ -39,20 +39,27 @@ ;;;-------------------------------------------------------------------------- ;;; 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 "" stream)) +(defun show-char (char) + "Format CHAR as a string in a readable way." + (cond ((null char) "") ((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))))) @@ -149,13 +157,15 @@ (#\' (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) @@ -178,6 +188,14 @@ ;; 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))