summaryrefslogtreecommitdiff
path: root/quant.lisp
blob: bdd0cfcac5b0b82a91240dd7f3bbc70ca8ac6962 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(in-package #:monparser)

(defparameter nothing
  (new nil))

(defun optional (p)
  (one-of p nothing))

(defun many (p &key all)
  (lambda (input)
    (let* ((result '())
           (last-failure
             (do ((r (funcall p input) (funcall p input))) ((failure-p r) r)
               (when (parsing-p r)
                 (setf input (parsing-left r))
                 (when (parsing-tree r)
                   (push (parsing-tree r) result))))))
      (if (or (not result)
              (and result all (has-data? (failure-place last-failure))))
        (make-failure :place input :message (failure-message last-failure))
        (make-parsing :tree (reverse result) :left input)))))

; TODO: Need to be redone in a non-recursive way
(defun repeat (p min &optional (max 0))
  (if (> min 0)
    (comp ((x p)
           (xs (repeat p (1- min) (1- max))))
      (cons x xs))
    (if (> max 0)
      (comp ((x (optional p))
             (xs (repeat p 0 (if x (1- max) 0))))
        (if x (cons x xs) x))
      nothing)))