(in-package #:monparser) (defclass text () ((index :type (unsigned-byte 44) :initarg :index :accessor index :initform 0) (data :type simple-string :initarg :data :reader data :initform ""))) (defun has-data? (cursor) (< (index cursor) (length (data cursor)))) (defun peek (cursor) (char (data cursor) (index cursor))) (defun advance (cursor) (make-instance 'text :data (data cursor) :index (+ (index cursor) 1))) (defun distance (from to) (- (index to) (index from))) (defun context-window (str index &key (side-length 20)) (let ((begin (max (- index side-length) 0)) (end (min (+ index side-length) (length str))) (result '())) (push (subseq str (1+ index) end) result) (push (elt str index) result) (push (subseq str begin index) result) result)) (defmethod print-object ((obj text) stream) (print-unreadable-object (obj stream :type t) (let ((str (if (has-data? obj) (format nil "~{~a~a~a~}" (context-window (data obj) (index obj) :side-length 10)) "END OF DATA"))) (format stream "~s" (substitute #\~ #\Newline str)))))