summaryrefslogtreecommitdiff
path: root/parser.lisp
diff options
context:
space:
mode:
authorJuan Manuel Tomás <jtomas1815@gmail.com>2024-10-12 03:30:25 -0300
committerJuan Manuel Tomás <jtomas1815@gmail.com>2024-10-12 03:30:25 -0300
commit1a9fd29b92c9516c84d32b5d6b1c5195c7a03bd6 (patch)
treebeade86447c3bbe89c3157f6684092850d31ccac /parser.lisp
parentaa7e4052fd22361ecf346ae1a2f6f30db0202c5c (diff)
downloadmonparser-1a9fd29b92c9516c84d32b5d6b1c5195c7a03bd6.tar.gz
monparser-1a9fd29b92c9516c84d32b5d6b1c5195c7a03bd6.zip
First full implementation of lazy binding in comp
Diffstat (limited to 'parser.lisp')
-rw-r--r--parser.lisp51
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)