Skip to content

Latest commit

 

History

82 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chomp

Nix Go MIT

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 💜.

Why Chomp?

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

Installation

go get github.com/purpleclay/chomp

How It Works

At 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"

The Combinator Contract

Every combinator honours a single documented contract, so combinators compose predictably regardless of who wrote them:

  1. Failure is non-consuming. On error, a combinator returns the State it was given unchanged (and the zero value for ext).
  2. Success extraction is a prefix. On success, for a Combinator[string], ext is 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.
  3. 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.

Examples

Real-world parser examples:

Documentation

About

A parser combinator library for Go that makes parsing text intuitive and maintainable

Topics

Resources

Code of conduct

Stars

0 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages