Creating a parser combinator library to parse JSON
Prev: seq | Contents | Next: many1, implemented |
I’m not sure how to implement many
, so I’ll start with something simpler. optional
matches zero or one things:
(def optional (parser) (fn (p) (iflet (p2 r) (parser p) ...)))
If the match succeeds, then I’ll want to return what the parser returned. Since I’m working towards many
, and I’ll want many
to return a list of the return values for each time the parser matches, I’ll have optional
return a list of the one return value:
(def optional (parser) (fn (p) (iflet (p2 r) (parser p) (return p2 (list r)) ...)))
If the parser doesn’t match, then the optional
still succeeds, since it matches zero or one things, so I’ll have it return the empty list:
(def optional (parser) (fn (p) (iflet (p2 r) (parser p) (return p2 (list r)) (return p nil))))
arc> (show-parse (optional json-number-char) "123") returning: (#\1) remaining: 23 nilarc> (show-parse (optional json-number-char) "a123") returning: nil remaining: a123 nil
So many
is like optional
, except that it applies the parser to the input over and over again until finally the match fails:
(def many (parser) (fn (p) ((afn (p a) (iflet (s2 r) (parser p) (self s2 (cons r a)) (return p rev.a))) p nil)))
arc> (show-parse (many json-number-char) "abc") returning: nil remaining: abc nilarc> (show-parse (many json-number-char) "1abc") returning: (#\1) remaining: abc nilarc> (show-parse (many json-number-char) "12abc") returning: (#\1 #\2) remaining: abc nilarc> (show-parse (many json-number-char) "123abc") returning: (#\1 #\2 #\3) remaining: abc nil
Prev: seq | Contents | Next: many1, implemented |
Questions? Comments? Email me andrew.wilcox [at] gmail.com