src/parser/scanner-impl.lisp: Location protocol for `string-scanner'.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 26 May 2016 08:26:09 +0000 (09:26 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 8 Jun 2018 18:58:28 +0000 (19:58 +0100)
Implement the protocol using the utilities carefully provided years ago
for the purpose.

doc/SYMBOLS
src/parser/scanner-impl.lisp

index ddf63e5..0d8549f 100644 (file)
@@ -1913,6 +1913,7 @@ file-location
   condition-with-location
   file-location
   position-aware-stream
+  string-scanner
   token-scanner
   token-scanner-place
 cl:make-load-form
@@ -2000,6 +2001,7 @@ scanner-capture-place
 scanner-column
   t
   charbuf-scanner
+  string-scanner
   token-scanner
 (setf scanner-column)
   t token-scanner
@@ -2009,6 +2011,7 @@ scanner-current-char
 scanner-filename
   t
   charbuf-scanner
+  string-scanner
   token-scanner
 scanner-interval
   charbuf-scanner t
@@ -2016,6 +2019,7 @@ scanner-interval
 scanner-line
   t
   charbuf-scanner
+  string-scanner
   token-scanner
 (setf scanner-line)
   t token-scanner
index 8bca29f..d856ba9 100644 (file)
 (export '(string-scanner make-string-scanner string-scanner-p))
 (defstruct (string-scanner
             (:constructor make-string-scanner
-                (string &key (start 0) end
+                (string &key (start 0) end filename
                  &aux (%string string)
                       (index start)
                       (limit (or end (length string))))))
   "Scanner structure for a simple string scanner."
   (%string "" :type string :read-only t)
+  (filename "<string>" :type string :read-only t)
   (index 0 :type (and fixnum unsigned-byte))
-  (limit nil :type (and fixnum unsigned-byte) :read-only t))
+  (limit nil :type (and fixnum unsigned-byte) :read-only t)
+  (line 1 :type fixnum)
+  (column 0 :type fixnum))
 (define-access-wrapper string-scanner-string string-scanner-%string
                       :read-only t)
 
   (char (string-scanner-string scanner) (string-scanner-index scanner)))
 
 (defmethod scanner-step ((scanner string-scanner))
-  (incf (string-scanner-index scanner)))
+  (let ((index (string-scanner-index scanner)))
+    (setf (values (string-scanner-line scanner)
+                 (string-scanner-column scanner))
+         (update-position (char (string-scanner-string scanner) index)
+                          (string-scanner-line scanner)
+                          (string-scanner-column scanner))
+         (string-scanner-index scanner) (1+ index))))
 
 (defmethod scanner-unread ((scanner string-scanner) char)
-  (decf (string-scanner-index scanner)))
+  (let ((index (1- (string-scanner-index scanner))))
+    (setf (values (string-scanner-line scanner)
+                 (string-scanner-column scanner))
+         (backtrack-position (char (string-scanner-string scanner) index)
+                             (string-scanner-line scanner)
+                             (string-scanner-column scanner))
+         (string-scanner-index scanner) index)))
+
+(defmethod scanner-filename ((scanner string-scanner))
+  (string-scanner-filename scanner))
+(defmethod scanner-line ((scanner string-scanner))
+  (string-scanner-line scanner))
+(defmethod scanner-column ((scanner string-scanner))
+  (string-scanner-column scanner))
+(defmethod file-location ((scanner string-scanner))
+  (make-file-location (string-scanner-filename scanner)
+                     (string-scanner-line scanner)
+                     (string-scanner-column scanner)))
 
 (defmethod scanner-capture-place ((scanner string-scanner))
   (string-scanner-index scanner))