blob: 19df9891c5f56e877dad159403a9abd1358ff3e7 (
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
52
53
54
55
56
57
58
59
60
61
62
63
|
* parzival
The quest of =parzival= is to make it fun and easy to build parsers that
consume streams and return common lisp values. E.g. A [[https://github.com/thegoofist/parzival/blob/master/examples/json-parzival.lisp][JSON]] parser or an HTTP
parser could both be written extremely succinctly in parzival.
In =parzival=, a *parser is a function* that accepts a *stream* and returns
three values:
1. A *parse result* (or =nil=), which is any value.
2. A *success indicator*, which is =t= or =nil=.
3. The possibly modified *stream* that was initially passed in.
** A neat example
What follows is a quick example of using =parzival= to build a parser for
simple arithmetic expressions. But first, you should be aware of two
*completely optional* naming conventions that =parzival= adopts.
1. Names beginning and ending in a =<= are *parsers*.
2. Names that begin with =<<= are *parser-combinators*, i.e. functions that
accept and return parsers.
#+begin_src lisp
;;; we want to parse + - / or * and result in a function that can be used do arithmetic on numbers
(defvar <op<
(<<bind (<<brackets <whitespace< (<<any-char "+-*/") <whitespace<)
(lambda (op-char)
(<<result
(case op-char
(#\+ #'+)
(#\- #'-)
(#\* #'*)
(t #'/))))))
(defvar <simple-expression<
(<<let ((arg1 <real<)
(op <op<)
(arg2 <real<))
(<<result (funcall op arg1 arg2))))
#+end_src
The above is "good enough" to parse simple expressions like "44.32 + 55" or
"88 / 11.11". E.g.
#+begin_src lisp
(parse "44.3 * 3" <simple-expression< t) ;; 132.9
#+end_src
** [0/4] To Do
1) [ ] Signal Conditions on Parse Failures from =parse= function
2) [ ] Related to (1), provide prettying-printing options for parse failures
3) [ ] Extend to support Binary stream parsers.
4) [ ] Complete Test Coverage
|