summaryrefslogtreecommitdiff
path: root/base.lisp
blob: 82063227f965452552355731451ccbd873af7159 (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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
(in-package #:monparser)

(defstruct parsing
  tree
  left
  limit)

(defstruct failure
  place
  message)

(defun lazy-parsing-p (r)
  (or (functionp r)
      (parsing-p r)))

(defun new (tree)
  (lambda (input &key limit lazy)
    (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 :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 (lazy-parsing-p (funcall next-parser sweep-input :lazy t))
              (setf limit (cursor-distance sweep-input input))))
          (if (< limit 0)
            (setf r (make-failure :place input
                                  :message "Reached end of input while sweeping."))
            (setf r (funcall p input :limit limit)))))
      (if (parsing-p r)
        (if lazy
          (lambda (ignored-input &key lazy limit)
            (declare (ignore ignored-input limit))
            (funcall (funcall f (parsing-tree r) input)
                     (parsing-left r)
                     :lazy lazy
                     :limit (if greedy (parsing-limit r))))
          (funcall (funcall f (parsing-tree r) input)
                   (parsing-left r)
                   :limit (if greedy (parsing-limit r))))
      r))))