diff --git a/examples_test.go b/examples_test.go index 6cdadb2..c031f8b 100644 --- a/examples_test.go +++ b/examples_test.go @@ -7,7 +7,7 @@ import ( "git.makaay.nl/mauricem/go-parsekit" ) -func Example_minimal() { +func Example_minimalAnnotated() { // Let's write a small example for parsing a really basic calculator. // The calculator understands input that looks like: // @@ -65,15 +65,15 @@ func Example_minimal() { } // All is ready for our parser. We now can create a new Parser struct. - // We need to tell it what the start state is. In our case, it's the - // of course the number state. + // We need to tell it what the start state is. In our case, it is + // the number state, since the calculation must start with a number. parser := parsekit.NewParser(numberHandler) - // Let's fee the parser some input to work with. + // Let's feed the parser some input to work with. run := parser.Parse("153+ 22+31 - 4- 6+42") - // We can step through the results of the parsing process by repeated - // calls to run.Next(). Next() returns the next parse item, a parse + // We can now step through the results of the parsing process by repeated + // calls to run.Next(). Next() returns either the next parse item, a parse // error or an end of file. Let's dump the parse results and handle the // computation while we're at it. sum := 0 @@ -118,6 +118,68 @@ func Example_minimal() { // Outcome of computation: 238 } +func Example_minimal() { + var c, a, m = parsekit.C, parsekit.A, parsekit.M + + var number = c.OneOrMore(a.Digit) + var whitespace = m.Drop(c.Opt(a.Whitespace)) + var operator = c.Seq(whitespace, c.Any(a.Plus, a.Minus), whitespace) + + const ( + numberType parsekit.ItemType = iota + operatorType + ) + + var operatorHandler parsekit.StateHandler + + numberHandler := func(p *parsekit.P) { + p.Expects("a number") + if p.On(number).Accept().End() { + p.EmitLiteral(numberType) + p.RouteTo(operatorHandler) + } + } + + operatorHandler = func(p *parsekit.P) { + if p.On(operator).Accept().End() { + p.EmitLiteral(operatorType) + p.RouteTo(numberHandler) + } else { + p.ExpectEndOfFile() + } + } + + parser := parsekit.NewParser(numberHandler) + run := parser.Parse("153+ 22+31 - 4- 6+42") + + sum := 0 + op := +1 + for { + item, err, ok := run.Next() + switch { + case !ok && err == nil: + fmt.Println("Outcome of computation:", sum) + return + case !ok: + fmt.Printf("Error: %s\n", err) + return + default: + switch { + case item.Type == operatorType && item.Value == "+": + op = +1 + case item.Type == operatorType && item.Value == "-": + op = -1 + default: + nr, _ := strconv.Atoi(item.Value) + sum += op * nr + } + } + } + + // Output: + // Outcome of computation: 238 +} + func ExampleItemType() { // Make use of positive values. Ideally, define your ItemTypes using // iota for easy automatic value management like this: