summaryrefslogtreecommitdiff
path: root/cursor.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'cursor.lisp')
-rw-r--r--cursor.lisp82
1 files changed, 58 insertions, 24 deletions
diff --git a/cursor.lisp b/cursor.lisp
index 72d4c90..a4cc100 100644
--- a/cursor.lisp
+++ b/cursor.lisp
@@ -1,40 +1,74 @@
(in-package #:monparser)
-(defclass cursor ()
- ((index :type (unsigned-byte 44) :initarg :index :accessor index :initform 0)
- (data :type simple-string :initarg :data :reader data :initform "")))
+(defstruct cursor
+ (start 0 :type (unsigned-byte 44))
+ (end 0 :type (unsigned-byte 44))
+ (data "" :type simple-string))
-(defun has-data? (cursor)
- (< (index cursor) (length (data cursor))))
+(declaim (ftype (function (cursor) boolean) cursor-has-data?))
+(defun cursor-has-data? (cursor)
+ (< (cursor-end cursor) (length (cursor-data cursor))))
-(defun peek (cursor)
- (char (data cursor)
- (index cursor)))
+(declaim (ftype (function (cursor) boolean) cursor-at-start?))
+(defun cursor-at-start? (cursor)
+ (= (cursor-start cursor) (cursor-end cursor)))
-(defun advance (cursor)
- (make-instance 'cursor
- :data (data cursor)
- :index (+ (index cursor) 1)))
+(declaim (ftype (function (cursor) standard-char) cursor-peek))
+(defun cursor-peek (cursor)
+ (char (cursor-data cursor)
+ (cursor-end cursor)))
+(declaim (ftype (function (cursor) cursor) cursor-advance))
+(defun cursor-advance (cursor)
+ (make-cursor :data (cursor-data cursor)
+ :start (cursor-start cursor)
+ :end (+ (cursor-end cursor) 1)))
+
+(declaim (ftype (function (cursor) cursor) cursor-rebase))
+(defun cursor-rebase (cursor)
+ (make-cursor :data (cursor-data cursor)
+ :start (cursor-end cursor)
+ :end (cursor-end cursor)))
+
+(declaim (ftype (function (cursor cursor) cursor) cursor-merge))
+(defun cursor-merge (prev next)
+ (assert (eq (cursor-data prev) (cursor-data next)))
+ (make-cursor :data (cursor-data next)
+ :start (cursor-start prev)
+ :end (cursor-end next)))
+
+(declaim (ftype (function (cursor cursor) fixnum) distance))
(defun distance (from to)
- (- (index to)
- (index from)))
+ (assert (eq (cursor-data from) (cursor-data to)))
+ (- (cursor-end to)
+ (cursor-end from)))
-(defun context-window (str index &key (side-length 20))
- (let ((begin (max (- index side-length) 0))
- (end (min (+ index side-length) (length str)))
+(declaim (ftype (function (cursor &key (:side-length fixnum)) t) context-window))
+(defun context-window (cursor &key (side-length 20))
+ (let ((begin (max (- (cursor-start cursor) side-length) 0))
+ (end (min (+ (cursor-end cursor) side-length) (length (cursor-data cursor))))
(result '()))
- (push (subseq str (1+ index) end) result)
- (push (elt str index) result)
- (push (subseq str begin index) result)
+ (push (subseq (cursor-data cursor) (cursor-end cursor) end) result)
+ (push (subseq (cursor-data cursor) (cursor-start cursor) (cursor-end cursor)) result)
+ (push (subseq (cursor-data cursor) begin (cursor-start cursor)) result)
result))
+(declaim (ftype (function (cursor) (cons fixnum fixnum)) line-and-column))
+(defun line-and-column (cursor)
+ (let ((line 1) (column 1))
+ (dotimes (i (cursor-end cursor))
+ (let ((c (char (cursor-data cursor) i)))
+ (case c
+ (#\Newline
+ (incf line)
+ (setf column 1))
+ (t (incf column)))))
+ (cons line column)))
+
(defmethod print-object ((obj cursor) stream)
(print-unreadable-object (obj stream :type t)
- (let ((str (if (has-data? obj)
+ (let ((str (if (cursor-has-data? obj)
(format nil "~{~a~a~a~}"
- (context-window (data obj)
- (index obj)
- :side-length 10))
+ (context-window obj :side-length 10))
"END OF DATA")))
(format stream "~s" (substitute #\~ #\Newline str)))))