Documentation
¶
Overview ¶
Package chomp provides a parser combinator library for chomping strings (a rune at a time) in Go. A more intuitive way to parse text without having to write a single regex.
Every combinator threads a State - the original input plus a cursor - rather than a bare string, so any point in a parse can recover its absolute byte position with no external bookkeeping. Combinator.Run is the string-in/string-out entry point for a top-level parse.
The combinator contract ¶
Every combinator in this package honours the same contract:
- Failure is non-consuming. On error, a combinator returns the State it was given unchanged (and the zero value for ext).
- Success extraction is a prefix. On success, for 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.
- Zero-width success terminates repetition. A repetition combinator stops iterating when an iteration succeeds without consuming input.
Custom combinators composed from this package should honour the same contract to remain safe to use with First, Opt, and the repetition combinators, all of which rely on rule 1 to backtrack correctly.
Index ¶
- Variables
- func Finalize(err error) error
- type Combinator
- func All[T any](c ...Combinator[T]) Combinator[[]T]
- func AllConsuming[T any](c Combinator[T]) Combinator[T]
- func Alpha() Combinator[string]
- func Alpha0() Combinator[string]
- func Alphanumeric() Combinator[string]
- func Alphanumeric0() Combinator[string]
- func AnyAlphanumeric() Combinator[string]
- func AnyBinaryDigit() Combinator[string]
- func AnyChar() Combinator[string]
- func AnyDigit() Combinator[string]
- func AnyHexDigit() Combinator[string]
- func AnyLetter() Combinator[string]
- func AnyOctalDigit() Combinator[string]
- func BinaryDigit() Combinator[string]
- func BinaryDigit0() Combinator[string]
- func BracketAngled() Combinator[string]
- func BracketSquare() Combinator[string]
- func Char(c rune) Combinator[string]
- func Cond[T any](cond bool, c Combinator[T]) Combinator[T]
- func Consumed[T any](c Combinator[T]) Combinator[Tuple2[string, T]]
- func Crlf() Combinator[string]
- func Cut[T any](c Combinator[T]) Combinator[T]
- func Delimited[T, U, V any](left Combinator[T], str Combinator[U], right Combinator[V]) Combinator[U]
- func Digit() Combinator[string]
- func Digit0() Combinator[string]
- func Eof() Combinator[string]
- func Eol() Combinator[string]
- func Escaped(normal Combinator[string], escape rune, escapable Combinator[string]) Combinator[string]
- func EscapedTransform(normal Combinator[string], escape rune, transform Combinator[string]) Combinator[string]
- func First[T any](c ...Combinator[T]) Combinator[T]
- func Flatten(c Combinator[[]string]) Combinator[string]
- func FoldMany[S, T any](c Combinator[T], init S, reducer func(S, T) S) Combinator[S]
- func FoldMany0[S, T any](c Combinator[T], init S, reducer func(S, T) S) Combinator[S]
- func HexDigit() Combinator[string]
- func HexDigit0() Combinator[string]
- func I(c Combinator[[]string], i int) Combinator[string]
- func IsA(str string) Combinator[string]
- func IsNot(str string) Combinator[string]
- func Label[T any](name string, c Combinator[T]) Combinator[T]
- func LengthCount[T any](length Combinator[int], c Combinator[T]) Combinator[[]T]
- func LineEnding() Combinator[string]
- func Many[T any](c Combinator[T]) Combinator[[]T]
- func ManyCount[T any](c Combinator[T]) Combinator[int]
- func ManyCount0[T any](c Combinator[T]) Combinator[int]
- func ManyN[T any](c Combinator[T], n int) Combinator[[]T]
- func ManyTill[T, U any](c Combinator[T], term Combinator[U]) Combinator[[]T]
- func ManyTill0[T, U any](c Combinator[T], term Combinator[U]) Combinator[[]T]
- func Map[S, T any](c Combinator[T], mapper func(in T) S) Combinator[S]
- func Multispace() Combinator[string]
- func Multispace0() Combinator[string]
- func Newline() Combinator[string]
- func NoneOf(str string) Combinator[string]
- func NotLineEnding() Combinator[string]
- func OctalDigit() Combinator[string]
- func OctalDigit0() Combinator[string]
- func OneOf(str string) Combinator[string]
- func Opt[T any](c Combinator[T]) Combinator[T]
- func Pair[A, B any](c1 Combinator[A], c2 Combinator[B]) Combinator[Tuple2[A, B]]
- func Parentheses() Combinator[string]
- func Peek[T any](c Combinator[T]) Combinator[T]
- func PeekNot[T any](c Combinator[T]) Combinator[string]
- func Preceded(pre, c Combinator[string]) Combinator[string]
- func QuoteDouble() Combinator[string]
- func QuoteSingle() Combinator[string]
- func Recognize[T any](c Combinator[T]) Combinator[string]
- func Repeat[T any](c Combinator[T], n int) Combinator[[]T]
- func RepeatRange[T any](c Combinator[T], n, m int) Combinator[[]T]
- func Rest() Combinator[string]
- func S(c Combinator[string]) Combinator[[]string]
- func Satisfy(pred func(rune) bool) Combinator[string]
- func SepPair[A, U, B any](c1 Combinator[A], sep Combinator[U], c2 Combinator[B]) Combinator[Tuple2[A, B]]
- func SeparatedList[T, U any](c Combinator[T], sep Combinator[U]) Combinator[[]T]
- func SeparatedList0[T, U any](c Combinator[T], sep Combinator[U]) Combinator[[]T]
- func Space() Combinator[string]
- func Space0() Combinator[string]
- func Tab() Combinator[string]
- func Tag(str string) Combinator[string]
- func TagNoCase(str string) Combinator[string]
- func Take(n int) Combinator[string]
- func TakeUntil1(str string) Combinator[string]
- func Terminated(c, suf Combinator[string]) Combinator[string]
- func Until(str string) Combinator[string]
- func Value[S, T any](c Combinator[T], val S) Combinator[S]
- func Verify[T any](c Combinator[T], predicate func(T) bool) Combinator[T]
- func While(p Predicate) Combinator[string]
- func WhileN(p Predicate, n int) Combinator[string]
- func WhileNM(p Predicate, n, m int) Combinator[string]
- func WhileNot(p Predicate) Combinator[string]
- func WhileNotN(p Predicate, n int) Combinator[string]
- func WhileNotNM(p Predicate, n, m int) Combinator[string]
- type CombinatorParseError
- type CutError
- type ParserError
- type Predicate
- type RangedParserError
- type RangedParserExec
- type State
- type Tuple2
Constants ¶
This section is empty.
Variables ¶
var ( // IsDigit determines whether a rune is a decimal digit. A rune is classed // as a digit if it is between the ASCII range of '0' or '9', or if it belongs // within the Unicode [Nd] category. // // [Nd]: https://www.fileformat.info/info/unicode/category/Nd/list.htm IsDigit = Named("is_digit", unicode.IsDigit) // IsLetter determines if a rune is a letter. A rune is classed as a letter // if it is between the ASCII range of 'a' and 'z' (including its uppercase // equivalents), or it belongs within any of the Unicode letter categories: // [Lu] [LI] [Lt] [Lm] [Lo]. // // [Lu]: https://www.fileformat.info/info/unicode/category/Lu/list.htm // [LI]: https://www.fileformat.info/info/unicode/category/Ll/list.htm // [Lt]: https://www.fileformat.info/info/unicode/category/Lt/list.htm // [Lm]: https://www.fileformat.info/info/unicode/category/Lm/list.htm // [Lo]: https://www.fileformat.info/info/unicode/category/Lo/list.htm IsLetter = Named("is_letter", unicode.IsLetter) // IsAlphanumeric determines whether a rune is a decimal digit or a letter. // This convenience method wraps the existing [IsDigit] and [IsLetter] // predicates. IsAlphanumeric = Named("is_alphanumeric", func(r rune) bool { return unicode.IsDigit(r) || unicode.IsLetter(r) }) // IsLineEnding determines whether a rune is one of the following ASCII // line ending characters '\r' or '\n'. IsLineEnding = Named("is_line_ending", func(r rune) bool { return r == '\n' || r == '\r' }) // IsSpace determines whether a rune is a space character. A rune is classed // as a space if it is either a space ' ' or a tab '\t'. IsSpace = Named("is_space", func(r rune) bool { return r == ' ' || r == '\t' }) // IsMultispace determines whether a rune is a whitespace character. A rune // is classed as whitespace if it is a space ' ', tab '\t', newline '\n', // or carriage return '\r'. IsMultispace = Named("is_multispace", func(r rune) bool { return r == ' ' || r == '\t' || r == '\n' || r == '\r' }) // IsHexDigit determines whether a rune is a hexadecimal digit. A rune is // classed as a hex digit if it is between '0'-'9', 'a'-'f', or 'A'-'F'. IsHexDigit = Named("is_hex_digit", func(r rune) bool { return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F') }) // IsOctalDigit determines whether a rune is an octal digit. A rune is classed // as an octal digit if it is between '0' and '7'. IsOctalDigit = Named("is_octal_digit", func(r rune) bool { return r >= '0' && r <= '7' }) // IsBinaryDigit determines whether a rune is a binary digit. A rune is classed // as a binary digit if it is either '0' or '1'. IsBinaryDigit = Named("is_binary_digit", func(r rune) bool { return r == '0' || r == '1' }) )
Functions ¶
func Finalize ¶ added in v0.8.0
Finalize prepares an error returned by a raw combinator invocation for use outside a parse. It is the boundary Combinator.Run applies errors to before returning them; custom drivers built on raw c(state) invocation should apply it at their own boundary.
For every CombinatorParseError reached through err's chain (walking down through ParserError, RangedParserError and CutError, the only wrapper types this package produces), it captures the failure's position once and clones Snippet's bounded display window into its own backing array, then drops the reference to the original input. An escaped error therefore holds O(1) memory regardless of input size, rather than pinning the entire input for as long as the error lives. Errors outside this closed set are returned unchanged. Applying Finalize more than once is a no-op.
Types ¶
type Combinator ¶
Combinator is a higher-order function capable of parsing text under a defined condition. Combinators can be combined to form more complex parsers. Upon success, a combinator will return both the unparsed and parsed State. All combinators are strict and must parse its input. Any failure to do so should raise a CombinatorParseError.
Raw invocation c(state) is the composition surface used by combinators calling combinators (and custom drivers); its errors are unfinalised and may still reference the live input. Use Combinator.Run as the string-in/string-out entry point, which finalises any error via Finalize before returning it.
func All ¶
func All[T any](c ...Combinator[T]) Combinator[[]T]
All will match the input text against a series of [Combinator]s. All combinators must match in the order provided.
chomp.All(
chomp.Tag("Hello"),
chomp.Until("W"),
chomp.Tag("World!")).Run("Hello, World!")
// ("", []string{"Hello", ", ", "World!"}, nil)
func AllConsuming ¶ added in v0.6.0
func AllConsuming[T any](c Combinator[T]) Combinator[T]
AllConsuming ensures the entire input is consumed by the inner parser, failing if any text remains unparsed.
chomp.AllConsuming(chomp.Tag("Hello")).Run("Hello")
// ("", "Hello", nil)
chomp.AllConsuming(chomp.Tag("Hello")).Run("Hello, World!")
// ("Hello, World!", "", error)
func Alpha ¶ added in v0.5.0
func Alpha() Combinator[string]
Alpha matches one or more ASCII or Unicode letters. Equivalent to While(IsLetter).
chomp.Alpha().Run("Hello123")
// ("123", "Hello", nil)
func Alpha0 ¶ added in v0.5.0
func Alpha0() Combinator[string]
Alpha0 matches zero or more ASCII or Unicode letters. Equivalent to WhileN(IsLetter, 0).
chomp.Alpha0().Run("123Hello")
// ("123Hello", "", nil)
func Alphanumeric ¶ added in v0.5.0
func Alphanumeric() Combinator[string]
Alphanumeric matches one or more alphanumeric characters. Equivalent to While(IsAlphanumeric).
chomp.Alphanumeric().Run("Hello123!")
// ("!", "Hello123", nil)
func Alphanumeric0 ¶ added in v0.5.0
func Alphanumeric0() Combinator[string]
Alphanumeric0 matches zero or more alphanumeric characters. Equivalent to WhileN(IsAlphanumeric, 0).
chomp.Alphanumeric0().Run("!Hello123")
// ("!Hello123", "", nil)
func AnyAlphanumeric ¶ added in v0.6.0
func AnyAlphanumeric() Combinator[string]
AnyAlphanumeric matches a single alphanumeric character.
chomp.AnyAlphanumeric().Run("a1!")
// ("1!", "a", nil)
func AnyBinaryDigit ¶ added in v0.6.0
func AnyBinaryDigit() Combinator[string]
AnyBinaryDigit matches a single binary digit (0-1).
chomp.AnyBinaryDigit().Run("101")
// ("01", "1", nil)
func AnyChar ¶ added in v0.5.0
func AnyChar() Combinator[string]
AnyChar matches any single character at the beginning of the input text.
chomp.AnyChar().Run("Hello")
// ("ello", "H", nil)
func AnyDigit ¶ added in v0.6.0
func AnyDigit() Combinator[string]
AnyDigit matches a single decimal digit (0-9).
chomp.AnyDigit().Run("123")
// ("23", "1", nil)
func AnyHexDigit ¶ added in v0.6.0
func AnyHexDigit() Combinator[string]
AnyHexDigit matches a single hexadecimal digit (0-9, a-f, A-F).
chomp.AnyHexDigit().Run("fF0")
// ("F0", "f", nil)
func AnyLetter ¶ added in v0.6.0
func AnyLetter() Combinator[string]
AnyLetter matches a single ASCII or Unicode letter.
chomp.AnyLetter().Run("Hello")
// ("ello", "H", nil)
func AnyOctalDigit ¶ added in v0.6.0
func AnyOctalDigit() Combinator[string]
AnyOctalDigit matches a single octal digit (0-7).
chomp.AnyOctalDigit().Run("752")
// ("52", "7", nil)
func BinaryDigit ¶ added in v0.5.0
func BinaryDigit() Combinator[string]
BinaryDigit matches one or more binary digits (0-1). Equivalent to While(IsBinaryDigit).
chomp.BinaryDigit().Run("1010 rest")
// (" rest", "1010", nil)
func BinaryDigit0 ¶ added in v0.5.0
func BinaryDigit0() Combinator[string]
BinaryDigit0 matches zero or more binary digits (0-1). Equivalent to WhileN(IsBinaryDigit, 0).
chomp.BinaryDigit0().Run("234")
// ("234", "", nil)
func BracketAngled ¶
func BracketAngled() Combinator[string]
BracketAngled will match any text delimited (or surrounded) by a pair of <angled brackets>.
chomp.BracketAngled().Run("<Hello, World!>")
// ("", "Hello, World!", nil)
func BracketSquare ¶
func BracketSquare() Combinator[string]
BracketSquare will match any text delimited (or surrounded) by a pair of [square brackets].
chomp.BracketSquare().Run("[Hello, World!]")
// ("", "Hello, World!", nil)
func Char ¶ added in v0.5.0
func Char(c rune) Combinator[string]
Char matches a specific single character at the beginning of the input text.
chomp.Char(',').Run(",,rest")
// (",rest", ",", nil)
func Cond ¶ added in v0.6.0
func Cond[T any](cond bool, c Combinator[T]) Combinator[T]
Cond conditionally applies a parser based on a boolean flag. If the condition is true, the parser is applied. Otherwise, it returns an empty result without consuming input. Enables optional parsing logic.
chomp.Cond(true, chomp.Tag("Hello")).Run("Hello, World!")
// (", World!", "Hello", nil)
chomp.Cond(false, chomp.Tag("Hello")).Run("Hello, World!")
// ("Hello, World!", "", nil)
func Consumed ¶ added in v0.6.0
func Consumed[T any](c Combinator[T]) Combinator[Tuple2[string, T]]
Consumed provides both the raw consumed text and the parsed output as a tuple. Enables access to both representations simultaneously.
chomp.Consumed(chomp.SepPair(
chomp.Alpha(),
chomp.Tag(", "),
chomp.Alpha())).Run("Hello, World!")
// ("!", Tuple2[string, Tuple2[string, string]]{First: "Hello, World", Second: Tuple2[string, string]{First: "Hello", Second: "World"}}, nil)
func Crlf ¶
func Crlf() Combinator[string]
Crlf must match a strict CRLF '\r\n' line ending. It never matches a bare LF or a bare CR; see LineEnding to also accept a bare LF, and Eol for how a bare CR is otherwise handled. Inspects at most the first two bytes of the input, regardless of its length.
chomp.Crlf().Run("\r\nHello")
// ("Hello", "\r\n", nil)
func Cut ¶ added in v0.6.0
func Cut[T any](c Combinator[T]) Combinator[T]
Cut converts recoverable parsing errors into fatal failures, preventing backtracking past decision points. Improves error messaging by committing to a parsing path once the cut point is reached.
// Without Cut, First would try the second alternative
// With Cut, once "if" matches, failure is fatal
chomp.First(
chomp.All(
chomp.Tag("if"),
chomp.Cut(chomp.Tag("("))),
chomp.S(chomp.Tag("identifier"))).Run("if x")
// ("if x", nil, CutError{...})
func Delimited ¶
func Delimited[T, U, V any](left Combinator[T], str Combinator[U], right Combinator[V]) Combinator[U]
Delimited will match a series of combinators against the input text. All must match, with the delimiters being discarded.
chomp.Delimited(
chomp.Tag("'"),
chomp.Tag("Hello, World!"),
chomp.Tag("'")).Run("'Hello, World!'")
// ("", "Hello, World!", nil)
func Digit ¶ added in v0.5.0
func Digit() Combinator[string]
Digit matches one or more decimal digits. Equivalent to While(IsDigit).
chomp.Digit().Run("123abc")
// ("abc", "123", nil)
func Digit0 ¶ added in v0.5.0
func Digit0() Combinator[string]
Digit0 matches zero or more decimal digits. Equivalent to WhileN(IsDigit, 0).
chomp.Digit0().Run("abc123")
// ("abc123", "", nil)
func Eof ¶ added in v0.6.0
func Eof() Combinator[string]
Eof matches only when at the end of input, returning an empty string on success. Prevents partial parsing by ensuring no input remains.
chomp.Eof().Run("")
// ("", "", nil)
chomp.Eof().Run("remaining")
// ("remaining", "", error)
func Eol ¶ added in v0.3.0
func Eol() Combinator[string]
Eol will scan and return any text before any ASCII line ending characters. Line endings are discarded. Unlike LineEnding, a bare CR '\r' is also consumed here, treated as a legacy-Mac line terminator.
chomp.Eol().Run("Hello, World!\nIt's a great day!")
// ("It's a great day!", "Hello, World!", nil)
func Escaped ¶ added in v0.5.0
func Escaped(normal Combinator[string], escape rune, escapable Combinator[string]) Combinator[string]
Escaped parses a string containing escape sequences. It takes a normal content combinator, an escape character, and a combinator that matches valid characters after the escape. The escape sequences are preserved in the output as-is.
chomp.Escaped(chomp.While(chomp.IsLetter), '\\', chomp.OneOf(`"n\`)).Run(`Hello\"World`)
// ("", `Hello\"World`, nil)
func EscapedTransform ¶ added in v0.5.0
func EscapedTransform(normal Combinator[string], escape rune, transform Combinator[string]) Combinator[string]
EscapedTransform parses a string containing escape sequences and transforms them. It takes a normal content combinator, an escape character, and a transform function that converts escape sequences to their actual values.
transform := func(s chomp.State) (chomp.State, string, error) {
switch s.Rest()[0] {
case 'n':
return s.Advance(1), "\n", nil
case '"':
return s.Advance(1), "\"", nil
case '\\':
return s.Advance(1), "\\", nil
}
return s, "", errors.New("invalid escape")
}
chomp.EscapedTransform(chomp.While(chomp.IsLetter), '\\', transform).Run(`Hello\nWorld`)
// ("", "Hello\nWorld", nil)
func First ¶
func First[T any](c ...Combinator[T]) Combinator[T]
First will match the input text against a series of [Combinator]s. Matching stops as soon as the first combinator succeeds. One Combinator must match. For better performance, try and order the combinators from most to least likely to match.
If a CutError is encountered during parsing, backtracking stops immediately and the error is propagated. This allows Cut to commit to a parsing path.
chomp.First(
chomp.Tag("Good Morning"),
chomp.Tag("Hello")).Run("Good Morning, World!")
// (", World!", "Good Morning", nil)
func Flatten ¶ added in v0.4.0
func Flatten(c Combinator[[]string]) Combinator[string]
Flatten the output from a Combinator by joining all extracted values into a string.
chomp.Flatten(
chomp.Many(chomp.Parentheses()),
).Run("(H)(el)(lo), World!")
// (", World!", "Hello", nil)
func FoldMany ¶ added in v0.6.0
func FoldMany[S, T any](c Combinator[T], init S, reducer func(S, T) S) Combinator[S]
FoldMany will scan the input text, matching the Combinator repeatedly and accumulating results using the provided reducer function. At least one element must match. An iteration that succeeds without consuming input stops the loop instead of being counted, so it can never repeat forever.
chomp.FoldMany(chomp.AnyDigit(), 0, func(acc int, val string) int {
n, _ := strconv.Atoi(val)
return acc + n
}).Run("123abc")
// ("abc", 6, nil)
func FoldMany0 ¶ added in v0.6.0
func FoldMany0[S, T any](c Combinator[T], init S, reducer func(S, T) S) Combinator[S]
FoldMany0 will scan the input text, matching the Combinator repeatedly and accumulating results using the provided reducer function. Zero or more elements may match. An iteration that succeeds without consuming input stops the loop instead of being counted, so it can never repeat forever.
chomp.FoldMany0(chomp.AnyDigit(), 0, func(acc int, val string) int {
n, _ := strconv.Atoi(val)
return acc + n
}).Run("abc")
// ("abc", 0, nil)
func HexDigit ¶ added in v0.5.0
func HexDigit() Combinator[string]
HexDigit matches one or more hexadecimal digits (0-9, a-f, A-F). Equivalent to While(IsHexDigit).
chomp.HexDigit().Run("1a2B3c rest")
// (" rest", "1a2B3c", nil)
func HexDigit0 ¶ added in v0.5.0
func HexDigit0() Combinator[string]
HexDigit0 matches zero or more hexadecimal digits (0-9, a-f, A-F). Equivalent to WhileN(IsHexDigit, 0).
chomp.HexDigit0().Run("xyz")
// ("xyz", "", nil)
func I ¶
func I(c Combinator[[]string], i int) Combinator[string]
I extracts and returns a single string from the result of the inner Combinator. Combinators of differing return types can be successfully chained together while using this conversion combinator.
chomp.I(chomp.SepPair(
chomp.Tag("Hello"),
chomp.Tag(", "),
chomp.Tag("World")), 1).Run("Hello, World!")
// ("!", "World", nil)
func IsA ¶ added in v0.8.0
func IsA(str string) Combinator[string]
IsA must match at least one character from the provided sequence at the beginning of the input text. Parsing stops upon the first unmatched character. An empty sequence can never satisfy "at least one", so this always fails.
chomp.IsA("eH").Run("Hello, World!")
// ("llo, World!", "He", nil)
func IsNot ¶ added in v0.8.0
func IsNot(str string) Combinator[string]
IsNot must not match at least one character at the beginning of the input text from the provided sequence. Parsing stops upon the first matched character. An empty sequence excludes nothing, so this matches the entire remaining input when at least one character remains; an empty input still fails.
chomp.IsNot("ol").Run("Hello, World!")
// ("llo, World!", "He", nil)
func Label ¶ added in v0.8.0
func Label[T any](name string, c Combinator[T]) Combinator[T]
Label attaches a grammar-level name to any failure beneath c, so an error speaks in terms the grammar's author chose rather than internal combinator names.
Nested Labels chain outermost-first: Label("manifest", Label("version", c)) records Labels: []string{"manifest", "version"} on the underlying CombinatorParseError, rendered by CombinatorParseError.Error and CombinatorParseError.Snippet as "... while parsing manifest > version", and by CombinatorParseError.LogValue as the "context" field. Any newline in name is collapsed to a space, preserving Error's single-line guarantee regardless of what the caller passes.
chomp.Label("version", chomp.Digit()).Run("abc")
// (..., "", chomp.CombinatorParseError{..., Labels: []string{"version"}})
func LengthCount ¶ added in v0.6.0
func LengthCount[T any](length Combinator[int], c Combinator[T]) Combinator[[]T]
LengthCount will first parse a length value using the length combinator, then apply the element combinator that exact number of times.
chomp.LengthCount(
chomp.Map(chomp.AnyDigit(), func(s string) int {
n, _ := strconv.Atoi(s)
return n
}),
chomp.AnyLetter(),
).Run("3abc")
// ("", []string{"a", "b", "c"}, nil)
func LineEnding ¶ added in v0.7.1
func LineEnding() Combinator[string]
LineEnding must match either a LF '\n' or CRLF '\r\n' line ending. A bare CR '\r' is never matched; see Eol if you need to treat a bare CR as a legacy-Mac line terminator. Inspects at most the first two bytes of the input, regardless of its length.
chomp.LineEnding().Run("\nHello")
// ("Hello", "\n", nil)
chomp.LineEnding().Run("\r\nHello")
// ("Hello", "\r\n", nil)
func Many ¶ added in v0.2.0
func Many[T any](c Combinator[T]) Combinator[[]T]
Many will scan the input text, and it must match the Combinator at least once. This Combinator is greedy and will continuously execute until the first failed match. It is the equivalent of calling ManyN with an argument of 1. See ManyN for its zero-width matching behaviour.
chomp.Many(chomp.OneOf("Ho")).Run("Hello, World!")
// ("ello, World!", []string{"H"}, nil)
func ManyCount ¶ added in v0.6.0
func ManyCount[T any](c Combinator[T]) Combinator[int]
ManyCount will scan the input text and count the number of times the Combinator matches. At least one match is required. Results are not stored, making this memory efficient for counting. An iteration that succeeds without consuming input stops counting instead of repeating forever.
chomp.ManyCount(chomp.AnyLetter()).Run("abc123")
// ("123", 3, nil)
func ManyCount0 ¶ added in v0.6.0
func ManyCount0[T any](c Combinator[T]) Combinator[int]
ManyCount0 will scan the input text and count the number of times the Combinator matches. Zero or more matches are allowed. Results are not stored, making this memory efficient for counting. An iteration that succeeds without consuming input stops counting instead of repeating forever.
chomp.ManyCount0(chomp.AnyLetter()).Run("123")
// ("123", 0, nil)
func ManyN ¶ added in v0.2.0
func ManyN[T any](c Combinator[T], n int) Combinator[[]T]
ManyN will scan the input text and match the Combinator a minimum number of times. This Combinator is greedy and will continuously execute until the first failed match. An iteration that succeeds without consuming input stops the loop instead of being counted, so it can never repeat forever.
chomp.ManyN(chomp.OneOf("W"), 0).Run("Hello, World!")
// ("Hello, World!", nil, nil)
func ManyTill ¶ added in v0.6.0
func ManyTill[T, U any](c Combinator[T], term Combinator[U]) Combinator[[]T]
ManyTill will scan the input text, matching the Combinator repeatedly until the terminator matches. The terminator is consumed but not included in the result. At least one element must match before the terminator. If an element succeeds without consuming input, the terminator can never be reached, so parsing fails instead of looping forever.
chomp.ManyTill(chomp.AnyChar(), chomp.Tag("END")).Run("abcEND")
// ("", []string{"a", "b", "c"}, nil)
func ManyTill0 ¶ added in v0.6.0
func ManyTill0[T, U any](c Combinator[T], term Combinator[U]) Combinator[[]T]
ManyTill0 will scan the input text, matching the Combinator repeatedly until the terminator matches. The terminator is consumed but not included in the result. Zero or more elements may match before the terminator. If an element succeeds without consuming input, the terminator can never be reached, so parsing fails instead of looping forever.
chomp.ManyTill0(chomp.AnyChar(), chomp.Tag("END")).Run("END")
// ("", nil, nil)
func Map ¶ added in v0.3.0
func Map[S, T any](c Combinator[T], mapper func(in T) S) Combinator[S]
Map the result of a Combinator to any other type
chomp.Map(
chomp.While(chomp.IsDigit),
func (in string) int { return len(in) }).Run("123456")
// ("", 6, nil)
func Multispace ¶ added in v0.5.0
func Multispace() Combinator[string]
Multispace matches one or more whitespace characters (space, tab, newline, carriage return). Equivalent to While(IsMultispace).
chomp.Multispace().Run(" \n\tHello")
// ("Hello", " \n\t", nil)
func Multispace0 ¶ added in v0.5.0
func Multispace0() Combinator[string]
Multispace0 matches zero or more whitespace characters (space, tab, newline, carriage return). Equivalent to WhileN(IsMultispace, 0).
chomp.Multispace0().Run("Hello")
// ("Hello", "", nil)
func Newline ¶ added in v0.5.0
func Newline() Combinator[string]
Newline matches a single newline character '\n'.
chomp.Newline().Run("\nHello")
// ("Hello", "\n", nil)
func NoneOf ¶
func NoneOf(str string) Combinator[string]
NoneOf must not match a single character at the beginning of the text from the provided sequence. An empty sequence excludes nothing, so this degenerates to matching any single character, the same as AnyChar.
chomp.NoneOf("loWrd!e").Run("Hello, World!")
// ("ello, World!", "H", nil)
func NotLineEnding ¶ added in v0.5.0
func NotLineEnding() Combinator[string]
NotLineEnding matches any characters until a line ending ('\n' or '\r'). Requires at least one character to be matched.
chomp.NotLineEnding().Run("Hello, World!\nNext line")
// ("\nNext line", "Hello, World!", nil)
func OctalDigit ¶ added in v0.5.0
func OctalDigit() Combinator[string]
OctalDigit matches one or more octal digits (0-7). Equivalent to While(IsOctalDigit).
chomp.OctalDigit().Run("0127 rest")
// (" rest", "0127", nil)
func OctalDigit0 ¶ added in v0.5.0
func OctalDigit0() Combinator[string]
OctalDigit0 matches zero or more octal digits (0-7). Equivalent to WhileN(IsOctalDigit, 0).
chomp.OctalDigit0().Run("89")
// ("89", "", nil)
func OneOf ¶
func OneOf(str string) Combinator[string]
OneOf must match a single character at the beginning of the text from the provided sequence. An empty sequence can never be matched, so this always fails.
chomp.OneOf("!,eH").Run("Hello, World!")
// ("ello, World!", "H", nil)
func Opt ¶
func Opt[T any](c Combinator[T]) Combinator[T]
Opt allows a Combinator to be optional by discarding its returned error and not modifying the input text upon failure. The inner combinator's remainder is never trusted on failure, even if it partially consumed the input before erroring.
chomp.Opt(chomp.Tag("Hey")).Run("Hello, World!")
// ("Hello, World!", "", nil)
func Pair ¶
func Pair[A, B any](c1 Combinator[A], c2 Combinator[B]) Combinator[Tuple2[A, B]]
Pair will scan the input text and match each Combinator in turn. Both combinators must match.
chomp.Pair(chomp.Tag("Hello,"), chomp.Tag(" World")).Run("Hello, World!")
// ("!", Tuple2[string, string]{First: "Hello,", Second: " World"}, nil)
func Parentheses ¶
func Parentheses() Combinator[string]
Parentheses will match any text delimited (or surrounded) by a pair of (parentheses).
chomp.Parentheses().Run("(Hello, World!)")
// ("", "Hello, World!", nil)
func Peek ¶ added in v0.3.0
func Peek[T any](c Combinator[T]) Combinator[T]
Peek will scan the text and apply the Combinator without consuming any input. Useful if you need to look ahead.
chomp.Peek(chomp.Tag("Hello")).Run("Hello, World!")
// ("Hello, World!", "Hello", nil)
chomp.Peek(
chomp.Many(chomp.Terminated(chomp.Until(" "), chomp.Tag(" "))),
).Run("Hello and Good Morning!")
// ("Hello and Good Morning!", []string{"Hello", "and", "Good"}, nil)
func PeekNot ¶ added in v0.6.0
func PeekNot[T any](c Combinator[T]) Combinator[string]
PeekNot succeeds when the inner parser fails without consuming input. Implements negative lookahead for validation. On success, returns an empty string without consuming any input. Pairs with Peek for positive lookahead.
chomp.PeekNot(chomp.Tag("Hello")).Run("World!")
// ("World!", "", nil)
chomp.PeekNot(chomp.Tag("Hello")).Run("Hello, World!")
// ("Hello, World!", "", error)
func Preceded ¶ added in v0.8.0
func Preceded(pre, c Combinator[string]) Combinator[string]
Preceded will scan the input text for a defined prefix and discard it before matching the remaining text against the Combinator. Both combinators must match.
chomp.Preceded(
chomp.Tag(`"`),
chomp.Tag("Hello")).Run(`"Hello, World!"`)
// (`, World!"`, "Hello", nil)
func QuoteDouble ¶
func QuoteDouble() Combinator[string]
QuoteDouble will match any text delimited (or surrounded) by a pair of "double quotes".
chomp.QuoteDouble().Run(`"Hello, World!"`)
// ("", "Hello, World!", nil)
func QuoteSingle ¶
func QuoteSingle() Combinator[string]
QuoteSingle will match any text delimited (or surrounded) by a pair of 'single quotes'.
chomp.QuoteSingle().Run("'Hello, World!'")
// ("", "Hello, World!", nil)
func Recognize ¶ added in v0.6.0
func Recognize[T any](c Combinator[T]) Combinator[string]
Recognize returns the consumed input as the output, regardless of the inner parser's result. Useful for capturing complex patterns as text.
chomp.Recognize(chomp.SepPair(
chomp.Alpha(),
chomp.Tag(", "),
chomp.Alpha())).Run("Hello, World!")
// ("!", "Hello, World", nil)
func Repeat ¶
func Repeat[T any](c Combinator[T], n int) Combinator[[]T]
Repeat will scan the input text and match the combinator the defined number of times. Every execution must match.
chomp.Repeat(chomp.Parentheses(), 2).Run("(Hello)(World)(!)")
// ("(!)", []string{"Hello", "World"}, nil)
func RepeatRange ¶ added in v0.2.0
func RepeatRange[T any](c Combinator[T], n, m int) Combinator[[]T]
RepeatRange will scan the input text and match the Combinator between a minimum and maximum number of times. It must match the expected minimum number of times.
chomp.RepeatRange(chomp.OneOf("Hleo"), 1, 8).Run("Hello, World!")
// (", World!", []string{"H", "e", "l", "l", "o"}, nil)
n must not exceed m.
func Rest ¶ added in v0.6.0
func Rest() Combinator[string]
Rest returns all remaining unconsumed input as a string value. Always succeeds, even with empty input.
chomp.Rest().Run("Hello, World!")
// ("", "Hello, World!", nil)
chomp.Rest().Run("")
// ("", "", nil)
func S ¶
func S(c Combinator[string]) Combinator[[]string]
S wraps the result of the inner Combinator within a string slice. Combinators of differing return types can be successfully chained together while using this conversion combinator.
chomp.S(chomp.Until(",")).Run("Hello, World!")
// (", World!", []string{"Hello"}, nil)
func Satisfy ¶ added in v0.5.0
func Satisfy(pred func(rune) bool) Combinator[string]
Satisfy matches a single character at the beginning of the input text that satisfies the given predicate function.
chomp.Satisfy(func(r rune) bool { return r >= 'A' && r <= 'Z' }).Run("Hello")
// ("ello", "H", nil)
func SepPair ¶
func SepPair[A, U, B any](c1 Combinator[A], sep Combinator[U], c2 Combinator[B]) Combinator[Tuple2[A, B]]
SepPair will scan the input text and match each Combinator, discarding the separator's output. All combinators must match.
chomp.SepPair(
chomp.Tag("Hello"),
chomp.Tag(", "),
chomp.Tag("World")).Run("Hello, World!")
// ("!", Tuple2[string, string]{First: "Hello", Second: "World"}, nil)
func SeparatedList ¶ added in v0.6.0
func SeparatedList[T, U any](c Combinator[T], sep Combinator[U]) Combinator[[]T]
SeparatedList will scan the input text and match the Combinator separated by the provided separator. At least one element must match. The separator output is discarded. If a separator and element together succeed without consuming input, iteration stops instead of repeating forever.
chomp.SeparatedList(chomp.Alpha(), chomp.Tag(",")).Run("a,b,c,")
// (",", []string{"a", "b", "c"}, nil)
func SeparatedList0 ¶ added in v0.6.0
func SeparatedList0[T, U any](c Combinator[T], sep Combinator[U]) Combinator[[]T]
SeparatedList0 will scan the input text and match the Combinator separated by the provided separator. Zero or more elements may match. The separator output is discarded. If a separator and element together succeed without consuming input, iteration stops instead of repeating forever.
chomp.SeparatedList0(chomp.Alpha(), chomp.Tag(",")).Run("123")
// ("123", []string{}, nil)
func Space ¶ added in v0.5.0
func Space() Combinator[string]
Space matches one or more space or tab characters. Equivalent to While(IsSpace).
chomp.Space().Run(" Hello")
// ("Hello", " ", nil)
func Space0 ¶ added in v0.5.0
func Space0() Combinator[string]
Space0 matches zero or more space or tab characters. Equivalent to WhileN(IsSpace, 0).
chomp.Space0().Run("Hello")
// ("Hello", "", nil)
func Tab ¶ added in v0.5.0
func Tab() Combinator[string]
Tab matches a single tab character '\t'.
chomp.Tab().Run("\tHello")
// ("Hello", "\t", nil)
func Tag ¶
func Tag(str string) Combinator[string]
Tag must match a series of characters at the beginning of the input text in the exact order and case provided. An empty str matches trivially without consuming any input.
chomp.Tag("Hello").Run("Hello, World!")
// (", World!", "Hello", nil)
func TagNoCase ¶ added in v0.5.0
func TagNoCase(str string) Combinator[string]
TagNoCase must match a series of characters at the beginning of the input text in the exact order provided, using full Unicode case-folding (not just ASCII). Runes are compared via their case-fold orbit, so fold pairs that don't share the same encoded byte length (the Kelvin sign 'K' U+212A folds with 'k'/'K', despite being 3 bytes to their 1) still match. Malformed UTF-8 in either the input or str never matches, even against a literal U+FFFD on the other side, since invalid bytes decode to the same replacement-character sentinel as a genuine one. The matched text from the input is returned (preserving the original casing). An empty str matches trivially without consuming any input, the same as Tag.
chomp.TagNoCase("hello").Run("HELLO, World!")
// (", World!", "HELLO", nil)
func Take ¶ added in v0.5.0
func Take(n int) Combinator[string]
Take will consume exactly n characters from the beginning of the input text. Unicode characters are handled correctly by counting runes, not bytes.
chomp.Take(5).Run("Hello, World!")
// (", World!", "Hello", nil)
func TakeUntil1 ¶ added in v0.5.0
func TakeUntil1(str string) Combinator[string]
TakeUntil1 will scan the input text for the first occurrence of the provided series of characters, requiring at least one character to be matched before the delimiter. Everything until that point in the text will be matched. An empty str always matches at position 0, which never satisfies "at least one", so this always fails.
chomp.TakeUntil1(",").Run("Hello, World!")
// (", World!", "Hello", nil)
chomp.TakeUntil1(",").Run(",World!")
// Error: must match at least one character
func Terminated ¶ added in v0.8.0
func Terminated(c, suf Combinator[string]) Combinator[string]
Terminated will scan the input text against the Combinator before matching a suffix and discarding it. Both combinators must match.
chomp.Terminated(
chomp.Tag("Hello"),
chomp.Tag(", ")).Run("Hello, World!")
// ("World!", "Hello", nil)
func Until ¶
func Until(str string) Combinator[string]
Until will scan the input text for the first occurrence of the provided series of characters. Everything until that point in the text will be matched. An empty str matches at position 0, so this succeeds trivially without consuming any input.
chomp.Until("World").Run("Hello, World!")
// ("World!", "Hello, ", nil)
func Value ¶ added in v0.6.0
func Value[S, T any](c Combinator[T], val S) Combinator[S]
Value returns a fixed value upon parser success, discarding the actual parse result. Useful for assigning semantic meaning to parsed tokens.
chomp.Value(chomp.Tag("true"), true).Run("true")
// ("", true, nil)
chomp.Value(chomp.Tag("false"), false).Run("false")
// ("", false, nil)
func Verify ¶ added in v0.6.0
func Verify[T any](c Combinator[T], predicate func(T) bool) Combinator[T]
Verify validates the parsed result against a predicate function without modifying the output. If the predicate returns false, the combinator fails. Useful for semantic validation of parsed data.
chomp.Verify(chomp.Alpha(), func(s string) bool {
return len(s) >= 3
}).Run("Hello, World!")
// (", World!", "Hello", nil)
chomp.Verify(chomp.Alpha(), func(s string) bool {
return len(s) >= 10
}).Run("Hello, World!")
// ("Hello, World!", "", error)
func While ¶
func While(p Predicate) Combinator[string]
While will scan the input text, testing each character against the provided Predicate. The Predicate must match at least one character.
chomp.While(chomp.IsLetter).Run("Hello, World!")
// (", World!", "Hello", nil)
func WhileN ¶ added in v0.3.0
func WhileN(p Predicate, n int) Combinator[string]
WhileN will scan the input text, testing each character against the provided Predicate. The Predicate must match at least n characters. If n is zero, this becomes an optional combinator.
chomp.WhileN(chomp.IsLetter, 1).Run("Hello, World!")
// (", World!", "Hello", nil)
chomp.WhileN(chomp.IsDigit, 0).Run("Hello, World!")
// ("Hello, World!", "", nil)
func WhileNM ¶ added in v0.3.0
func WhileNM(p Predicate, n, m int) Combinator[string]
WhileNM will scan the input text, testing each character against the provided Predicate. The Predicate must match a minimum of n and upto a maximum of m characters. If n is zero, this becomes an optional combinator.
chomp.WhileNM(chomp.IsLetter, 1, 8).Run("Hello, World!")
// (", World!", "Hello", nil)
func WhileNot ¶
func WhileNot(p Predicate) Combinator[string]
WhileNot will scan the input text, testing each character against the provided Predicate. The Predicate must not match at least one character. It has the inverse behavior of While.
chomp.WhileNot(chomp.IsDigit).Run("Hello, World!")
// ("", "Hello, World!", nil)
func WhileNotN ¶ added in v0.3.0
func WhileNotN(p Predicate, n int) Combinator[string]
WhileNotN will scan the input text, testing each character against the provided Predicate. The Predicate must not match at least n characters. If n is zero, this becomes an optional combinator. It has the inverse behavior of WhileN.
chomp.WhileNotN(chomp.IsDigit, 1).Run("Hello, World!")
// ("", "Hello, World!", nil)
chomp.WhileNotN(chomp.IsLetter, 0).Run("Hello, World!")
// ("Hello, World!", "", nil)
func WhileNotNM ¶ added in v0.3.0
func WhileNotNM(p Predicate, n, m int) Combinator[string]
WhileNotNM will scan the input text, testing each character against the provided Predicate. The Predicate must not match a minimum of n and upto a maximum of m characters. If n is zero, this becomes an optional combinator. It has the inverse behavior of WhileNM.
chomp.WhileNotNM(chomp.IsLetter, 1, 9).Run("20240709 was a great day")
// ("was a great day", "20240709 ", nil)
type CombinatorParseError ¶
type CombinatorParseError struct {
// Expected describes, in human terms, what the combinator required to
// succeed. Empty when no single literal applies, in which case
// [CombinatorParseError.Error], [CombinatorParseError.Snippet] and
// [CombinatorParseError.LogValue] fall back to a description derived
// from Type.
Expected string
// State at the point of failure, capturing the absolute position
// within the original input alongside the unparsed suffix. Only
// meaningful before the error is finalised (see [Finalize]): a
// finalised error - any error returned by [Combinator.Run] - clears
// State, since retaining it would keep the entire original input
// reachable for as long as the error lives. Use
// [CombinatorParseError.Offset] and [CombinatorParseError.Position]
// instead, which work correctly either way.
State State
// Labels records the chain of grammar-level names (see the future
// Label combinator) being parsed when the failure occurred, outermost
// first. Always empty until a caller wraps a combinator with Label.
Labels []string
// Type of [Combinator] that failed.
Type string
// contains filtered or unexported fields
}
CombinatorParseError defines an error that is raised when a combinator fails to parse the input text under its expected condition.
func (CombinatorParseError) Error ¶
func (e CombinatorParseError) Error() string
Error returns a single-line, grep-stable string representation of the current error: "chomp: parse error at line %d, column %d (offset %d): expected %s". It never contains a newline. For a human-facing, caret-annotated view of the failure, see CombinatorParseError.Snippet.
func (CombinatorParseError) LogValue ¶ added in v0.8.0
func (e CombinatorParseError) LogValue() slog.Value
LogValue implements slog.LogValuer, emitting offset/line/column/ expected (and context, once Labels is non-empty) as structured fields instead of a string to be parsed.
func (CombinatorParseError) Offset ¶ added in v0.8.0
func (e CombinatorParseError) Offset() int
Offset returns the byte offset into the original input where parsing failed. Unlike reading CombinatorParseError.State directly, this works correctly whether or not the error has been finalised (see Finalize).
func (CombinatorParseError) Position ¶ added in v0.8.0
func (e CombinatorParseError) Position() (line, col int)
Position returns the 1-based line and rune-aware column where parsing failed. Unlike reading CombinatorParseError.State directly, this works correctly whether or not the error has been finalised (see Finalize).
func (CombinatorParseError) Snippet ¶ added in v0.8.0
func (e CombinatorParseError) Snippet() string
Snippet renders a caret-annotated view of the source line containing the failure, for human-facing output such as a CLI - reached via errors.As rather than included in CombinatorParseError.Error, so multi-line output only ever appears because a caller asked for it.
Long lines are truncated to a window around the failure column. Tabs in the source line are replicated verbatim in the caret padding, so a terminal's own tab-stop expansion keeps both lines aligned. Alignment is rune-count based: double-width glyphs (e.g. CJK) may visually drift the caret, since that is inherently terminal-display-width dependent.
type CutError ¶ added in v0.6.0
type CutError struct {
// Err contains the underlying error that caused the cut.
Err error
}
CutError is a fatal parsing error that prevents backtracking past the decision point. Used with Cut to improve error messaging.
func (CutError) Error ¶ added in v0.6.0
Error delegates to the inner error's Error(), for the same reason as ParserError.Error. Fatal-vs-recoverable is a distinction for errors.As/errors.Is on the CutError type itself, not the rendered string.
func (CutError) LogValue ¶ added in v0.8.0
LogValue delegates to the inner error's LogValue if it implements slog.LogValuer, otherwise falls back to its Error() string.
type ParserError ¶
type ParserError struct {
// Err contains the [CombinatorParseError] that caused the parser to fail.
Err error
// Type of [Parser] that failed.
Type string
}
ParserError defines an error that is raised when a parser fails to parse the input text due to a failed Combinator.
func (ParserError) Error ¶
func (e ParserError) Error() string
Error delegates to the inner error's Error(). Only the leaf CombinatorParseError carries a position; ParserError adds no prefix of its own so the rendered message stays the single, grep-stable line CombinatorParseError.Error produces, regardless of wrapping depth.
func (ParserError) LogValue ¶ added in v0.8.0
func (e ParserError) LogValue() slog.Value
LogValue delegates to the inner error's LogValue if it implements slog.LogValuer, otherwise falls back to its Error() string.
func (ParserError) Unwrap ¶
func (e ParserError) Unwrap() error
Unwrap returns the inner CombinatorParseError.
type Predicate ¶
type Predicate interface {
// Match a rune against a defined expression, returning true
// if the condition is met
Match(r rune) bool
// Returns the name of the predicate for error handling
fmt.Stringer
}
Predicate defines an expression that will return either true or false
type RangedParserError ¶ added in v0.2.0
type RangedParserError struct {
// Err contains the [CombinatorParseError] that caused the parser to fail.
Err error
// Range contains the execution details of the ranged parser.
Exec RangedParserExec
// Type of [Parser] that failed.
Type string
}
RangedParserError defines an error that is raised when a ranged parser fails to parse the input text due to a failed Combinator within the expected execution range.
func (RangedParserError) Error ¶ added in v0.2.0
func (e RangedParserError) Error() string
Error delegates to the inner error's Error(), for the same reason as ParserError.Error. RangedParserError.Exec remains available programmatically via errors.As for callers that want execution counts.
func (RangedParserError) LogValue ¶ added in v0.8.0
func (e RangedParserError) LogValue() slog.Value
LogValue delegates to the inner error's LogValue if it implements slog.LogValuer, otherwise falls back to its Error() string.
func (RangedParserError) Unwrap ¶ added in v0.2.0
func (e RangedParserError) Unwrap() error
Unwrap returns the inner CombinatorParseError.
type RangedParserExec ¶ added in v0.2.0
type RangedParserExec struct {
// Min is the minimum number of expected executions.
Min int
// Max is the maximum number of possible executions.
Max int
// Count contains the number of executions.
Count int
}
RangedParserExec details how a ranged Combinator was executed.
func (RangedParserExec) String ¶ added in v0.2.0
func (e RangedParserExec) String() string
String returns a string representation of a RangedParserExec.
type State ¶ added in v0.8.0
type State struct {
// contains filtered or unexported fields
}
State carries the original input alongside a cursor into it. It is the threading value passed between every Combinator, so any point in a parse can recover its absolute position with no external bookkeeping.