X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/239fa5bd3dff0b38b0cebdd3438311f21c24ba4f..89ef4001b93c0219096c94125e7e9fdb745d2c97:/src/lexer-proto.lisp diff --git a/src/lexer-proto.lisp b/src/lexer-proto.lisp index e72152e..d6d33cb 100644 --- a/src/lexer-proto.lisp +++ b/src/lexer-proto.lisp @@ -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 @@ ;;;-------------------------------------------------------------------------- ;;; 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 @@ (format nil "~/sod::show-char/" type) (case type (:id (format nil "" value)) + (:int "") (:string "") (:char "") (:eof "") @@ -95,9 +99,48 @@ (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.