b48a67ea22c9848c601bf5085d8c224abc5ee746
[sod] / src / parser / streams-proto.lisp
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-line position-aware-stream-column))
61 (defclass position-aware-stream (proxy-stream)
62 ((file :initarg :file :initform nil
63 :type (or pathname null) :accessor position-aware-stream-file)
64 (line :initarg :line :initform 1
65 :type fixnum :accessor position-aware-stream-line)
66 (column :initarg :column :initform 0
67 :type fixnum :accessor position-aware-stream-column))
68 (:documentation
69 "Character stream which keeps track of the line and column position.
70
71 A position-aware-stream wraps an existing character stream and tracks the
72 line and column position of the current stream position. A newline
73 character increases the line number by one and resets the column number to
74 zero; most characters advance the column number by one, but tab advances
75 to the next multiple of eight. (This is consistent with Emacs, at least.)
76 The position can be read using `stream-line-and-column'.
77
78 This is a base class; you probably want `position-aware-input-stream' or
79 `position-aware-output-stream'."))
80
81 (export 'position-aware-input-stream)
82 (defclass position-aware-input-stream
83 (position-aware-stream proxy-character-input-stream)
84 ()
85 (:documentation
86 "A character input stream which tracks the input position.
87
88 This is particularly useful for parsers and suchlike, which want to
89 produce accurate error-location information."))
90
91 (export 'position-aware-output-stream)
92 (defclass position-aware-output-stream
93 (position-aware-stream proxy-character-output-stream)
94 ()
95 (:documentation
96 "A character output stream which tracks the output position.
97
98 This is particularly useful when generating C code: the position can be
99 used to generate `#line' directives referring to the generated code after
100 insertion of some user code."))
101
102 ;;;----- That's all, folks --------------------------------------------------