A Parsec-style parser combinator library for Carp.
(load "git@github.com:carpentry-org/parsec@0.2.0")(let [p (Parser.between (Parser.byte \[)
(Parser.byte \])
(Parser.Lexer.integer))]
(match (Parser.parse p "[42]")
(Result.Success n) (println* &n)
(Result.Error e) (IO.errorln &(Parser.format-error &e))))Parser.parse is strict, the parser must consume the whole input.
For a step-by-step walk-through building an arithmetic expression parser from scratch, see the tutorial. For caveats and idioms, see pitfalls. The full API reference is generated from the source and lives at the carpentry.
Alternation follows Parsec semantics: (Parser.alt p q) only tries
q when p fails without consuming. To allow backtracking after
p has consumed, wrap it in Parser.try:
(Parser.alt
(Parser.try (Parser.string @"foobar"))
(Parser.string @"foobaz"))Parser.string is atomic: a partial mismatch fails empty without
needing try.
Use Parser.recurse against a Parser.placeholder-initialized cell.
Declare the recursive grammar in a top-level def, set! it once at
startup, reference it from sub-parsers:
(def *sexp* (the (Parser SExp) (Parser.placeholder)))
(defn list-p []
(Parser.between (Parser.byte \()
(Parser.byte \))
(Parser.many (Parser.recurse &*sexp*))))
(defn init-grammar []
(set! *sexp* (Parser.alt (sym-p) (list-p))))Parser.lazy is also available for small one-off grammars but
rebuilds the parser tree on every call.
kv.carpis a key-value config parserlisp.carpare s-expressions with a recursiveBoxASTarith.carpis an arithmetic expression evaluator with operator precedence and parens
For a full Carp source-form reader built on parsec — atoms, compound
forms, reader macros, and first-class comments — see
carpentry-org/carp-reader.
Have fun!