| 1 | ;;; -*-lisp-*- |
| 2 | ;;; |
| 3 | ;;; Additional stream protocol. |
| 4 | ;;; |
| 5 | ;;; (c) 2009 Straylight/Edgeware |
| 6 | ;;; |
| 7 | |
| 8 | ;;;----- Licensing notice --------------------------------------------------- |
| 9 | ;;; |
| 10 | ;;; This file is part of the Sensible Object Design, an object system for C. |
| 11 | ;;; |
| 12 | ;;; SOD is free software; you can redistribute it and/or modify |
| 13 | ;;; it under the terms of the GNU General Public License as published by |
| 14 | ;;; the Free Software Foundation; either version 2 of the License, or |
| 15 | ;;; (at your option) any later version. |
| 16 | ;;; |
| 17 | ;;; SOD is distributed in the hope that it will be useful, |
| 18 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 19 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 20 | ;;; GNU General Public License for more details. |
| 21 | ;;; |
| 22 | ;;; You should have received a copy of the GNU General Public License |
| 23 | ;;; along with SOD; if not, write to the Free Software Foundation, |
| 24 | ;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 25 | |
| 26 | (cl:in-package #:sod-parser) |
| 27 | |
| 28 | ;;;-------------------------------------------------------------------------- |
| 29 | ;;; Discovery of file names and stream positions. |
| 30 | |
| 31 | (export 'stream-pathname) |
| 32 | (defgeneric stream-pathname (stream) |
| 33 | (:documentation |
| 34 | "Returns the pathname of the file that STREAM is open on. |
| 35 | |
| 36 | If STREAM is open on a file, then return the pathname of that file. |
| 37 | Otherwise return nil.") |
| 38 | |
| 39 | ;; Provide some default methods. Most streams don't have a pathname. |
| 40 | ;; File-based streams provide a pathname, but it's usually been merged with |
| 41 | ;; `*default-pathname-defaults*' or some such, which has made it absolute, |
| 42 | ;; which isn't ideal. We'll hack around this in more useful classes later. |
| 43 | (:method ((stream stream)) nil) |
| 44 | (:method ((stream file-stream)) (pathname stream))) |
| 45 | |
| 46 | (export 'stream-line-and-column) |
| 47 | (defgeneric stream-line-and-column (stream) |
| 48 | (:documentation |
| 49 | "Returns the current stream position of STREAM as line/column numbers. |
| 50 | |
| 51 | Returns two values: the line and column numbers of STREAM's input |
| 52 | position, or nil if the stream isn't capable of tracking these things.") |
| 53 | (:method ((stream stream)) |
| 54 | (values nil nil))) |
| 55 | |
| 56 | ;;;-------------------------------------------------------------------------- |
| 57 | ;;; Enhanced stream classes. |
| 58 | |
| 59 | (export '(position-aware-stream |
| 60 | position-aware-stream-file position-aware-stream-line |
| 61 | position-aware-stream-column)) |
| 62 | (defclass position-aware-stream (proxy-stream) |
| 63 | ((file :initarg :file :initform nil |
| 64 | :type (or pathname null) :accessor position-aware-stream-file) |
| 65 | (line :initarg :line :initform 1 |
| 66 | :type fixnum :accessor position-aware-stream-line) |
| 67 | (column :initarg :column :initform 0 |
| 68 | :type fixnum :accessor position-aware-stream-column)) |
| 69 | (:documentation |
| 70 | "Character stream which keeps track of the line and column position. |
| 71 | |
| 72 | A position-aware-stream wraps an existing character stream and tracks the |
| 73 | line and column position of the current stream position. A newline |
| 74 | character increases the line number by one and resets the column number to |
| 75 | zero; most characters advance the column number by one, but tab advances |
| 76 | to the next multiple of eight. (This is consistent with Emacs, at least.) |
| 77 | The position can be read using `stream-line-and-column'. |
| 78 | |
| 79 | This is a base class; you probably want `position-aware-input-stream' or |
| 80 | `position-aware-output-stream'.")) |
| 81 | |
| 82 | (export 'position-aware-input-stream) |
| 83 | (defclass position-aware-input-stream |
| 84 | (position-aware-stream proxy-character-input-stream) |
| 85 | () |
| 86 | (:documentation |
| 87 | "A character input stream which tracks the input position. |
| 88 | |
| 89 | This is particularly useful for parsers and suchlike, which want to |
| 90 | produce accurate error-location information.")) |
| 91 | |
| 92 | (export 'position-aware-output-stream) |
| 93 | (defclass position-aware-output-stream |
| 94 | (position-aware-stream proxy-character-output-stream) |
| 95 | () |
| 96 | (:documentation |
| 97 | "A character output stream which tracks the output position. |
| 98 | |
| 99 | This is particularly useful when generating C code: the position can be |
| 100 | used to generate `#line' directives referring to the generated code after |
| 101 | insertion of some user code.")) |
| 102 | |
| 103 | ;;;----- That's all, folks -------------------------------------------------- |