(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))))