X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/bf090e021a5c20da452a4841cdfb8eb78e29544e..aa14a4cddcb96b681d5c19a2ec8bad382f43b264:/src/parser/proto-scanner.lisp diff --git a/src/parser/proto-scanner.lisp b/src/parser/proto-scanner.lisp deleted file mode 100644 index 966c77c..0000000 --- a/src/parser/proto-scanner.lisp +++ /dev/null @@ -1,269 +0,0 @@ -;;; -*-lisp-*- -;;; -;;; Scanner protocol definitions. -;;; -;;; (c) 2009 Straylight/Edgeware -;;; - -;;;----- Licensing notice --------------------------------------------------- -;;; -;;; This file is part of the Sensble 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 -;;; the Free Software Foundation; either version 2 of the License, or -;;; (at your option) any later version. -;;; -;;; SOD is distributed in the hope that it will be useful, -;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with SOD; if not, write to the Free Software Foundation, -;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -(cl:in-package #:sod-parser) - -;;;-------------------------------------------------------------------------- -;;; Scanner context protocol. - -(export 'parser-scanner) -(defgeneric parser-scanner (context) - (:documentation - "Return the symbol naming the CONTEXT's run-time scanner.")) - -(export 'scanner-context) -(defclass scanner-context () - ((scanner :initarg :scanner :type symbol :reader parser-scanner)) - (:documentation - "Base class for scanner contexts. - - A scanner is simply an object maintaining the run-time state of a parsing - operation, in the same way as a parser context maintains the compile-time - state. So the scanner context is a compile-time context which expands to - calls to use the run-time scanner. See? - - This class provides common compile-time behaviour for `parser-at-eof-p' - and friends by invoking corresponding methods on the scanner object at - run-time.")) - -;;;-------------------------------------------------------------------------- -;;; Basic scanner protocol. - -(export 'scanner-at-eof-p) -(defgeneric scanner-at-eof-p (scanner) - (:documentation - "Answer whether the SCANNER is at end-of-file. - - It is an error to query the current item when at end-of-file.")) - -(export 'scanner-step) -(defgeneric scanner-step (scanner) - (:documentation - "Advance the SCANNER to the next item. - - The precise nature of the items isn't known at this level, so a protocol - for accessing them is left for later.")) - -;;;-------------------------------------------------------------------------- -;;; Scanner place-capture protocol. - -(export 'scanner-capture-place) -(defgeneric scanner-capture-place (scanner) - (:documentation - "Capture the SCANNER's current place and return it.") - (:method (scanner) - (error "Scanner ~S doesn't support rewinding." scanner))) - -(export 'scanner-restore-place) -(defgeneric scanner-restore-place (scanner place) - (:documentation - "`Rewind' the SCANNER to the captured PLACE. - - The place was previously captured by `scanner-capture-place'.")) - -(export 'scanner-release-place) -(defgeneric scanner-release-place (scanner place) - (:documentation - "Release a PLACE captured from the SCANNER. - - The place was previously captured by `scanner-capture-place'.") - (:method (scanner place) nil)) - -(export 'with-scanner-place) -(defmacro with-scanner-place ((place scanner) &body body) - "Evaluate BODY with PLACE bound to the captured current place. - - Automatically releases the place when the BODY finishes. Note that - if you wanted to circumvent the cleanup then you should have used - `with-parser-place', which does all of this in the meta-level." - (once-only (scanner) - `(let ((,place (scanner-capture-place ,scanner))) - (unwind-protect (progn ,@body) - (scanner-release-place ,scanner ,place))))) - -;;;-------------------------------------------------------------------------- -;;; Character scanner protocol. - -(export 'character-scanner) -(defclass character-scanner () - () - (:documentation "Base class for character scanners.")) - -(export 'character-scanner-context) -(defclass character-scanner-context - (scanner-context character-parser-context) - () - (:documentation - "A context for a richer character-oriented scanner.")) - -(export 'scanner-current-char) -(defgeneric scanner-current-char (scanner) - (:documentation - "Returns the SCANNER's current character. - - You advance to the next one using `scanner-step'.")) - -(export 'scanner-unread) -(defgeneric scanner-unread (scanner char) - (:documentation - "Rewind SCANNER by one character, specifically CHAR. - - CHAR must be the character most recently stepped over by `scanner-step' -- - it is an error to unread before the first call to `scanner-step'. It is - also an error to unread after encountering end-of-file.")) - -(export 'scanner-interval) -(defgeneric scanner-interval (scanner place-a &optional place-b) - (:documentation - "Return the characters from PLACE-A up to (but not including) PLACE-B. - - The characters are returned as a string. If PLACE-B is omitted, return - the characters up to (but not including) the current position. It is an - error if PLACE-B precedes PLACE-A or they are from different scanners.")) - -(export '(scanner-filename scanner-line scanner-column)) -(defgeneric scanner-filename (scanner) - (:documentation "Return the filename backing the SCANNER.") - (:method (scanner) nil)) -(defgeneric scanner-line (scanner) - (:documentation "Return the SCANNER's current line number.") - (:method (scanner) nil)) -(defgeneric scanner-column (scanner) - (:documentation "Return the SCANNER's current column number.") - (:method (scanner) nil)) - -(defun scanner-file-location (scanner) - "Capture the current location of the SCANNER. - - This uses the generic functions `scanner-filename', `scanner-line' and - `scanner-column' to compute its result. There are default methods on - these functions which make up dummy results. - - There is a method for `file-location' defined on `character-scanner' which - simply calls this function; but since some scanners are structure-objects - rather than standard-objects they can't include `character-scanner' as a - superclass." - (make-file-location (scanner-filename scanner) - (scanner-line scanner) - (scanner-column scanner))) - -;;;-------------------------------------------------------------------------- -;;; Token scanner protocol. - -;; A place marker. - -(export '(token-scanner-place token-scanner-place-p)) -(defstruct token-scanner-place - "A link in the chain of lookahead tokens; capturable as a place. - - If the scanner's place is captured, it starts to maintain a list of - lookahead tokens. The list contains internal links -- it works out - slightly easier that way. This is basically a simpler version of the - charbuf scanner (q.v.); most significantly, the chain links here do double - duty as place markers. - - The details of this structure are not a defined part of the token scanner - protocol." - - (next nil :type (or token-scanner-place null)) - (type nil :read-only t) - (value nil :read-only t) - (line 1 :type (or fixnum null) :read-only t) - (column 0 :type (or fixnum null) :read-only t)) - -;; The token scanner base class and parser context. - -(export '(token-scanner token-type token-value)) -(defclass token-scanner () - ((type :reader token-type) - (value :reader token-value) - (captures :initform 0 :type fixnum) - (tail :initform nil :type (or token-scanner-place null)) - (filename :initarg :filename :type string :reader scanner-filename) - (line :initarg :line :initform 1 :type fixnum :accessor scanner-line) - (column :initarg :column :initform 0 - :type fixnum :accessor scanner-column)) - (:documentation - "A rewindable scanner for tokenizing. - - The scanner should be used via the parser protocol; see also the token - scanner protocol, which explains the model. - - Subclasses must provide the detailed scanning behaviour -- most notably - the `scanner-token' generic function. This function should also update - the `line' and `column' slots to track the position in the underlying - source, if appropriate, and also implement a method on `file-location' to - return the location. This class will handle the remaining details, such - as dealing correctly with rewinding.")) - -(export 'token-scanner-context) -(defclass token-scanner-context (scanner-context token-parser-context) - () - (:documentation - "A parser context for a richer token-based scanners.")) - -;; Protocol. - -(export 'scanner-token) -(defgeneric scanner-token (scanner) - (:documentation - "Internal protocol: read the next token from the SCANNER. - - This function is called by `scanner-step' to actually read the next token - if necessary. It should return two values: the token's `type' and its - `value'.")) - -;;;-------------------------------------------------------------------------- -;;; Character scanner streams. -;;; -;;; This seems like an abstraction inversion, but it's important if we're to -;;; `read' from a character scanner. - -(export 'character-scanner-stream) -(defclass character-scanner-stream (fundamental-character-input-stream) - ((scanner :initarg :scanner)) - (:documentation - "A stream which reads from a character scanner. - - The SCANNER must implement the character scanner protcol, including - `scanner-current-char', `scanner-step', and `scanner-unread'; it is not - necessary that the scanner implement the place-capture protocol. - - The stream can be made more efficient by implementing - `stream-read-sequence' and `stream-read-line' in a scanner-specific - manner.")) - -(export 'make-scanner-stream) -(defgeneric make-scanner-stream (scanner) - (:documentation - "Return a stream which reads from the SCANNER. - - The default method simply constructs a `character-scanner-stream' - instance. Subclasses of `character-scanner' can override this method in - order to return instances of more efficient stream subclasses.") - (:method ((scanner character-scanner)) - (make-instance 'character-scanner-stream :scanner scanner))) - -;;;----- That's all, folks --------------------------------------------------