Commit db8df26edcfd230e784b218b0bb2fe8839db79a7

Thomas de Grivel 2018-06-13T18:07:01

generic read relying on lexer-token

diff --git a/package.lisp b/package.lisp
index 5488f80..204bd22 100644
--- a/package.lisp
+++ b/package.lisp
@@ -26,7 +26,10 @@
    #:*buffer-size*
    #:discard-token
    #:lexer
-   #:lexer-eof
+   #:lexer-buffer
+   #:lexer-in-character
+   #:lexer-in-eof
+   #:lexer-in-line
    #:lexer-input
    #:lexer-input-n
    #:lexer-match-char
diff --git a/token-stream.lisp b/token-stream.lisp
index 0afa0de..70589f4 100644
--- a/token-stream.lisp
+++ b/token-stream.lisp
@@ -55,8 +55,8 @@
               :initform -1
               :accessor lexer-in-character
               :type fixnum)
-   (eof :initform nil
-	:accessor lexer-eof)
+   (in-eof :initform nil
+           :accessor lexer-in-eof)
    (buffer :initform (make-buffer)
            :accessor lexer-buffer
            :type string)
@@ -68,7 +68,10 @@
           :type lexer-token)
    (stack :initform ()
           :accessor lexer-stack
-          :type list)))
+          :type list)
+   (eof-p :initform nil
+          :accessor lexer-eof-p
+          :type boolean)))
 
 (defgeneric discard-token (lexer)
   (:documentation "Discard token from lexer stack top."))
@@ -94,6 +97,9 @@ buffer for matching at index."))
   (:documentation "Put a character into lexer buffer, extending it by
 *BUFFER-SIZE* if necessary."))
 
+(defgeneric lexer-token (lexer)
+  (:documentation "Consumes and returns a token."))
+
 (defgeneric make-token (lexer symbol &rest initargs)
   (:documentation "Create a token of given class from lexer stack
 top."))
@@ -163,28 +169,33 @@ stack."))
                        (t
                         (incf (the fixnum (lexer-in-character lx)))))
                  (values c nil)))
-        ((:eof) (setf (lexer-eof lx) t)
+        ((:eof) (setf (lexer-in-eof lx) t)
          (values nil :eof))
         ((:non-blocking)
-         (values nil :non-blocking))))))
+         (signal (make-condition 'non-blocking :stream lx)))))))
 
 (defmethod lexer-match-start ((lx lexer))
   (token-start (lexer-match lx)))
 
-(defmethod (setf lexer-match-start) ((value fixnum) (lx lexer))
-  (setf (token-start (lexer-match lx)) value))
+(defmethod (setf lexer-match-start) ((value integer) (lx lexer))
+  (setf (token-start (lexer-match lx)) (the fixnum value)))
 
-(defmethod lexer-input-n ((lx lexer) (n fixnum))
+(defmethod lexer-input-n ((lx lexer) (n integer))
+  (declare (type fixnum n))
   (loop
-     (unless (< (- (the fixnum (fill-pointer (lexer-buffer lx)))
-                   (the fixnum (lexer-match-start lx)))
-                n)
-       (return))
-     (when (lexer-eof lx)
-       (return))
-     (lexer-input lx)))
-
-(defmethod lexer-match-char ((lx lexer) (index fixnum))
+     (let ((length (- (the fixnum (fill-pointer (lexer-buffer lx)))
+                      (the fixnum (lexer-match-start lx)))))
+       (declare (type fixnum length))
+       (when (lexer-in-eof lx)
+         (if (= 0 length)
+             (signal (make-instance 'end-of-file :stream lx))
+             (return)))
+       (unless (< length n)
+         (return))
+       (lexer-input lx))))
+
+(defmethod lexer-match-char ((lx lexer) (index integer))
+  (declare (type fixnum index))
   (lexer-input-n lx (the fixnum (1+ index)))
   (let ((buf (lexer-buffer lx))
         (match-index (+ (the fixnum (lexer-match-start lx))
@@ -206,13 +217,16 @@ stack."))
                                :start start)))
     (push token (lexer-stack lx))))
 
+(defun subseq* (sequence start &optional end)
+  (subseq sequence start end))
+
 (defmethod pop-token ((lx lexer))
   (assert (lexer-stack lx))
   (let* ((buffer (lexer-buffer lx))
 	 (fp (fill-pointer buffer))
 	 (token (pop (lexer-stack lx)))
 	 (match-start (lexer-match-start lx))
-         (string (subseq buffer (token-start token) match-start)))
+         (string (subseq* buffer (token-start token) match-start)))
     (setf (token-string token) string)
     (when (endp (lexer-stack lx))
       (replace buffer buffer :start2 match-start :end2 fp)
@@ -229,7 +243,14 @@ stack."))
 	   initargs)))
 
 (defmethod discard-token ((lx lexer))
-  (pop-token lx)
+  (pop (lexer-stack lx))
+  (when (endp (lexer-stack lx))
+    (let* ((buffer (lexer-buffer lx))
+           (fp (fill-pointer buffer))
+           (match-start (lexer-match-start lx)))
+      (replace buffer buffer :start2 match-start :end2 fp)
+      (setf (lexer-match-start lx) 0
+            (fill-pointer buffer) (- fp match-start))))
   nil)
 
 ;;  Matcher
@@ -251,7 +272,7 @@ stack."))
      (let ((match (match lx s)))
        (when match
          (return match)))
-     (when (lexer-eof lx)
+     (when (lexer-in-eof lx)
        (return))
      (lexer-input lx)
      (incf (the fixnum (lexer-match-start lx)))))
@@ -263,7 +284,7 @@ stack."))
 (defmethod match-not ((lx lexer) (f function))
   (let ((match-start (lexer-match-start lx)))
     (cond ((or (funcall f lx)
-               (lexer-eof lx))
+               (lexer-in-eof lx))
            (setf (lexer-match-start lx) match-start)
            nil)
           (t
@@ -282,7 +303,8 @@ stack."))
 	      (setf (lexer-match-start ,lx) ,match-start)
 	      nil)))))
 
-(defmethod match-times ((lx lexer) (f function) (min fixnum) (max fixnum))
+(defmethod match-times ((lx lexer) (f function) (min integer) (max integer))
+  (declare (type fixnum min max))
   (match-sequence lx
     (let ((n 0))
       (loop
@@ -294,7 +316,8 @@ stack."))
                (return (lexer-match-start lx))))
          (incf n)))))
 
-(defmethod match-times ((lx lexer) (f function) (min fixnum) (max null))
+(defmethod match-times ((lx lexer) (f function) (min integer) (max null))
+  (declare (type fixnum min))
   (match-sequence lx
     (let ((n 0))
       (declare (type fixnum n))
@@ -304,3 +327,10 @@ stack."))
                (return nil)
                (return (lexer-match-start lx))))
          (incf n)))))
+
+(defmethod stream-read ((lx lexer))
+  (if (lexer-eof-p lx)
+      (values nil :eof)
+      (handler-case (values (lexer-token lx) nil)
+        (end-of-file () (values nil :eof))
+        (non-blocking () (values nil :non-blocking)))))