summaryrefslogtreecommitdiff
path: root/parser.lisp
diff options
context:
space:
mode:
authorJuan Manuel Tomás <jtomas1815@gmail.com>2024-10-05 00:09:29 -0300
committerJuan Manuel Tomás <jtomas1815@gmail.com>2024-10-05 00:09:29 -0300
commitbb97077120cfa3966f0d43a7a1447d87ef8c818c (patch)
tree1bbb085d8707a8e31dc4656469ffcf4ad89e2c07 /parser.lisp
parent33518551e019f4dab7d95c9390c66b6b8b2339f2 (diff)
downloadmonparser-bb97077120cfa3966f0d43a7a1447d87ef8c818c.tar.gz
monparser-bb97077120cfa3966f0d43a7a1447d87ef8c818c.zip
Evaluate one-of parsers lazily
Diffstat (limited to 'parser.lisp')
-rw-r--r--parser.lisp70
1 files changed, 40 insertions, 30 deletions
diff --git a/parser.lisp b/parser.lisp
index ca13598..2fe6f67 100644
--- a/parser.lisp
+++ b/parser.lisp
@@ -28,31 +28,41 @@
(format stream "~a: ~a" (cursor (failure-place obj)) (failure-message obj)))))
(defun new (tree)
- (lambda (input)
+ (lambda (input &optional lazy)
+ (declare (ignore lazy))
(make-parsing :tree tree :left input)))
(defun bind-with-input (p f)
- (lambda (input)
+ (lambda (input &optional lazy)
(let ((r (funcall p input)))
(if (parsing-p r)
- (funcall (the function (funcall f (parsing-tree r) input))
- (parsing-left r))
+ (if lazy
+ (lambda (ignored-input &optional lazy)
+ (declare (ignore ignored-input))
+ (funcall (funcall f (parsing-tree r) input) (parsing-left r) lazy))
+ (funcall (funcall f (parsing-tree r) input) (parsing-left r)))
r))))
(defun bind (p f)
- (lambda (input)
+ (lambda (input &optional lazy)
(let ((r (funcall p input)))
(if (parsing-p r)
- (funcall (the function (funcall f (parsing-tree r)))
- (parsing-left r))
+ (if lazy
+ (lambda (ignored-input &optional lazy)
+ (declare (ignore ignored-input))
+ (funcall (funcall f (parsing-tree r)) (parsing-left r) lazy))
+ (funcall (funcall f (parsing-tree r)) (parsing-left r)))
r))))
(defun discarding-bind (p f)
- (lambda (input)
+ (lambda (input &optional lazy)
(let ((r (funcall p input)))
(if (parsing-p r)
- (funcall (the function (funcall f))
- (parsing-left r))
+ (if lazy
+ (lambda (ignored-input &optional lazy)
+ (declare (ignore ignored-input))
+ (funcall (funcall f) (parsing-left r) lazy))
+ (funcall (funcall f) (parsing-left r)))
r))))
(defmacro comp (bindings &body body)
@@ -70,25 +80,23 @@
`(bind-with-input ,p (lambda (,(car v) ,(cdr v)) (comp ,(cdr bindings) ,@body)))
(error "Binding name/(name,input) must be either a symbol or a cons of symbols."))))))
-(defun crit (p)
- (lambda (input)
- (let ((r (funcall p input)))
- (if (parsing-p r)
- r
- (error (format nil "~a" r))))))
-
(defun one-of (first-parser second-parser &rest other-parsers)
- (lambda (input)
- (labels ((one-of-rec (parsers failures)
- (if (car parsers)
- (let ((r (funcall (car parsers) input)))
- (cond ((failure-p r)
- (one-of-rec (cdr parsers) (cons r failures)))
- ((listp r)
- (one-of-rec (cdr parsers) (append r failures)))
- (t r)))
- failures)))
- (one-of-rec (cons first-parser (cons second-parser other-parsers)) nil))))
+ (lambda (input &optional lazy)
+ (declare (ignore lazy))
+ (labels ((one-of-rec (parsers)
+ (let ((intermediate-parsers '())
+ (result (make-failure :place input
+ :message "Exausted options.")))
+ (dolist (p parsers)
+ (let ((r (funcall p input (> (length parsers) 1))))
+ (cond ((functionp r)
+ (push r intermediate-parsers))
+ ((parsing-p r)
+ (setf result r)))))
+ (if intermediate-parsers
+ (one-of-rec intermediate-parsers)
+ result))))
+ (one-of-rec (cons first-parser (cons second-parser other-parsers))))))
(defmacro unit (&optional predicate)
(cond ((null predicate)
@@ -102,7 +110,8 @@
(lambda (x)
(and (symbolp x)
(string-equal (symbol-name x) "IT"))) predicate))))
- `(lambda (input)
+ `(lambda (input &optional lazy)
+ (declare (ignore lazy))
(if (has-data? input)
(let ((it (peek input)))
(if ,predicate
@@ -112,7 +121,8 @@
(make-failure :place input :message "Reached end of input."))))
(defun literal (target)
- (lambda (input)
+ (lambda (input &optional lazy)
+ (declare (ignore lazy))
(if (has-data? input)
(if (prefix? target input)
(make-parsing :tree target :left (advance input (length target)))