src/parser/scanner-charbuf-impl.lisp: Simplify `stream-read-line'.
[sod] / src / parser / scanner-charbuf-impl.lisp
index 86dc999..8377a74 100644 (file)
   (buf nil :type (or charbuf (member nil :eof)) :read-only t)
   (size 0 :type charbuf-index :read-only t))
 
-(export 'charbuf-scanner-place-p)
-(defstruct charbuf-scanner-place
-  "A captured place we can return to later.
-
-   We remember the buffer-chain link, so that we can retrace our steps up to
-   the present.  We also need the index at which we continue reading
-   characters; and the line and column numbers to resume from."
-  (link nil :type charbuf-chain-link :read-only t)
-  (index 0 :type charbuf-index :read-only t)
-  (line 0 :type fixnum :read-only t)
-  (column 0 :type fixnum :read-only t))
-
 ;;;--------------------------------------------------------------------------
 ;;; Main class.
 
 (export 'charbuf-scanner)
 (defclass charbuf-scanner (character-scanner)
-  ((stream :initarg :stream :type stream)
+  ((%stream :initarg :stream :type stream)
    (buf :initform nil :type (or charbuf (member nil :eof)))
    (size :initform 0 :type (integer 0 #.charbuf-size))
    (index :initform 0 :type (integer 0 #.charbuf-size))
    captured places properly when he's finished.  In practice, this is usually
    done using the `peek' parser macro so there isn't a problem."))
 
+(export 'charbuf-scanner-place-p)
+(defstruct charbuf-scanner-place
+  "A captured place we can return to later.
+
+   We remember the buffer-chain link, so that we can retrace our steps up to
+   the present.  We also need the index at which we continue reading
+   characters; and the line and column numbers to resume from."
+  (scanner nil :type charbuf-scanner :read-only t)
+  (link nil :type charbuf-chain-link :read-only t)
+  (index 0 :type charbuf-index :read-only t)
+  (line 0 :type fixnum :read-only t)
+  (column 0 :type fixnum :read-only t))
+
+(defmethod file-location ((place charbuf-scanner-place))
+  (make-file-location (scanner-filename
+                      (charbuf-scanner-place-scanner place))
+                     (charbuf-scanner-place-line place)
+                     (charbuf-scanner-place-column place)))
+
 ;;;--------------------------------------------------------------------------
 ;;; Utilities.
 
    (if we're currently rewound) or with a new buffer from the stream."))
 
 (defmethod charbuf-scanner-fetch ((scanner charbuf-scanner))
-  (with-slots (stream buf size index tail captures) scanner
+  (with-slots ((stream %stream) buf size index tail captures) scanner
     (loop
       (acond
 
   ;; Grab the filename from the underlying stream if we don't have a better
   ;; guess.
   (default-slot (scanner 'filename slot-names)
-    (with-slots (stream) scanner
+    (with-slots ((stream %stream)) scanner
       (aif (stream-pathname stream) (namestring it) nil)))
 
   ;; Get ready with the first character.
     (incf captures)
     (unless tail
       (setf tail (make-charbuf-chain-link :buf buf :size size)))
-    (make-charbuf-scanner-place :link tail :index index
+    (make-charbuf-scanner-place :scanner scanner :link tail :index index
                                :line line :column column)))
 
 (defmethod scanner-restore-place ((scanner charbuf-scanner) place)
   (let* ((slices nil)
         (place-b (or place-b
                      (with-slots (index tail) scanner
-                       (make-charbuf-scanner-place :link tail
+                       (make-charbuf-scanner-place :scanner scanner
+                                                   :link tail
                                                    :index index))))
         (last-link (charbuf-scanner-place-link place-b)))
     (flet ((bad ()
     (unless end (setf end (length seq)))
     (let ((i start) (n (- end start)))
       (labels ((copy (i buf start end)
-                (do ((j i (1+ j))
-                     (k start (1+ k)))
-                    ((>= k end))
-                  (setf (char seq j) (schar buf k))))
+                (replace seq buf :start1 i :start2 start :end2 end))
               (snarf (buf start end)
                 (let ((m (- end start)))
                   (cond ((< m n)
       (flet ((snarf (buf start end)
               (let ((pos (position #\newline buf :start start :end end)))
                 (push (make-charbuf-slice buf start (or pos end)) slices)
-                (if pos
-                    (values (concatenate-charbuf-slices (nreverse slices))
-                            (1+ pos))
-                    (values nil 0))))
-            (fail ()
-              (values (concatenate-charbuf-slices (nreverse slices)) t)))
-       (charbuf-scanner-map scanner #'snarf #'fail)))))
+                (values pos (and pos (1+ pos))))))
+       (multiple-value-bind (result eofp)
+           (charbuf-scanner-map scanner #'snarf)
+         (declare (ignore result))
+         (values (concatenate-charbuf-slices (nreverse slices))) eofp)))))
 
 ;;;----- That's all, folks --------------------------------------------------