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