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 text and returns a tuple (rem, ext, err):
input
│
▼
┌─────────────────────┐
│ Combinator │
└─────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ rem │ │ ext │ │ err │
└───────────┘ └───────────┘ └───────────┘
remaining extracted error (if any)
text text
// Parse a simple tag
rem, ext, _ := chomp.Tag("Hello")("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[[]string] {
return chomp.SepPair(
chomp.While(chomp.IsLetter), // key: letters
chomp.Tag("="), // separator (discarded)
chomp.While(chomp.IsLetter), // value: letters
)
}
rem, kv, _ := KeyValue()("name=alice&age=30")
// kv: ["name", "alice"]
// rem: "&age=30"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