;;; -*-lisp-*- ;;; ;;; Additional stream protocol. ;;; ;;; (c) 2009 Straylight/Edgeware ;;; ;;;----- Licensing notice --------------------------------------------------- ;;; ;;; 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 ;;; 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) ;;;-------------------------------------------------------------------------- ;;; Discovery of file names and stream positions. (export 'stream-pathname) (defgeneric stream-pathname (stream) (:documentation "Returns the pathname of the file that STREAM is open on. If STREAM is open on a file, then return the pathname of that file. Otherwise return nil.") ;; Provide some default methods. Most streams don't have a pathname. ;; File-based streams provide a pathname, but it's usually been merged with ;; `*default-pathname-defaults*' or some such, which has made it absolute, ;; which isn't ideal. We'll hack around this in more useful classes later. (:method ((stream stream)) nil) (:method ((stream file-stream)) (pathname stream))) (export 'stream-line-and-column) (defgeneric stream-line-and-column (stream) (:documentation "Returns the current stream position of STREAM as line/column numbers. Returns two values: the line and column numbers of STREAM's input position, or nil if the stream isn't capable of tracking these things.") (:method ((stream stream)) (values nil nil))) ;;;-------------------------------------------------------------------------- ;;; Enhanced stream classes. (export '(position-aware-stream position-aware-stream-file position-aware-stream-line position-aware-stream-column)) (defclass position-aware-stream (proxy-stream) ((file :initarg :file :initform nil :type (or pathname null) :accessor position-aware-stream-file) (line :initarg :line :initform 1 :type fixnum :accessor position-aware-stream-line) (column :initarg :column :initform 0 :type fixnum :accessor position-aware-stream-column)) (:documentation "Character stream which keeps track of the line and column position. A position-aware-stream wraps an existing character stream and tracks the line and column position of the current stream position. A newline character increases the line number by one and resets the column number to zero; most characters advance the column number by one, but tab advances to the next multiple of eight. (This is consistent with Emacs, at least.) The position can be read using `stream-line-and-column'. This is a base class; you probably want `position-aware-input-stream' or `position-aware-output-stream'.")) (export 'position-aware-input-stream) (defclass position-aware-input-stream (position-aware-stream proxy-character-input-stream) () (:documentation "A character input stream which tracks the input position. This is particularly useful for parsers and suchlike, which want to produce accurate error-location information.")) (export 'position-aware-output-stream) (defclass position-aware-output-stream (position-aware-stream proxy-character-output-stream) () (:documentation "A character output stream which tracks the output position. This is particularly useful when generating C code: the position can be used to generate `#line' directives referring to the generated code after insertion of some user code.")) ;;;----- That's all, folks --------------------------------------------------