Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 83 lines (74 sloc) 3.275 kB
f5e912f @Ramarren Plurarize combinators in system/package name
authored
1 (in-package :parser-combinators)
d9a26fb @Ramarren Split basic.lisp
authored
2
3 ;;; emulating monads... did I even understand those?
4 ;;; bind :: Parser a -> (a -> Parser b) -> Parser b
5 ;;; (parser-tree1 function-from-tree1-to-parser-tree2)=>parser-tree2
8dec19a @Ramarren Use proper apostrophe marks in comment
authored
6 ;;; p `bind` f = \inp -> concat [f v inp' | (v,inp') <- p inp]
d9a26fb @Ramarren Split basic.lisp
authored
7 ;;; (bind p f inp)=(concat list-comprehension)
8
084e587 @Ramarren Remove unnecesary laziness layer. Replace with `delayed?` macro to us…
authored
9 (defun execute-bind (inp parser parser-generator) ;return continuation function
a1c55d9 @Ramarren Make vectors and characters accepted as parsers.
authored
10 (with-parsers (parser)
11 (let ((p-parse-continuation (funcall parser inp))
12 (q-parse-continuation nil))
13 #'(lambda ()
14 (let ((result nil))
15 (iter (when q-parse-continuation (setf result (funcall q-parse-continuation)))
16 (until (or result
17 (and (null p-parse-continuation)
18 (null q-parse-continuation))))
19 (unless result
20 (setf q-parse-continuation
21 (let ((p-next-result
22 (funcall p-parse-continuation)))
23 (if p-next-result
24 (let ((v (tree-of p-next-result))
25 (inp-prime (suffix-of p-next-result)))
26 (funcall (ensure-parser (funcall parser-generator v)) inp-prime))
27 (setf p-parse-continuation nil))))))
28 result)))))
d9a26fb @Ramarren Split basic.lisp
authored
29
2107f2d @Ramarren Core combinators do not have to be macros.
authored
30 (defun bind (parser parser-generator)
31 #'(lambda (inp)
32 (execute-bind inp
33 parser
34 parser-generator)))
d9a26fb @Ramarren Split basic.lisp
authored
35
36 (defun execute-choice (inp parser1 parser2)
f8b73b2 @Ramarren Eliminate unnecesary intermediate parse results objects
authored
37 (let ((continuation-1 (funcall parser1 inp))
38 (continuation-2 nil))
290aeb1 @Ramarren Implement lazy results.
authored
39 #'(lambda ()
f8b73b2 @Ramarren Eliminate unnecesary intermediate parse results objects
authored
40 (cond (continuation-1
41 (let ((result (funcall continuation-1)))
ae52aad @Ramarren Untabify and whitespace cleanup.
authored
42 (unless result
f8b73b2 @Ramarren Eliminate unnecesary intermediate parse results objects
authored
43 (setf continuation-1 nil)
44 (setf continuation-2 (funcall parser2 inp))
45 (setf result (funcall continuation-2)))
ae52aad @Ramarren Untabify and whitespace cleanup.
authored
46 result))
f8b73b2 @Ramarren Eliminate unnecesary intermediate parse results objects
authored
47 (continuation-2
48 (let ((result (funcall continuation-2)))
ae52aad @Ramarren Untabify and whitespace cleanup.
authored
49 (unless result
f8b73b2 @Ramarren Eliminate unnecesary intermediate parse results objects
authored
50 (setf continuation-2 nil))
51 result))
ae52aad @Ramarren Untabify and whitespace cleanup.
authored
52 (t nil)))))
d9a26fb @Ramarren Split basic.lisp
authored
53
2107f2d @Ramarren Core combinators do not have to be macros.
authored
54 (defun choice (parser1 parser2)
d9a26fb @Ramarren Split basic.lisp
authored
55 "Combinator: all alternatives from two parsers"
2107f2d @Ramarren Core combinators do not have to be macros.
authored
56 (let ((parser1 (ensure-parser parser1))
57 (parser2 (ensure-parser parser2)))
084e587 @Ramarren Remove unnecesary laziness layer. Replace with `delayed?` macro to us…
authored
58 #'(lambda (inp)
f8b73b2 @Ramarren Eliminate unnecesary intermediate parse results objects
authored
59 (execute-choice inp parser1 parser2))))
d9a26fb @Ramarren Split basic.lisp
authored
60
2107f2d @Ramarren Core combinators do not have to be macros.
authored
61 (defun choice1 (parser1 parser2)
d9a26fb @Ramarren Split basic.lisp
authored
62 "Combinator: one alternative from two parsers"
2107f2d @Ramarren Core combinators do not have to be macros.
authored
63 (let ((parser1 (ensure-parser parser1))
64 (parser2 (ensure-parser parser2)))
65 (define-oneshot-result inp is-unread
66 (funcall (execute-choice inp
67 parser1
68 parser2)))))
d9a26fb @Ramarren Split basic.lisp
authored
69
2107f2d @Ramarren Core combinators do not have to be macros.
authored
70 (defun choices (&rest parser-list)
d9a26fb @Ramarren Split basic.lisp
authored
71 "Combinator: all alternatives from multiple parsers"
084e587 @Ramarren Remove unnecesary laziness layer. Replace with `delayed?` macro to us…
authored
72 (if (cdr parser-list)
2107f2d @Ramarren Core combinators do not have to be macros.
authored
73 (choice (car parser-list)
74 (apply #'choices (cdr parser-list)))
084e587 @Ramarren Remove unnecesary laziness layer. Replace with `delayed?` macro to us…
authored
75 (car parser-list)))
d9a26fb @Ramarren Split basic.lisp
authored
76
2107f2d @Ramarren Core combinators do not have to be macros.
authored
77 (defun choices1 (&rest parser-list)
d9a26fb @Ramarren Split basic.lisp
authored
78 "Combinator: one alternative from multiple parsers"
2107f2d @Ramarren Core combinators do not have to be macros.
authored
79 (define-oneshot-result inp is-unread
80 (iter (for p in parser-list)
81 (for result = (funcall (funcall (ensure-parser p) inp)))
82 (thereis result))))
Something went wrong with that request. Please try again.