Fast single byte matcher

This commit is contained in:
Adam Scarr 2017-08-07 21:57:12 +10:00
parent 88aaf567a5
commit b4f5fb423e
2 changed files with 28 additions and 1 deletions

View File

@ -81,6 +81,21 @@ func ParseString(parser Parserish, input string) (result interface{}, remaining
} }
func Exact(match string) Parser { func Exact(match string) Parser {
if len(match) == 1 {
matchByte := match[0]
return NewParser(match, func(ps *State) Node {
ps.AutoWS()
if ps.Input[ps.Pos] != matchByte {
ps.ErrorHere(match)
return Node{}
}
ps.Advance(1)
return Node{Token: match}
})
}
return NewParser(match, func(ps *State) Node { return NewParser(match, func(ps *State) Node {
ps.AutoWS() ps.AutoWS()
if !strings.HasPrefix(ps.Get(), match) { if !strings.HasPrefix(ps.Get(), match) {

View File

@ -49,17 +49,29 @@ func TestParsifyAll(t *testing.T) {
} }
func TestExact(t *testing.T) { func TestExact(t *testing.T) {
t.Run("success", func(t *testing.T) { t.Run("success string", func(t *testing.T) {
node, ps := runParser("foobar", Exact("fo")) node, ps := runParser("foobar", Exact("fo"))
require.Equal(t, "fo", node.Token) require.Equal(t, "fo", node.Token)
require.Equal(t, "obar", ps.Get()) require.Equal(t, "obar", ps.Get())
}) })
t.Run("success char", func(t *testing.T) {
node, ps := runParser("foobar", Exact("f"))
require.Equal(t, "f", node.Token)
require.Equal(t, "oobar", ps.Get())
})
t.Run("error", func(t *testing.T) { t.Run("error", func(t *testing.T) {
_, ps := runParser("foobar", Exact("bar")) _, ps := runParser("foobar", Exact("bar"))
require.Equal(t, "bar", ps.Error.Expected) require.Equal(t, "bar", ps.Error.Expected)
require.Equal(t, 0, ps.Pos) require.Equal(t, 0, ps.Pos)
}) })
t.Run("error char", func(t *testing.T) {
_, ps := runParser("foobar", Exact("o"))
require.Equal(t, "o", ps.Error.Expected)
require.Equal(t, 0, ps.Pos)
})
} }
func TestChars(t *testing.T) { func TestChars(t *testing.T) {