diff --git a/example_hellomatcher_test.go b/example_hellomatcher_test.go index 23debec..da50d83 100644 --- a/example_hellomatcher_test.go +++ b/example_hellomatcher_test.go @@ -41,6 +41,7 @@ func Example_helloWorldUsingMatcher() { "hello Pizza!", "Oh no!", "Hello, world", + "Hello,!", } { output, err, ok := parser.Parse(input) if !ok { @@ -56,4 +57,5 @@ func Example_helloWorldUsingMatcher() { // [3] Input: "hello Pizza!" Output: Pizza // [4] Input: "Oh no!" Error: unexpected character 'O' (expected a friendly greeting) // [5] Input: "Hello, world" Error: unexpected character 'H' (expected a friendly greeting) + // [6] Input: "Hello,!" Error: unexpected character 'H' (expected a friendly greeting) } diff --git a/example_helloparser_test.go b/example_helloparser1_test.go similarity index 98% rename from example_helloparser_test.go rename to example_helloparser1_test.go index baa5403..97fb94c 100644 --- a/example_helloparser_test.go +++ b/example_helloparser1_test.go @@ -67,7 +67,7 @@ func createHelloParser() *parsekit.Parser { return parsekit.NewParser(stateStartOfGreeting) } -func Example_helloWorldUsingParser() { +func Example_helloWorldUsingParser1() { parser := createHelloParser() for i, input := range []string{ diff --git a/example_helloparser2_test.go b/example_helloparser2_test.go new file mode 100644 index 0000000..a125ad4 --- /dev/null +++ b/example_helloparser2_test.go @@ -0,0 +1,91 @@ +// This is the same as the example helloWorldUsingParser1, except that in +// this implementation the state machine is implemented using a combination +// of some TokenHandlers and only a single state, in which multiple +// ParseAPI.On() calls are combined to do all the work in one go. +package parsekit_test + +import ( + "fmt" + + "git.makaay.nl/mauricem/go-parsekit" +) + +const greeteeItem2 parsekit.ItemType = 1 + +func stateFullGreeting(p *parsekit.ParseAPI) { + c, a, m := parsekit.C, parsekit.A, parsekit.M + if !p.On(c.StrNoCase("hello")).Skip() { + p.EmitError("the greeting is not being friendly") + return + } + if !p.On(c.Seq(c.Opt(a.Whitespace), a.Comma, c.Opt(a.Whitespace))).Skip() { + p.EmitError("the greeting is not properly separated") + return + } + if !p.On(m.Trim(c.OneOrMore(c.Except(a.Excl, a.AnyRune)), " \t")).Accept() { + p.EmitError("the greeting is targeted at thin air") + return + } + if !p.On(a.Excl).Stay() { + p.EmitError("the greeting is not loud enough") + return + } + if !p.On(a.EndOfFile).Stay() { + p.EmitError("too much stuff going on after the closing '!'") + return + } + + name := p.BufLiteral() + if name == "" { + p.EmitError("the name cannot be empty") + } else { + p.Emit(greeteeItem, name) + } + + p.ExpectEndOfFile() +} + +func Example_helloWorldUsingParser2() { + parser := parsekit.NewParser(stateFullGreeting) + + for i, input := range []string{ + "Hello, world!", + "HELLO ,Johnny!", + "hello , Bob123!", + "hello Pizza!", + "", + " ", + "hello", + "hello,", + "hello , ", + "hello , Droopy", + "hello , Droopy!", + "hello , \t \t Droopy \t !", + "Oh no!", + "hello,!", + "HELLO, Buster! Eat this!", + } { + item, err, ok := parser.Parse(input).Next() + if !ok { + fmt.Printf("[%d] Input: %q Error: %s\n", i, input, err) + } else { + fmt.Printf("[%d] Input: %q Output: %s\n", i, input, item.Value) + } + } + // Output: + // [0] Input: "Hello, world!" Error: too much stuff going on after the closing '!' + // [1] Input: "HELLO ,Johnny!" Error: too much stuff going on after the closing '!' + // [2] Input: "hello , Bob123!" Error: too much stuff going on after the closing '!' + // [3] Input: "hello Pizza!" Error: the greeting is not properly separated + // [4] Input: "" Error: the greeting is not being friendly + // [5] Input: " " Error: the greeting is not being friendly + // [6] Input: "hello" Error: the greeting is not properly separated + // [7] Input: "hello," Error: the greeting is targeted at thin air + // [8] Input: "hello , " Error: the greeting is targeted at thin air + // [9] Input: "hello , Droopy" Error: the greeting is not loud enough + // [10] Input: "hello , Droopy!" Error: too much stuff going on after the closing '!' + // [11] Input: "hello , \t \t Droopy \t !" Error: too much stuff going on after the closing '!' + // [12] Input: "Oh no!" Error: the greeting is not being friendly + // [13] Input: "hello,!" Error: the greeting is targeted at thin air + // [14] Input: "HELLO, Buster! Eat this!" Error: too much stuff going on after the closing '!' +}