summaryrefslogtreecommitdiff
path: root/base.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'base.lisp')
-rw-r--r--base.lisp51
1 files changed, 51 insertions, 0 deletions
diff --git a/base.lisp b/base.lisp
new file mode 100644
index 0000000..8206322
--- /dev/null
+++ b/base.lisp
@@ -0,0 +1,51 @@
+(in-package #:monparser)
+
+(defstruct parsing
+ tree
+ left
+ limit)
+
+(defstruct failure
+ place
+ message)
+
+(defun lazy-parsing-p (r)
+ (or (functionp r)
+ (parsing-p r)))
+
+(defun new (tree)
+ (lambda (input &key limit lazy)
+ (declare (ignore lazy))
+ (if (and limit (> limit 0))
+ (make-failure :place input
+ :message (format nil "Didn't reach expected limit: ~a." limit))
+ (make-parsing :tree tree :left input))))
+
+(defun bind (p f &key (greedy t))
+ (lambda (input &key limit lazy)
+ (let (r)
+ (if greedy
+ (setf r (funcall p input :limit limit))
+ (let ((next-parser (funcall f nil input))
+ (limit -1))
+ (do ((sweep-input input (advance sweep-input)))
+ ((or (not (has-data? sweep-input))
+ (> limit -1)) nil)
+ (when (lazy-parsing-p (funcall next-parser sweep-input :lazy t))
+ (setf limit (cursor-distance sweep-input input))))
+ (if (< limit 0)
+ (setf r (make-failure :place input
+ :message "Reached end of input while sweeping."))
+ (setf r (funcall p input :limit limit)))))
+ (if (parsing-p r)
+ (if lazy
+ (lambda (ignored-input &key lazy limit)
+ (declare (ignore ignored-input limit))
+ (funcall (funcall f (parsing-tree r) input)
+ (parsing-left r)
+ :lazy lazy
+ :limit (if greedy (parsing-limit r))))
+ (funcall (funcall f (parsing-tree r) input)
+ (parsing-left r)
+ :limit (if greedy (parsing-limit r))))
+ r))))