goparsify/combinator_test.go

215 lines
6.0 KiB
Go
Raw Normal View History

2017-08-06 06:31:35 +02:00
package parsec
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestNil(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("hello world", Nil)
2017-08-06 06:31:35 +02:00
require.Equal(t, nil, node)
2017-08-06 15:32:10 +02:00
require.Equal(t, 0, p2.Pos)
require.False(t, p2.Errored())
}
func TestNever(t *testing.T) {
node, p2 := runParser("hello world", Never)
require.Equal(t, nil, node)
require.Equal(t, 0, p2.Pos)
require.True(t, p2.Errored())
2017-08-06 06:31:35 +02:00
}
func TestAnd(t *testing.T) {
2017-08-06 15:32:10 +02:00
parser := And("hello", WS, "world")
2017-08-06 06:31:35 +02:00
t.Run("matches sequence", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("hello world", parser)
require.Equal(t, []interface{}{"hello", "world"}, node)
2017-08-06 07:43:23 +02:00
require.Equal(t, "", p2.Get())
2017-08-06 06:31:35 +02:00
})
t.Run("returns errors", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
_, p2 := runParser("hello there", parser)
require.Equal(t, "world", p2.Error.Expected)
require.Equal(t, 6, p2.Error.pos)
require.Equal(t, 0, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("No parsers", func(t *testing.T) {
assertNilParser(t, And())
})
}
2017-08-06 09:02:39 +02:00
func TestMaybe(t *testing.T) {
t.Run("matches sequence", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("hello world", Maybe("hello"))
2017-08-06 09:02:39 +02:00
require.Equal(t, "hello", node)
require.Equal(t, " world", p2.Get())
})
t.Run("returns no errors", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p3 := runParser("hello world", Maybe("world"))
require.Equal(t, nil, node)
require.False(t, p3.Errored())
require.Equal(t, 0, p3.Pos)
2017-08-06 09:02:39 +02:00
})
}
2017-08-06 06:31:35 +02:00
func TestAny(t *testing.T) {
t.Run("Matches any", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("hello world!", Any("hello", "world"))
2017-08-06 09:02:39 +02:00
require.Equal(t, "hello", node)
2017-08-06 15:32:10 +02:00
require.Equal(t, 5, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("Returns longest error", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
_, p2 := runParser("hello world!", Any(
"nope",
And("hello", WS, "world", "."),
And("hello", WS, "brother"),
))
require.Equal(t, "offset 11: Expected .", p2.Error.Error())
require.Equal(t, 11, p2.Error.Pos())
require.Equal(t, 0, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("Accepts nil matches", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("hello world!", Any(Exact("ffffff"), WS))
2017-08-06 06:31:35 +02:00
require.Equal(t, nil, node)
2017-08-06 15:32:10 +02:00
require.Equal(t, 0, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("No parsers", func(t *testing.T) {
assertNilParser(t, Any())
})
}
func TestKleene(t *testing.T) {
t.Run("Matches sequence with sep", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,", Kleene(Chars("a-g"), ","))
require.False(t, p2.Errored())
require.Equal(t, []interface{}{"a", "b", "c", "d", "e"}, node)
require.Equal(t, 10, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("Matches sequence without sep", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,", Kleene(Any(Chars("a-g"), ",")))
require.Equal(t, []interface{}{"a", ",", "b", ",", "c", ",", "d", ",", "e", ","}, node)
require.Equal(t, 10, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("Stops on error", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,", Kleene(Chars("a-c"), ","))
require.Equal(t, []interface{}{"a", "b", "c"}, node)
require.Equal(t, 6, p2.Pos)
2017-08-06 06:31:35 +02:00
require.Equal(t, "d,e,", p2.Get())
})
}
func TestMany(t *testing.T) {
t.Run("Matches sequence with sep", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,", Many(Chars("a-g"), Exact(",")))
require.Equal(t, []interface{}{"a", "b", "c", "d", "e"}, node)
require.Equal(t, 10, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("Matches sequence without sep", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,", Many(Any(Chars("abcdefg"), Exact(","))))
require.Equal(t, []interface{}{"a", ",", "b", ",", "c", ",", "d", ",", "e", ","}, node)
require.Equal(t, 10, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("Stops on error", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,", Many(Chars("abc"), Exact(",")))
require.Equal(t, []interface{}{"a", "b", "c"}, node)
require.Equal(t, 6, p2.Pos)
2017-08-06 06:31:35 +02:00
require.Equal(t, "d,e,", p2.Get())
})
t.Run("Returns error if nothing matches", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
_, p2 := runParser("a,b,c,d,e,", Many(Chars("def"), Exact(",")))
require.Equal(t, "offset 0: Expected def", p2.Error.Error())
2017-08-06 06:31:35 +02:00
require.Equal(t, "a,b,c,d,e,", p2.Get())
})
}
func TestKleeneUntil(t *testing.T) {
t.Run("Matches sequence with sep", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,fg", KleeneUntil(Chars("abcde"), "d", ","))
require.Equal(t, []interface{}{"a", "b", "c"}, node)
require.Equal(t, "d,e,fg", p2.Get())
2017-08-06 06:31:35 +02:00
})
t.Run("Breaks if separator does not match", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,fg", KleeneUntil(Chars("abcdefg", 1, 1), "y", ","))
require.Equal(t, []interface{}{"a", "b", "c", "d", "e", "f"}, node)
require.Equal(t, "g", p2.Get())
2017-08-06 06:31:35 +02:00
})
}
func TestManyUntil(t *testing.T) {
t.Run("Matches sequence until", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("a,b,c,d,e,", ManyUntil(Chars("abcdefg"), "d", ","))
require.Equal(t, []interface{}{"a", "b", "c"}, node)
require.Equal(t, 6, p2.Pos)
2017-08-06 06:31:35 +02:00
})
t.Run("Returns error until matches early", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
_, p2 := runParser("a,b,c,d,e,", ManyUntil(Chars("abc"), "a", ","))
require.Equal(t, "offset 0: Expected something else", p2.Error.Error())
require.Equal(t, 0, p2.Pos)
2017-08-06 06:31:35 +02:00
require.Equal(t, "a,b,c,d,e,", p2.Get())
})
}
2017-08-06 09:02:39 +02:00
type htmlTag struct {
Name string
}
func TestMap(t *testing.T) {
2017-08-06 15:32:10 +02:00
parser := Map(And("<", Chars("a-zA-Z0-9"), ">"), func(n interface{}) interface{} {
return htmlTag{n.([]interface{})[1].(string)}
2017-08-06 09:02:39 +02:00
})
t.Run("sucess", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
result, _ := runParser("<html>", parser)
2017-08-06 09:02:39 +02:00
require.Equal(t, htmlTag{"html"}, result)
})
t.Run("error", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
_, ps := runParser("<html", parser)
require.Equal(t, "offset 5: Expected >", ps.Error.Error())
require.Equal(t, 0, ps.Pos)
2017-08-06 09:02:39 +02:00
})
}
func TestMerge(t *testing.T) {
var bracer Parser
bracer = And("(", Maybe(&bracer), ")")
parser := Merge(bracer)
t.Run("sucess", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
result, _ := runParser("((()))", parser)
2017-08-06 09:02:39 +02:00
require.Equal(t, "((()))", result)
})
t.Run("error", func(t *testing.T) {
2017-08-06 15:32:10 +02:00
_, ps := runParser("((())", parser)
require.Equal(t, "offset 5: Expected )", ps.Error.Error())
require.Equal(t, 0, ps.Pos)
2017-08-06 09:02:39 +02:00
})
require.Panics(t, func() {
flatten(1)
})
}
2017-08-06 06:31:35 +02:00
func assertNilParser(t *testing.T, parser Parser) {
2017-08-06 15:32:10 +02:00
node, p2 := runParser("fff", parser)
2017-08-06 06:31:35 +02:00
require.Equal(t, nil, node)
2017-08-06 15:32:10 +02:00
require.Equal(t, 0, p2.Pos)
2017-08-06 06:31:35 +02:00
}