summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Manuel Tomás <jtomas1815@gmail.com>2022-12-04 23:57:17 -0300
committerJuan Manuel Tomás <jtomas1815@gmail.com>2022-12-04 23:57:17 -0300
commitcdbfa453e870756dc32785b23a934b37e28d071c (patch)
treec04629d9c30911f2312718fc95212eb10ef7ecee
parentf205d4c5dbd0ccb26cb9020e3ef8ae86d1336403 (diff)
downloadmonparser-cdbfa453e870756dc32785b23a934b37e28d071c.tar.gz
monparser-cdbfa453e870756dc32785b23a934b37e28d071c.zip
First advances to lookahead implementation
-rw-r--r--input.lisp15
-rw-r--r--parser.lisp26
2 files changed, 32 insertions, 9 deletions
diff --git a/input.lisp b/input.lisp
index 3e646b4..4f803ec 100644
--- a/input.lisp
+++ b/input.lisp
@@ -5,17 +5,22 @@
(file nil :read-only t)
(data nil :read-only t))
-(defun has-data? (input)
- (< (input-cursor input)
+(defun has-data? (input &optional (window-size 1))
+ (< (+ window-size -1 (input-cursor input))
(length (input-data input))))
-(defun element (input)
+(defun peek-1 (input)
(char (input-data input)
(input-cursor input)))
-(defun advance (input)
+(defun peek-n (input window-size)
+ (subseq (input-data input)
+ (input-cursor input)
+ window-size))
+
+(defun advance (input &optional (amount 1))
(let ((new-input (copy-structure input)))
- (incf (input-cursor new-input))
+ (incf (input-cursor new-input) amount)
new-input))
(declaim (ftype (function (simple-string) (values input &optional)) from-string))
diff --git a/parser.lisp b/parser.lisp
index 04d3f2b..a1ef1a8 100644
--- a/parser.lisp
+++ b/parser.lisp
@@ -33,7 +33,7 @@
(lambda (input)
(make-critical-failure :place input :message message)))
-(defun either (first-parser &rest other-parsers)
+(defun either (first-parser second-parser &rest other-parsers)
(lambda (input)
(labels ((either-rec (body)
(if (cdr body)
@@ -42,17 +42,26 @@
(either-rec (cdr body))
r))
(funcall (car body) input))))
- (either-rec (cons first-parser other-parsers)))))
+ (either-rec (cons first-parser (cons second-parser other-parsers))))))
(defun unit (&optional (predicate #'characterp))
(lambda (input)
(if (input::has-data? input)
- (let ((c (input::element input)))
+ (let ((c (input::peek-1 input)))
(if (funcall predicate c)
(make-parsing :tree c :left (input::advance input))
(make-normal-failure :place input :message "Predicate not satisfied.")))
(make-normal-failure :place input :message "Reached end of input."))))
+(defun literal (predicate)
+ (lambda (input)
+ (if (input::has-data? input (length predicate))
+ (let ((str (input::peek-n input (length predicate))))
+ (if (string= predicate str)
+ (make-parsing :tree str :left (input::advance input (length predicate)))
+ (make-normal-failure :place input :message "Predicate not satisfied.")))
+ (make-normal-failure :place input :message "Reached end of input."))))
+
(defmacro comp (bindings &body body)
(if (null bindings)
`(new (progn ,@body))
@@ -65,7 +74,7 @@
(defparameter nothing
(new nil))
-(defun zero-or-one (p)
+(defun optional (p)
(either p nothing))
(defun zero-or-more (p)
@@ -78,3 +87,12 @@
(comp ((x p)
(xs (zero-or-more p)))
(cons x xs)))
+
+(defun separated-list (p separator)
+ (comp ((v p)
+ (sep (optional (the-char separator)))
+ (vn (if sep
+ (either (separated-list p separator)
+ (fail "Value expected."))
+ nothing)))
+ (cons v vn)))