### Seq Combinator for Sequential Matching Source: https://context7.com/vektah/goparsify/llms.txt Shows how the `Seq` combinator matches multiple parsers in order, storing their results in `Child`. Includes an example of mapping results to a custom type and handling sequence failures. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Match key=value pairs kvParser := Seq(Chars("a-zA-Z"), "=", Chars("a-zA-Z0-9")).Map(func(n *Result) { n.Result = map[string]string{ n.Child[0].Token: n.Child[2].Token, } }) result, err := Run(kvParser, "color=blue") if err != nil { panic(err) } fmt.Println(result) // map[color:blue] // If any parser in the sequence fails, the whole Seq fails and Pos is restored _, err2 := Run(kvParser, "color") fmt.Println(err2) // offset 5: expected = } ``` -------------------------------- ### Example Debug Output from HTML Parser Test Source: https://github.com/vektah/goparsify/blob/master/readme.md This output shows the detailed step-by-step execution of the HTML parser when run with debugging enabled. It logs the state of the parser, tokens found, and expected tokens. ```text adam:goparsify(master)$ go test -tags debug ./html -v === RUN TestParse hTml.go:48 | hello

hello

hello

hello

hello

hello

hello

hello

hello

found > hTml.go:43 | hello

] hTml.go:24 | hello

hTml.go:48 |

| < found < hTml.go:20 | color="blue">w | identifier found p hTml.go:33 | color="blue">w | attrs { hTml.go:32 | color="blue">w | attr { hTml.go:20 | ="blue">worldworldworld

world

world

world

world

world

found > hTml.go:43 | world

] hTml.go:24 | world

| text found world hTml.go:23 |

| } found "world" hTml.go:23 |

| element { hTml.go:21 |

| text did not find <> hTml.go:48 |

| tag { hTml.go:43 |

| tstart { hTml.go:43 | /p> | < found < hTml.go:20 | /p> | identifier did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:43 |

| } did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:48 |

| } did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:23 |

| } did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:24 |

| } found ["world"] hTml.go:44 |

| tend { hTml.go:44 | p> | | identifier found p hTml.go:44 | | > found > hTml.go:44 | | } found [] hTml.go:48 | | } found "hello " hTml.go:23 | | } found html.htmlTag{Name:"p", Attributes:map[string]string{"color":"blue"}, Body:[]interface {}{"world"}} hTml.go:23 | | element { hTml.go:48 | | tag { hTml.go:43 | | tstart { hTml.go:43 | /body> | < found < hTml.go:20 | /body> | identifier did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:43 | | } did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:48 | | } did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:21 | | text did not find <> hTml.go:23 | | } did not find [a-zA-Z][a-zA-Z0-9]* hTml.go:24 | | } found ["hello ",html.htmlTag{Name:"p", Attributes:map[string]string{"color":"blue"}, Body:[]interface {}{"world"}}] hTml.go:44 | | tend { hTml.go:44 | body> | | identifier found body hTml.go:44 | | > found > hTml.go:44 | | } found [] hTml.go:48 | | } found [[<,body,,map[string]string{},>],,[]interface {}{"hello ", html.htmlTag{Name:"p", Attributes:map[string]string{"color":"blue"}, Body:[]interface {}{"world"}}},[]] --- PASS: TestParse (0.00s) PASS ok github.com/vektah/goparsify/html 0.117s ``` -------------------------------- ### Test Calculator Number Parsing Source: https://github.com/vektah/goparsify/blob/master/readme.md Tests the basic parsing of numbers in the calculator example. Ensures that single numeric literals are correctly parsed. ```go func TestNumbers(t *testing.T) { result, err := Calc(`1`) require.NoError(t, err) require.EqualValues(t, 1, result) } ``` -------------------------------- ### Basic Parser Usage with Exact Source: https://context7.com/vektah/goparsify/llms.txt Demonstrates creating a parser for a literal string and using it with `NewState` and `Result`. Shows how to access the matched token and remaining input. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // A Parser is just a func(*State, *Result). // String literals are auto-converted to Exact parsers via Parsify. hello := Exact("hello") ps := NewState("hello world") var r Result hello(ps, &r) fmt.Println(r.Token) // hello fmt.Println(ps.Get()) // " world" (remaining input) } ``` -------------------------------- ### Running Parsers with Run Source: https://context7.com/vektah/goparsify/llms.txt Demonstrates the `Run` function for executing a parser over an entire string. Shows default unicode whitespace skipping, ASCII whitespace mode, and error handling for unconsumed input and parse failures. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { word := Chars("a-zA-Z") // Default: unicode whitespace skipping result, err := Run(word, " hello ") fmt.Println(result, err) // hello // ASCII whitespace mode (~20% faster for ASCII-only input) result2, err2 := Run(word, " world ", ASCIIWhitespace) fmt.Println(result2, err2) // world // Error: input not fully consumed _, err3 := Run(word, "hello world") fmt.Println(err3) // left unparsed: world // Error: parse failure _, err4 := Run(Exact("foo"), "bar") fmt.Println(err4) // offset 0: expected foo } ``` -------------------------------- ### Enable Parser Debugging and Logging Source: https://github.com/vektah/goparsify/blob/master/readme.md To debug parsers, first build with the debug tag using `go test -tags debug`. Then, enable logging by calling `EnableLogging(os.Stdout)` in your code. ```bash go test -tags debug ./html -v ``` ```go EnableLogging(os.Stdout) ``` -------------------------------- ### Enable Debug Logging and Dump Stats Source: https://context7.com/vektah/goparsify/llms.txt When built with the `debug` tag, `EnableLogging` traces parser steps to an `io.Writer`, and `DumpDebugStats` prints a performance table. Remember to call `DisableLogging` when done. ```go // Build with: go test -tags debug -v ./... package main import ( "os" . "github.com/vektah/goparsify" ) func main() { word := NewParser("word", Chars("a-z")) // Enable step-by-step trace to stdout EnableLogging(os.Stdout) Run(word, "hello") DisableLogging() // Print cumulative timing table (sorted by total time) DumpDebugStats() // Example output: // | var name | matches | total time | self time | calls | errors | location // | -------------------- | -------------------- | --------------- | --------------- | ---------- | ---------- | ---------- // | word | [a-z] | 500.21µs | 500.21µs | 1 | 0 | main.go:10 } ``` -------------------------------- ### Match first successful parser with Any Source: https://context7.com/vektah/goparsify/llms.txt Use `Any` to try multiple parsers in sequence and return the result of the first one that succeeds. It reports the longest error encountered if all alternatives fail. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Match true, false, or null JSON-style keywords boolNull := Any( Bind("true", true), Bind("false", false), Bind("null", nil), ) for _, input := range []string{"true", "false", "null"} { result, err := Run(boolNull, input) fmt.Printf("% -5s => %v (err: %v)\n", input, result, err) } // true => true (err: ) // false => false (err: ) // null => (err: ) _, err := Run(boolNull, "maybe") fmt.Println(err) // offset 0: expected null } ``` -------------------------------- ### Complete JSON Parser with goparsify Source: https://context7.com/vektah/goparsify/llms.txt A full JSON parser demonstrating literals, combinators, recursive grammars, `Cut` for error quality, and `Map` for typed output. Use `Unmarshal` with `ASCIIWhitespace` for performance. ```go package json import ( . "github.com/vektah/goparsify" ) var ( _value Parser _null = Bind("null", nil) _true = Bind("true", true) _false = Bind("false", false) _string = Map(StringLit(`"`), func(r *Result) { r.Result = r.Token }) _number = NumberLit() _properties = Some(Seq(StringLit(`"`), ":", &_value), ",") _array = Seq("[", Cut(), Some(&_value, ","), "]").Map(func(n *Result) { ret := []interface{}{ for _, child := range n.Child[2].Child { ret = append(ret, child.Result) } n.Result = ret }) _object = Seq("{ ", Cut(), _properties, "}").Map(func(n *Result) { ret := map[string]interface{}{ for _, prop := range n.Child[2].Child { ret[prop.Child[0].Token] = prop.Child[2].Result } n.Result = ret }) ) func init() { _value = Any(_null, _true, _false, _string, _number, _array, _object) } // Unmarshal parses a JSON string using ASCII whitespace mode for performance. func Unmarshal(input string) (interface{}, error) { return Run(_value, input, ASCIIWhitespace) } // Usage: // result, err := Unmarshal(`{"name":"Alice","scores":[10,20,30],"active":true}`) // // result => map[string]interface{}{ // // "name": "Alice", // // "scores": []interface{}{int64(10), int64(20), int64(30)}, // // "active": true, // // } ``` -------------------------------- ### Benchmark Results Source: https://github.com/vektah/goparsify/blob/master/readme.md Performance benchmarks comparing goparsify's JSON unmarshalling against other methods. Shows significant improvements in speed and allocations. ```text $ go test -benchmem -bench=. ./json BenchmarkUnmarshalParsec-8 20000 74880 ns/op 50846 B/op 1318 allocs/op BenchmarkUnmarshalParsify-8 30000 50631 ns/op 45055 B/op 233 allocs/op BenchmarkUnmarshalStdlib-8 30000 46989 ns/op 14210 B/op 260 allocs/op PASS ok github.com/vektah/goparsify/json 6.124s ``` -------------------------------- ### Break Typechecking Loop with Pointer Parser Source: https://github.com/vektah/goparsify/blob/master/readme.md Demonstrates how to break a typechecking loop in recursive parsers using a pointer and initializing it in an init function. ```go var ( value Parser prod = Seq(&value, Some(And(prodOp, &value))) ) func init() { value = Any(number, groupExpr) } ``` -------------------------------- ### Break Initialization Cycles with *Parser Source: https://context7.com/vektah/goparsify/llms.txt Use a forward-declared `Parser` variable and assign the actual parser in `init()` to break Go initialization cycles caused by mutually recursive parsers. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) var ( value Parser // forward declaration array = Seq("[", Many(&value, ","), "]") object = Seq("{ ", Many(Seq(StringLit("\""), ":", &value), ","), "}") ) func init() { // Break the cycle: value can now reference array and object value = Any( Bind("null", nil), Bind("true", true), Bind("false", false), NumberLit(), Map(StringLit("\""), func(n *Result) { n.Result = n.Token }), array, object, ) } func main() { result, err := Run(value, `{"key": [1, 2, 3]}`) if err != nil { panic(err) } fmt.Println(result) // map[key:[1 2 3]] (after full mapping) } ``` -------------------------------- ### Run Parser with ASCII Whitespace Source: https://github.com/vektah/goparsify/blob/master/readme.md This function is used to run a parser with a specific input, optionally using ASCII whitespace handling for performance. ```go Run(parser, input, ASCIIWhitespace) ``` -------------------------------- ### Test Calculator Addition Parsing Source: https://github.com/vektah/goparsify/blob/master/readme.md Tests the addition functionality of the calculator. Verifies that expressions like '1+1' are correctly evaluated. ```go func TestAddition(t *testing.T) { result, err := Calc(`1+1`) require.NoError(t, err) require.EqualValues(t, 2, result) } ``` -------------------------------- ### Control Whitespace Skipping Source: https://context7.com/vektah/goparsify/llms.txt Utilize `ASCIIWhitespace`, `UnicodeWhitespace`, or `NoWhitespace` to manage automatic whitespace skipping between tokens. These `VoidParser` functions can be passed to `Run` or assigned to `State.WS`. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { word := Chars("a-zA-Z") // Default: UnicodeWhitespace (handles \t \n \r and all Unicode spaces) r1, _ := Run(word, "\t hello") fmt.Println(r1) // — use .Map to get value; Token="hello" ps1 := NewState("\t hello") var o1 Result word(ps1, &o1) fmt.Println(o1.Token) // hello // ASCIIWhitespace: faster, handles only \t \n \v \f \r space ps2 := NewState(" world") ps2.WS = ASCIIWhitespace var o2 Result word(ps2, &o2) fmt.Println(o2.Token) // world // NoWhitespace: whitespace is significant, never skipped ps3 := NewState(" test") ps3.WS = NoWhitespace var o3 Result word(ps3, &o3) fmt.Println(ps3.Errored()) // true — leading spaces not skipped _ = r1 } ``` -------------------------------- ### Match Regular Expressions with Regex Source: https://context7.com/vektah/goparsify/llms.txt Regex compiles and anchors the given pattern at the current position, returning the match in .Token. It's useful for matching specific patterns like ISO dates. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Match an ISO date date := Regex(`\d{4}-\d{2}-\d{2}`) ps := NewState("2024-01-15 extra") var out Result date(ps, &out) fmt.Println(out.Token) // 2024-01-15 fmt.Println(ps.Get()) // " extra" _, err := Run(date, "not-a-date") fmt.Println(err) // offset 0: expected \d{4}-\d{2}-\d{2} } ``` -------------------------------- ### Match a specific string with Exact Source: https://context7.com/vektah/goparsify/llms.txt Use `Exact` to match a literal string precisely. It uses a fast byte-compare for single-byte strings and stores the match in the `.Token` field. Leading whitespace is automatically skipped. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { p := Exact("->") result, err := Run(p, "->") fmt.Println(result, err) // (Token is set, not Result) ps := NewState(" -> ") var out Result p(ps, &out) fmt.Println(out.Token) // -> (leading whitespace skipped automatically) } ``` -------------------------------- ### Match Character Classes with Chars Source: https://context7.com/vektah/goparsify/llms.txt Use Chars to match one or more characters defined by ranges, alphabets, or combinations. Optional min/max repetition counts can be provided. Use .Map to set .Result. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { identifier := Chars("a-zA-Z_", 1, -1) // 1+ identifier chars hexByte := Chars("a-fA-F0-9", 2, 2) // exactly 2 hex chars digits4to6 := Chars("0-9", 4, 6) // 4 to 6 digits r1, _ := Run(identifier, "myVar_1") fmt.Println(r1) // (Token is set; use .Map to set .Result) ps := NewState("myVar_1") var out Result identifier(ps, &out) fmt.Println(out.Token) // myVar_1 ps2 := NewState("ff") var out2 Result hexByte(ps2, &out2) fmt.Println(out2.Token) // ff _, err := Run(digits4to6, "123") fmt.Println(err) // offset 0: expected 0-9 _ = r1 } ``` -------------------------------- ### Prevent Backtracking with Cuts Source: https://github.com/vektah/goparsify/blob/master/readme.md Illustrates how to use cuts to prevent backtracking and improve error messages. Without a cut, the parser might ignore subsequent input after a partial match. ```go alpha := Chars("a-z") // without a cut if the close tag is left out the parser will backtrack and ignore the rest of the string nocut := Many(Any(Seq("<", alpha, ">"), alpha)) _, err := Run(nocut, "asdf "), alpha)) _, err = Run(cut, "asdf ``` -------------------------------- ### Result Structure and Seq Combinator Source: https://context7.com/vektah/goparsify/llms.txt Illustrates the `Result` type's `Child` field for storing sub-results from combinators like `Seq`. Shows direct inspection of `Result` fields after parsing. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Seq returns children in .Child[n] p := Seq("(", Chars("0-9"), ")") res, err := Run(p, "(42)") if err != nil { panic(err) } node := res // Run returns interface{} - cast via Map instead (see Map section) _ = node fmt.Println("parsed successfully") // Direct Result inspection ps := NewState("(42)") var out Result p(ps, &out) fmt.Println(out.Child[0].Token) // ( fmt.Println(out.Child[1].Token) // 42 fmt.Println(out.Child[2].Token) // ) } ``` -------------------------------- ### Assign Constant Values with Bind Source: https://context7.com/vektah/goparsify/llms.txt Use `Bind` to assign a fixed value to `.Result` when a parser succeeds, without executing a callback. This is ideal for parsing keyword constants like boolean or null literals. ```go package main import ( "fmt" . "github.com/vektah/gopoparsify" ) func main() { // JSON-style boolean and null literals _true := Bind("true", true) _false := Bind("false", false) _null := Bind("null", nil) boolNull := Any(_true, _false, _null) for _, input := range []string{"true", "false", "null"} { result, _ := Run(boolNull, input) fmt.Printf("% -5s => %v (%T)\n", input, result, result) } // true => true (bool) // false => false (bool) // null => () } ``` -------------------------------- ### Match one or more repetitions with Some Source: https://context7.com/vektah/goparsify/llms.txt Use `Some` to match a parser one or more times. It collects results in `node.Child`. An optional separator can be provided, which is consumed but not included in the output. Fails on empty input. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Comma-separated list of words, requiring at least one word := Chars("a-zA-Z") list := Some(word, ",").Map(func(n *Result) { words := make([]string, len(n.Child)) for i, c := range n.Child { words[i] = c.Token } n.Result = words }) result, err := Run(list, "foo,bar,baz") if err != nil { panic(err) } fmt.Println(result) // [foo bar baz] // Fails on empty input _, err2 := Run(list, "") fmt.Println(err2) // offset 0: expected !EOF } ``` -------------------------------- ### Arithmetic Expression Calculator Parser Source: https://context7.com/vektah/goparsify/llms.txt Defines parsers for arithmetic operations including addition, subtraction, multiplication, division, and parentheses. It uses grammar layering to handle operator precedence and forward declarations for recursive parsing. This parser is suitable for evaluating mathematical expressions. ```go package calc import ( "fmt" . "github.com/vektah/goparsify" ) var ( value Parser // forward declaration to break cycle sumOp = Chars("+-", 1, 1) prodOp = Chars("/*", 1, 1) groupExpr = Seq("(", &value, ")").Map(func(n *Result) { n.Result = n.Child[1].Result }) number = NumberLit().Map(func(n *Result) { switch i := n.Result.(type) { case int64: n.Result = float64(i) case float64: n.Result = i } }) prod = Seq(&value, Many(Seq(prodOp, &value))).Map(func(n *Result) { i := n.Child[0].Result.(float64) for _, op := range n.Child[1].Child { switch op.Child[0].Token { case "*": i *= op.Child[1].Result.(float64) case "/": i /= op.Child[1].Result.(float64) } } n.Result = i }) sum = Seq(prod, Many(Seq(sumOp, prod))).Map(func(n *Result) { i := n.Child[0].Result.(float64) for _, op := range n.Child[1].Child { switch op.Child[0].Token { case "+": i += op.Child[1].Result.(float64) case "-": i -= op.Child[1].Result.(float64) } } n.Result = i }) ) func init() { value = Any(number, groupExpr) } func Calc(input string) (float64, error) { result, err := Run(Maybe(sum), input) if err != nil { return 0, err } return result.(float64), nil } ``` -------------------------------- ### Define Addition Parser for Calculator Source: https://github.com/vektah/goparsify/blob/master/readme.md Defines a parser for addition and subtraction operations. It maps the parsed structure to calculate the sum or difference. ```go var sumOp = Chars("+-", 1, 1) sum = Seq(number, Some(And(sumOp, number))).Map(func(n Result) Result { i := n.Child[0].Result.(float64) for _, op := range n.Child[1].Child { switch op.Child[0].Token { case "+": i += op.Child[1].Result.(float64) case "-": i -= op.Child[1].Result.(float64) } } return Result{Result: i} }) ``` -------------------------------- ### Match zero or more repetitions with Many Source: https://context7.com/vektah/goparsify/llms.txt Use `Many` to match a parser zero or more times. It functions like `Some` but succeeds even with zero matches, returning an empty `Child` slice. Useful for accumulating results. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { digit := Chars("0-9") digits := Many(digit).Map(func(n *Result) { result := "" for _, c := range n.Child { result += c.Token } n.Result = result }) // Zero matches — succeeds with empty result result, err := Run(Seq(digits, "end"), "end") fmt.Println(result, err) // [ end] // Multiple matches ps := NewState("123abc") var out Result digits(ps, &out) fmt.Println(out.Result) // 123 fmt.Println(ps.Get()) // abc } ``` -------------------------------- ### Define Number Parser for Calculator Source: https://github.com/vektah/goparsify/blob/master/readme.md Defines a parser for numeric literals and a helper function to run parsers. It maps results to float64 for consistent calculator operations. ```go var number = NumberLit().Map(func(n Result) Result { switch i := n.Result.(type) { case int64: return Result{Result: float64(i)} case float64: return Result{Result: i} default: panic(fmt.Errorf("unknown value %#v", i)) } }) func Calc(input string) (float64, error) { result, err := Run(y, input) if err != nil { return 0, err } return result.(float64), nil } ``` -------------------------------- ### Consume Until Terminator Sequence with Until Source: https://context7.com/vektah/goparsify/llms.txt Until consumes bytes until one of the given multi-character terminator strings is found. It matches full sequences rather than individual characters. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Consume until a closing comment marker comment := Seq("/*", Until("*/"), "*/").Map(func(n *Result) { n.Result = n.Child[1].Token }) result, err := Run(comment, "/* hello world */") if err != nil { panic(err) } fmt.Println(result) // " hello world " } ``` -------------------------------- ### Match Until Character Class with NotChars Source: https://context7.com/vektah/goparsify/llms.txt NotChars consumes input as long as characters do not match the given set. Useful for capturing content up to a delimiter character. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Capture everything that isn't a quote content := NotChars(`"`) ps := NewState(`hello world"rest`) var out Result content(ps, &out) fmt.Println(out.Token) // hello world fmt.Println(ps.Get()) // "rest } ``` -------------------------------- ### Prevent Backtracking with Cut Source: https://context7.com/vektah/goparsify/llms.txt Employ `Cut` to establish a point of no return, preventing higher-level `Any` or `Maybe` combinators from backtracking past it. This ensures precise error messages and avoids redundant parsing. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { alpha := Chars("a-z") // Without Cut: causes silent backtrack nocut := Many(Any(Seq("<", alpha, ">"), alpha)) _, err := Run(nocut, "asdf is required — precise error cut := Many(Any(Seq("<", Cut(), alpha, ">"), alpha)) _, err2 := Run(cut, "asdf } ``` -------------------------------- ### Transform Parser Results with Map Source: https://context7.com/vektah/goparsify/llms.txt Use `Map` to apply a callback function after a parser succeeds, converting raw tokens into typed values. This is useful for transforming parsed data into specific types like integers or custom structs. ```go package main import ( "fmt" "strconv" . "github.com/vektah/goparsify" ) func main() { // Parse an integer and store it as int integer := Chars("0-9").Map(func(n *Result) { v, _ := strconv.Atoi(n.Token) n.Result = v }) // Parse a key:value pair and return a struct type Pair struct{ Key, Value string } kv := Seq(Chars("a-zA-Z"), ":", Chars("a-zA-Z0-9")).Map(func(n *Result) { n.Result = Pair{ Key: n.Child[0].Token, Value: n.Child[2].Token, } }) r1, _ := Run(integer, "123") fmt.Printf("%T %v\n", r1, r1) // int 123 r2, _ := Run(kv, "age:42") fmt.Printf("%T %v\n", r2, r2) // main.Pair {age 42} } ``` -------------------------------- ### Disable automatic whitespace skipping with NoAutoWS Source: https://context7.com/vektah/goparsify/llms.txt Use `NoAutoWS` to wrap a parser and disable automatic whitespace consumption for all parsers within it. This is crucial for parsing whitespace-sensitive formats where spaces are significant. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Without NoAutoWS, whitespace between chars is silently consumed withWS := Seq(Chars("a-z"), Chars("a-z")) result, _ := Run(withWS, "hello world") fmt.Println(result) // matches "hello" then "world" (skips space) // With NoAutoWS, the space makes the second Chars fail noWS := NoAutoWS(Seq(Chars("a-z"), Chars("a-z"))) _, err := Run(noWS, "hello world") fmt.Println(err) // left unparsed: world // (first Chars consumed "hello", second stopped at space) _ = result } ``` -------------------------------- ### Match Numeric Literals with NumberLit Source: https://context7.com/vektah/goparsify/llms.txt NumberLit matches integers and floating-point numbers, including scientific notation. It returns int64 for integers and float64 for floats, stored in .Result. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { num := NumberLit() for _, input := range []string{"42", "-7", "3.14", "1.5e10", "+100"} { ps := NewState(input) var out Result num(ps, &out) fmt.Printf("% -8s => %T(%v)\n", input, out.Result, out.Result) } // 42 => int64(42) // -7 => int64(-7) // 3.14 => float64(3.14) // 1.5e10 => float64(1.5e+10) // +100 => int64(100) } ``` -------------------------------- ### Match zero or one occurrence with Maybe Source: https://context7.com/vektah/goparsify/llms.txt Use `Maybe` to optionally match a parser. If the wrapped parser fails, `Maybe` suppresses the error and leaves the parse position unchanged. Useful for optional elements like signs. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Optional leading minus sign followed by digits sign := Maybe(Chars("+-", 1, 1)) digits := Chars("0-9") integer := Seq(sign, digits).Map(func(n *Result) { n.Result = n.Child[0].Token + n.Child[1].Token }) for _, input := range []string{"-42", "+7", "100"} { result, err := Run(integer, input) fmt.Printf("% -5s => %v (err: %v)\n", input, result, err) } // -42 => -42 (err: ) // +7 => +7 (err: ) // 100 => 100 (err: ) } ``` -------------------------------- ### Concatenate Child Tokens with Merge Source: https://context7.com/vektah/goparsify/llms.txt Use `Merge` to recursively flatten all child tokens into a single `Token` string. This is useful for joining multiple token fragments collected by combinators like `Seq`. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Floating point: optional sign + digits + dot + digits floatParser := Merge(Seq( Maybe(Chars("+-", 1, 1)), Chars("0-9"), ".", Chars("0-9"), )) ps := NewState("-3.14rest") var out Result floatParser(ps, &out) fmt.Println(out.Token) // -3.14 fmt.Println(ps.Get()) // rest } ``` -------------------------------- ### Match Quoted String Literals with StringLit Source: https://context7.com/vektah/goparsify/llms.txt StringLit parses a quoted string supporting unicode, escape sequences, and unicode code points. The argument specifies which quote characters are accepted. Escape sequences are resolved. ```go package main import ( "fmt" . "github.com/vektah/goparsify" ) func main() { // Accept only double-quoted strings dq := StringLit(`"`) ps := NewState(`"hello\nworld"`) var out Result dq(ps, &out) fmt.Println(out.Token) // hello\nworld (escape sequences resolved) // Accept single or double quotes anyQuote := StringLit(`"'`) // Note: This line seems to have a typo in the original, should be `"'` or `"'` r1, _ := Run(anyQuote, "'it\'s fine'") fmt.Println(r1) // (use Map; Token has the value) ps2 := NewState("'it\'s fine'") var out2 Result anyQuote(ps2, &out2) fmt.Println(out2.Token) // it's fine // Unicode escape ps3 := NewState(`"\u0041"`) var out3 Result dq(ps3, &out3) fmt.Println(out3.Token) // A _ = r1 } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.