forked from Ramarren/cl-parser-combinators
-
Notifications
You must be signed in to change notification settings - Fork 1
/
primitives.lisp
51 lines (46 loc) · 1.72 KB
/
primitives.lisp
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 :parser-combinators)
;;; primitive parsers
(declaim (inline result))
(defun result (v)
"Primitive parser: return v, leaves input unmodified."
#'(lambda (inp)
(let ((closure-value (make-instance 'parser-possibility
:tree v :suffix inp)))
#'(lambda ()
(when closure-value
(prog1
closure-value
(setf closure-value nil)))))))
(defun zero ()
"Primitive parser: parsing failure"
(constantly nil))
(def-cached-parser item
"Primitive parser: consume item from input and return it."
#'(lambda (inp)
(typecase inp
(end-context (constantly nil))
(context
(let ((closure-value (make-instance 'parser-possibility
:tree (context-peek inp) :suffix (context-next inp))))
#'(lambda ()
(when closure-value
(prog1
closure-value
(setf closure-value nil)))))))))
(defun force? (parser)
"Parser modifier: fully realize result from parser"
#'(lambda (inp)
(let ((continuation (funcall parser inp)))
(let ((all-results (iter (for result = (funcall continuation))
(while result)
(collect result))))
#'(lambda ()
(when all-results
(pop all-results)))))))
(defmacro delayed? (parser)
"Parser modifier macro: parser will be built when called. This is necessary for left-recursive parsers."
`(let ((parser-cache nil))
#'(lambda (inp)
(unless parser-cache
(setf parser-cache ,parser))
(funcall parser-cache inp))))