package parsekit_test import ( "fmt" "testing" "git.makaay.nl/mauricem/go-parsekit" ) func ExampleMatchAnyRune(t *testing.T) { parser := parsekit.New( func(p *parsekit.P) { p.Expects("Any valid rune") if p.On(a.AnyRune).Accept().End() { p.EmitLiteral(TestItem) } }) run := parser.Parse("¡Any / valid / character will dö!") match, _, ok := run.Next() if ok { fmt.Printf("Match = %q\n", match) } } func TestCombinators(t *testing.T) { for i, c := range []struct { input string matcher parsekit.Matcher mustMatch bool expected string }{ {"xxx", c.Rune('x'), true, "x"}, {"x ", c.Rune(' '), false, ""}, {"aa", c.RuneRange('b', 'e'), false, ""}, {"bb", c.RuneRange('b', 'e'), true, "b"}, {"cc", c.RuneRange('b', 'e'), true, "c"}, {"dd", c.RuneRange('b', 'e'), true, "d"}, {"ee", c.RuneRange('b', 'e'), true, "e"}, {"ff", c.RuneRange('b', 'e'), false, ""}, {"Hello, world!", c.String("Hello"), true, "Hello"}, {"HellÖ, world!", c.StringNoCase("hellö"), true, "HellÖ"}, {"+X", c.Runes('+', '-', '*', '/'), true, "+"}, {"-X", c.Runes('+', '-', '*', '/'), true, "-"}, {"*X", c.Runes('+', '-', '*', '/'), true, "*"}, {"/X", c.Runes('+', '-', '*', '/'), true, "/"}, {"!X", c.Runes('+', '-', '*', '/'), false, ""}, {"abc", c.Not(c.Rune('b')), true, "a"}, {"bcd", c.Not(c.Rune('b')), false, ""}, {"bcd", c.Not(c.Rune('b')), false, ""}, {"abc", c.AnyOf(c.Rune('a'), c.Rune('b')), true, "a"}, {"bcd", c.AnyOf(c.Rune('a'), c.Rune('b')), true, "b"}, {"cde", c.AnyOf(c.Rune('a'), c.Rune('b')), false, ""}, {"ababc", c.Repeat(4, c.Runes('a', 'b')), true, "abab"}, {"ababc", c.Repeat(5, c.Runes('a', 'b')), false, ""}, {"", c.Min(0, c.Rune('a')), true, ""}, {"a", c.Min(0, c.Rune('a')), true, "a"}, {"aaaaa", c.Min(4, c.Rune('a')), true, "aaaaa"}, {"aaaaa", c.Min(5, c.Rune('a')), true, "aaaaa"}, {"aaaaa", c.Min(6, c.Rune('a')), false, ""}, {"", c.Max(4, c.Rune('b')), true, ""}, {"X", c.Max(4, c.Rune('b')), true, ""}, {"bbbbbX", c.Max(4, c.Rune('b')), true, "bbbb"}, {"bbbbbX", c.Max(5, c.Rune('b')), true, "bbbbb"}, {"bbbbbX", c.Max(6, c.Rune('b')), true, "bbbbb"}, {"", c.MinMax(0, 0, c.Rune('c')), true, ""}, {"X", c.MinMax(0, 0, c.Rune('c')), true, ""}, {"cccccX", c.MinMax(0, 0, c.Rune('c')), true, ""}, {"cccccX", c.MinMax(0, 1, c.Rune('c')), true, "c"}, {"cccccX", c.MinMax(0, 5, c.Rune('c')), true, "ccccc"}, {"cccccX", c.MinMax(0, 6, c.Rune('c')), true, "ccccc"}, {"cccccX", c.MinMax(1, 1, c.Rune('c')), true, "c"}, {"", c.MinMax(1, 1, c.Rune('c')), false, ""}, {"X", c.MinMax(1, 1, c.Rune('c')), false, ""}, {"cccccX", c.MinMax(1, 3, c.Rune('c')), true, "ccc"}, {"cccccX", c.MinMax(1, 6, c.Rune('c')), true, "ccccc"}, {"cccccX", c.MinMax(3, 4, c.Rune('c')), true, "cccc"}, {"", c.OneOrMore(c.Rune('d')), false, ""}, {"X", c.OneOrMore(c.Rune('d')), false, ""}, {"dX", c.OneOrMore(c.Rune('d')), true, "d"}, {"dddddX", c.OneOrMore(c.Rune('d')), true, "ddddd"}, {"", c.ZeroOrMore(c.Rune('e')), true, ""}, {"X", c.ZeroOrMore(c.Rune('e')), true, ""}, {"eX", c.ZeroOrMore(c.Rune('e')), true, "e"}, {"eeeeeX", c.ZeroOrMore(c.Rune('e')), true, "eeeee"}, {"Hello, world!X", c.Sequence(c.String("Hello"), a.Comma, a.Space, c.String("world"), a.Excl), true, "Hello, world!"}, {"101010123", c.OneOrMore(c.Sequence(c.Rune('1'), c.Rune('0'))), true, "101010"}, {"", c.Optional(c.OneOrMore(c.Rune('f'))), true, ""}, {"ghijkl", c.Optional(c.Rune('h')), true, ""}, {"ghijkl", c.Optional(c.Rune('g')), true, "g"}, {"fffffX", c.Optional(c.OneOrMore(c.Rune('f'))), true, "fffff"}, {"--cool", c.Sequence(c.Drop(c.OneOrMore(a.Minus)), c.String("cool")), true, "cool"}, {"1,2,3,b,c", c.Separated(a.Comma, a.Digit), true, "1,2,3"}, {`\x9a\x01\xF0\xfCAndSomeMoreStuff`, c.OneOrMore(c.Sequence(a.Backslash, c.Rune('x'), c.Repeat(2, a.HexDigit))), true, `\x9a\x01\xF0\xfC`}, } { parser := parsekit.New(c.matcher).Parse(c.input) item, err, ok := parser.Next() if c.mustMatch { if !ok { t.Errorf("Test [%d] %q failed with error: %s", i+1, c.input, err) } else if item.Type != parsekit.MatchedItem { t.Errorf("Test [%d] %q failed: should match, but it didn't", i+1, c.input) } else if item.Value != c.expected { t.Errorf("Test [%d] %q failed: not expected output:\nexpected: %s\nactual: %s\n", i, c.input, c.expected, item.Value) } } else { if ok { t.Errorf("Test [%d] %q failed: should not match, but it did", i+1, c.input) } } } }