A parser combinator library for Go that makes parsing text intuitive and maintainable. Stop wrestling with regex and start writing parsers that read like natural grammar.
Inspired by nom 💜.
Parser combinators offer significant advantages over regular expressions:
| Chomp | Regex | |
|---|---|---|
| Readability | Reads like grammar rules | Often "write-only" patterns |
| Composability | Build complex parsers from simple, reusable pieces | Monolithic patterns that resist reuse |
| Error Messages | Clear context on what failed and where | Generic "no match" or cryptic positions |
| Maintainability | Easy to modify and extend | Small changes can break everything |
| Nested Structures | Natural support for recursion | Struggles or impossible |
| Type Safety | Compile-time guarantees | Runtime string manipulation |
go get github.com/purpleclay/chompAt the heart of chomp is the combinator - a function that attempts to parse a State (the original input plus a cursor) and returns a tuple (rem, ext, err). Run is the string-in/string-out entry point for a top-level parse:
input
│
▼
┌─────────────────────┐
│ Combinator │
└─────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ rem │ │ ext │ │ err │
└───────────┘ └───────────┘ └───────────┘
remaining extracted error (if any)
text text
// Parse a simple tag
rem, ext, _ := chomp.Tag("Hello").Run("Hello, World!")
// ext: "Hello"
// rem: ", World!"Combinators can be composed together to build sophisticated parsers:
// Parse a key-value pair like "name=alice"
func KeyValue() chomp.Combinator[chomp.Tuple2[string, string]] {
return chomp.SepPair(
chomp.While(chomp.IsLetter), // key: letters
chomp.Tag("="), // separator (discarded)
chomp.While(chomp.IsLetter), // value: letters
)
}
rem, kv, _ := KeyValue().Run("name=alice&age=30")
// kv: {First: "name", Second: "alice"}
// rem: "&age=30"Every combinator honours a single documented contract, so combinators compose predictably regardless of who wrote them:
- Failure is non-consuming. On error, a combinator returns the
Stateit was given unchanged (and the zero value forext). - Success extraction is a prefix. On success, for a
Combinator[string],extis exactly the consumed prefix:input == ext + rem. Combinators that transform their output, or intentionally discard part of the matched text (delimiters, prefixes, suffixes, separators), are documented as such and are exempt from this clause only. - Zero-width success terminates repetition. A repetition combinator stops iterating when an iteration succeeds without consuming input.
If you write your own combinators, follow the same rules — First, Opt, and the repetition combinators all rely on rule 1 to backtrack correctly.
Real-world parser examples:
- GPG Private Key Parser - Parse GPG key metadata
- Git Diff Parser - Parse unified diff output
- Combinator Reference - All available combinators
- Benchmarks - Performance benchmarks