diff options
author | Juan Manuel Tomás <jtomas1815@gmail.com> | 2024-10-12 03:30:25 -0300 |
---|---|---|
committer | Juan Manuel Tomás <jtomas1815@gmail.com> | 2024-10-12 03:30:25 -0300 |
commit | 1a9fd29b92c9516c84d32b5d6b1c5195c7a03bd6 (patch) | |
tree | beade86447c3bbe89c3157f6684092850d31ccac /parser.lisp | |
parent | aa7e4052fd22361ecf346ae1a2f6f30db0202c5c (diff) | |
download | monparser-1a9fd29b92c9516c84d32b5d6b1c5195c7a03bd6.tar.gz monparser-1a9fd29b92c9516c84d32b5d6b1c5195c7a03bd6.zip |
First full implementation of lazy binding in comp
Diffstat (limited to 'parser.lisp')
-rw-r--r-- | parser.lisp | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/parser.lisp b/parser.lisp index 9d4be57..4120253 100644 --- a/parser.lisp +++ b/parser.lisp @@ -17,6 +17,10 @@ left limit) +(defun lazy-parsing-p (r) + (or (functionp r) + (parsing-p r))) + (defstruct failure place message) @@ -30,20 +34,23 @@ (defun new (tree) (lambda (input &key limit lazy) - (declare (ignore lazy limit)) - (make-parsing :tree tree :left input))) + (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)) + (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 (functionp (funcall next-parser sweep-input :lazy t)) + (when (lazy-parsing-p (funcall next-parser sweep-input :lazy t)) (setf limit (input-sub sweep-input input)))) (if (< limit 0) (setf r (make-failure :place input @@ -51,16 +58,16 @@ (setf r (funcall p input :limit limit))))) (if (parsing-p r) (if lazy - (lambda (ignored-input &key lazy inner-limit) - (declare (ignore ignored-input inner-limit)) + (lambda (ignored-input &key lazy limit) + (declare (ignore ignored-input limit)) (funcall (funcall f (parsing-tree r) input) (parsing-left r) :lazy lazy - :limit (parsing-limit r))) + :limit (if greedy (parsing-limit r)))) (funcall (funcall f (parsing-tree r) input) (parsing-left r) - :limit (parsing-limit r))) - r)))) + :limit (if greedy (parsing-limit r)))) + r)))) (defmacro comp (bindings &body body) (if (null bindings) @@ -91,12 +98,15 @@ (defun one-of (first-parser second-parser &rest other-parsers) (lambda (input &key limit lazy) - (declare (ignore lazy limit)) + (declare (ignore lazy)) (labels ((one-of-rec (parsers) (let ((intermediate-parsers '()) (result nil)) (dolist (p parsers) - (let ((r (funcall p input :lazy (> (length parsers) 1)))) + (let ((r (funcall p + input + :lazy (> (length parsers) 1) + :limit limit))) (cond ((functionp r) (push r intermediate-parsers)) ((parsing-p r) @@ -126,14 +136,17 @@ (and (symbolp x) (string-equal (symbol-name x) "IT"))) predicate)))) `(lambda (input &key limit lazy) - (declare (ignore lazy limit)) - (if (has-data? input) - (let ((it (peek input))) - (if ,predicate - (make-parsing :tree it :left (advance input)) - (make-failure :place input - :message (format nil "Expected: ~a, Got: ~a" ',predicate it)))) - (make-failure :place input :message "Reached end of input.")))) + (declare (ignore lazy)) + (format t "unit limit ~a~&" limit) + (if (and limit (<= limit 0)) + (make-failure :place input :message "Reached established limit.") + (if (has-data? input) + (let ((it (peek input))) + (if ,predicate + (make-parsing :tree it :left (advance input) :limit (if limit (1- limit))) + (make-failure :place input + :message (format nil "Expected: ~a, Got: ~a" ',predicate it)))) + (make-failure :place input :message "Reached end of input."))))) (defun literal (target) (lambda (input &key limit lazy) |