summaryrefslogtreecommitdiff
path: root/core.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'core.lisp')
-rw-r--r--core.lisp62
1 files changed, 28 insertions, 34 deletions
diff --git a/core.lisp b/core.lisp
index 3b06936..6e4bf6e 100644
--- a/core.lisp
+++ b/core.lisp
@@ -1,17 +1,8 @@
(in-package #:monparser)
-(defun opposite (p)
- (lambda (input &key lazy)
- (let ((result (funcall p input)))
- (cond ((parsing-p result)
- (make-failure :place input :message "Unexpected match."))
- ((failure-p result)
- (make-parsing :tree nil :left input))
- (t (error "Unexpected result type."))))))
-
-(defun fail (message)
- (lambda (input &key lazy)
- (make-failure :place input :message message)))
+(defun fail (message &key (priority 1))
+ (lambda (input)
+ (make-failure :place input :message message :priority priority)))
(defmacro unit (&optional predicate)
(cond ((null predicate)
@@ -29,44 +20,47 @@
(and (symbolp x)
(string-equal (symbol-name x) "IT"))) predicate))))
(t (error (format nil "Invalid predicate: ~a." predicate))))
- `(lambda (input &key lazy)
- (declare (ignore lazy))
+ `(lambda (input)
(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))))
+ :message (format nil "Expected: ~a, Got: ~:c." ',predicate it))))
(make-failure :place input
- :message (format nil "Reached end of input. Expected: ~a" ',predicate)))))
+ :message (format nil "Reached end of input. Expected: ~a." ',predicate)))))
+
+(defparameter end
+ (lambda (input)
+ (if (has-data? input)
+ (make-failure :place input :message "Didn't reach end of input.")
+ (make-parsing :tree nil :left input))))
-(defun lazily-select-parser (input parsers)
- (let ((intermediate-parsers '())
- (result (make-failure :place input
- :message "Exhausted options.")))
+(defun select-parser (input parsers)
+ (let ((result (make-failure :place input)))
(dolist (p parsers)
- (let ((r (funcall p
- input
- :lazy (> (length parsers) 1))))
- (cond ((functionp r)
- (push r intermediate-parsers))
- ((parsing-p r)
+ (let ((r (funcall p input)))
+ (cond ((parsing-p r)
(when (or (not (parsing-p result))
(> (input-cursor (parsing-left r))
(input-cursor (parsing-left result))))
(setf result r)))
((failure-p r)
(when (failure-p result)
- (setf result r)))
- (t (error (format nil "Invalid return value: ~a" r))))))
- (if intermediate-parsers
- (lazily-select-parser input intermediate-parsers)
- result)))
+ (let ((priority-cmp (- (failure-priority r)
+ (failure-priority result))))
+ (when (or (> priority-cmp 0)
+ (and (= priority-cmp 0)
+ (>= (input-cursor (failure-place r))
+ (input-cursor (failure-place result)))))
+ (setf result r)))))
+ (t (error (format nil "Invalid return value: ~a." r))))))
+ result))
(defmacro one-of (first-parser second-parser &rest other-parsers)
- `(lambda (input &key lazy)
- (declare (ignore lazy))
- (lazily-select-parser input (list ,first-parser ,second-parser ,@other-parsers))))
+ `(lambda (input)
+ (select-parser input
+ (list ,first-parser ,second-parser ,@other-parsers))))
;;; TODO: Find a way to be able to use the input without needing to define a name for it.
(defmacro comp (bindings &body body)