about summary refs log tree commit diff stats
path: root/clex.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'clex.lisp')
-rw-r--r--clex.lisp41
1 files changed, 41 insertions, 0 deletions
diff --git a/clex.lisp b/clex.lisp
new file mode 100644
index 0000000..52eb822
--- /dev/null
+++ b/clex.lisp
@@ -0,0 +1,41 @@
+(defclass <string-lexer> () ((string :initarg :s :accessor string)
+                             (current :initform 0 :accessor current)
+                             (size :accessor size)))
+
+(defmethod initialize-object :after ((self <string-lexer>) initargs)
+   (setf (size self) (length (str self))))
+
+(defgeneric forward (cl &rest args))
+(defmethod forward ((cl <string-lexer>) &rest args)
+   (let ((incr (if (null args)
+                   1
+                   (car args))))
+        (setf (curr cl) (+ (curr cl) incr))))
+
+(defgeneric extract (pred cl))
+(defmethod extract (pred (cl <string-lexer>))
+   (let* ((st (string cl))
+          (pos (current cl))
+          (ext (lambda (n)
+                  (if (and (< n (size cl)) (pred (elt st n)))
+                      (ext (+ n 1))
+                      n)))
+          (res (ext pos)))
+         (setf (current cl) res)
+         (subseq (string cl) pos (- res pos))))
+
+(defgeneric extract-int (cl))
+(defmethod extract-int ((cl <string-lexer>))
+  ;; TODO: flet?
+  (let ((is-int (lambda (x)
+                  (and (char>= x #\0) (char<= x #\9)))))
+    (convert (extract is-int cl) <number>)))
+
+(defgeneric extract-ident (cl))
+(defmethod extract-ident ((cl <string-lexer>))
+  (let ((is-alpha-num (lambda (x)
+                        (or (and (char>= x #\a) (char<= x #\z))
+                          (and (char>= x #\A) (char<= x #\Z))
+                          (and (char>= x #\0) (char<= x #\9))
+                          (char= x #\_)))))
+    (extract is-alpha-num)))