go-parsekit/examples/example_helloSingleStatePar...

109 lines
3.4 KiB
Go

// This is the same as the other hello examples, 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.
//
// Note that things are much easier to implement using custom TokenHandlers (see
// the other helloParserCombinator example for this). Doing this implementation
// is mainly for your learning pleasure.
//
// One big difference between the parser/combinator-based example and this one,
// is that this parser reports errors much more fine-grained. This might or
// might not be useful for your specific use case.
package examples
import (
"fmt"
"git.makaay.nl/mauricem/go-parsekit"
)
func Example_helloWorldUsingParser2() {
parser := &helloparser2{}
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!",
} {
name, err := parser.Parse(input)
if err != nil {
fmt.Printf("[%d] Input: %q Error: %s\n", i, input, err)
} else {
fmt.Printf("[%d] Input: %q Output: %s\n", i, input, name)
}
}
// Output:
// [0] Input: "Hello, world!" Output: world
// [1] Input: "HELLO ,Johnny!" Output: Johnny
// [2] Input: "hello , Bob123!" Output: Bob123
// [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!" Output: Droopy
// [11] Input: "hello , \t \t Droopy \t !" Output: Droopy
// [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 '!'
}
// ---------------------------------------------------------------------------
// Implementation of the parser
// ---------------------------------------------------------------------------
type helloparser2 struct {
greetee string
}
func (h *helloparser2) Parse(input string) (string, *parsekit.Error) {
parser := parsekit.NewParser(h.start)
err := parser.Execute(input)
return h.greetee, err
}
func (h *helloparser2) start(p *parsekit.ParseAPI) {
c, a, m := parsekit.C, parsekit.A, parsekit.M
if !p.On(a.StrNoCase("hello")).Skip() {
p.Error("the greeting is not being friendly")
return
}
if !p.On(c.Seq(c.Opt(a.Whitespace), a.Comma, c.Opt(a.Whitespace))).Skip() {
p.Error("the greeting is not properly separated")
return
}
if p.On(m.TrimSpace(c.OneOrMore(c.Except(a.Excl, a.AnyRune)))).Accept() {
h.greetee = p.Result().String()
if h.greetee == "" {
p.Error("the name cannot be empty")
return
}
} else {
p.Error("the greeting is targeted at thin air")
return
}
if !p.On(a.Excl).Skip() {
p.Error("the greeting is not loud enough")
} else if !p.On(a.EndOfFile).Stay() {
p.Error("too much stuff going on after the closing '!'")
} else {
p.Stop()
}
}