refactor test harness
This commit is contained in:
parent
0e236fb688
commit
a09675fc27
10
boot.go
10
boot.go
@ -187,21 +187,17 @@ func defineAllBoot(s *Syntax, defs [][]string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initBoot(definitions [][]string) (*Syntax, error) {
|
func createBoot() (*Syntax, error) {
|
||||||
s := NewSyntax()
|
s := NewSyntax()
|
||||||
if err := defineAllBoot(s, definitions); err != nil {
|
if err := defineAllBoot(s, bootSyntaxDefs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, s.Init()
|
return s, s.Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createBoot() (*Syntax, error) {
|
|
||||||
return initBoot(bootSyntaxDefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func bootSyntax() (*Syntax, error) {
|
func bootSyntax() (*Syntax, error) {
|
||||||
b, err := initBoot(bootSyntaxDefs)
|
b, err := createBoot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func testParseFromTree(t *testing.T, n *Node, f io.ReadSeeker) *Node {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNode(t, nn, n)
|
checkNode(t, false, nn, n)
|
||||||
return nn
|
return nn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
69
check_test.go
Normal file
69
check_test.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package treerack
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func checkNodes(t *testing.T, ignorePosition bool, left, right []*Node) {
|
||||||
|
if len(left) != len(right) {
|
||||||
|
t.Error("length doesn't match", len(left), len(right))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(left) > 0 {
|
||||||
|
checkNode(t, ignorePosition, left[0], right[0])
|
||||||
|
if t.Failed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
left, right = left[1:], right[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkNode(t *testing.T, ignorePosition bool, left, right *Node) {
|
||||||
|
if (left == nil) != (right == nil) {
|
||||||
|
t.Error("nil reference doesn't match", left == nil, right == nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if left == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if left.Name != right.Name {
|
||||||
|
t.Error("name doesn't match", left.Name, right.Name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignorePosition && left.From != right.From {
|
||||||
|
t.Error("from doesn't match", left.Name, left.From, right.From)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignorePosition && left.To != right.To {
|
||||||
|
t.Error("to doesn't match", left.Name, left.To, right.To)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(left.Nodes) != len(right.Nodes) {
|
||||||
|
t.Error("length doesn't match", left.Name, len(left.Nodes), len(right.Nodes))
|
||||||
|
t.Log(left)
|
||||||
|
t.Log(right)
|
||||||
|
for {
|
||||||
|
if len(left.Nodes) > 0 {
|
||||||
|
t.Log("<", left.Nodes[0])
|
||||||
|
left.Nodes = left.Nodes[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(right.Nodes) > 0 {
|
||||||
|
t.Log(">", right.Nodes[0])
|
||||||
|
right.Nodes = right.Nodes[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(left.Nodes) == 0 && len(right.Nodes) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNodes(t, ignorePosition, left.Nodes, right.Nodes)
|
||||||
|
}
|
@ -724,10 +724,12 @@ func eskipTreeToEskip(n *Node) ([]*eskip.Route, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEskip(t *testing.T) {
|
func TestEskip(t *testing.T) {
|
||||||
r := generateEskip(1 << 9)
|
const count = 1 << 9
|
||||||
|
|
||||||
|
r := generateEskip(count)
|
||||||
e := eskip.Print(true, r...)
|
e := eskip.Print(true, r...)
|
||||||
b := bytes.NewBufferString(e)
|
b := bytes.NewBufferString(e)
|
||||||
s, err := testSyntax("eskip.parser", -1)
|
s, err := openSyntaxFile("eskip.parser")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
20
json_test.go
20
json_test.go
@ -285,8 +285,8 @@ func jsonTreeToJSON(n *Node) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestJSON(t *testing.T) {
|
func TestJSON(t *testing.T) {
|
||||||
test(t, "json.parser", "value", []testItem{{
|
runTestsFile(t, "json.parser", []testItem{{
|
||||||
msg: "true",
|
title: "true",
|
||||||
text: "true",
|
text: "true",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
@ -296,7 +296,7 @@ func TestJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "false",
|
title: "false",
|
||||||
text: "false",
|
text: "false",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
@ -306,7 +306,7 @@ func TestJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "null",
|
title: "null",
|
||||||
text: "null",
|
text: "null",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
@ -316,7 +316,7 @@ func TestJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "string",
|
title: "string",
|
||||||
text: `"\"\\n\b\t\uabcd"`,
|
text: `"\"\\n\b\t\uabcd"`,
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
@ -326,7 +326,7 @@ func TestJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "number",
|
title: "number",
|
||||||
text: "6.62e-34",
|
text: "6.62e-34",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
@ -336,7 +336,7 @@ func TestJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "object",
|
title: "object",
|
||||||
text: `{
|
text: `{
|
||||||
"true": true,
|
"true": true,
|
||||||
"false": false,
|
"false": false,
|
||||||
@ -404,7 +404,7 @@ func TestJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "array",
|
title: "array",
|
||||||
text: `[true, false, null, "string", 42, {
|
text: `[true, false, null, "string", 42, {
|
||||||
"true": true,
|
"true": true,
|
||||||
"false": false,
|
"false": false,
|
||||||
@ -487,7 +487,7 @@ func TestJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "bugfix, 100",
|
title: "bugfix, 100",
|
||||||
text: "100",
|
text: "100",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
@ -509,7 +509,7 @@ func TestRandomJSON(t *testing.T) {
|
|||||||
|
|
||||||
buf := bytes.NewBuffer(b)
|
buf := bytes.NewBuffer(b)
|
||||||
|
|
||||||
s, err := testSyntax("json.parser", -1)
|
s, err := openSyntaxFile("json.parser")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -3,13 +3,13 @@ package treerack
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestKeyVal(t *testing.T) {
|
func TestKeyVal(t *testing.T) {
|
||||||
test(t, "keyval.parser", "doc", []testItem{{
|
runTestsFile(t, "keyval.parser", []testItem{{
|
||||||
msg: "empty",
|
title: "empty",
|
||||||
}, {
|
}, {
|
||||||
msg: "a comment",
|
title: "a comment",
|
||||||
text: "# a comment",
|
text: "# a comment",
|
||||||
}, {
|
}, {
|
||||||
msg: "a key",
|
title: "a key",
|
||||||
text: "a key",
|
text: "a key",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
@ -24,7 +24,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "a key with a preceeding whitespace",
|
title: "a key with a preceeding whitespace",
|
||||||
text: " a key",
|
text: " a key",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
@ -42,7 +42,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "a key and a comment",
|
title: "a key and a comment",
|
||||||
text: `
|
text: `
|
||||||
# a comment
|
# a comment
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "a key value pair",
|
title: "a key value pair",
|
||||||
text: "a key = a value",
|
text: "a key = a value",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
@ -83,7 +83,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "key value pairs with a comment at the end of line",
|
title: "key value pairs with a comment at the end of line",
|
||||||
text: `
|
text: `
|
||||||
a key = a value # a comment
|
a key = a value # a comment
|
||||||
another key = another value # another comment
|
another key = another value # another comment
|
||||||
@ -126,7 +126,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "value without a key",
|
title: "value without a key",
|
||||||
text: "= a value",
|
text: "= a value",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
@ -138,7 +138,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "a key value pair with comment",
|
title: "a key value pair with comment",
|
||||||
text: `
|
text: `
|
||||||
# a comment
|
# a comment
|
||||||
a key = a value
|
a key = a value
|
||||||
@ -167,7 +167,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "a key with multiple symbols",
|
title: "a key with multiple symbols",
|
||||||
text: "a key . with.multiple.symbols=a value",
|
text: "a key . with.multiple.symbols=a value",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
@ -200,7 +200,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "a group key",
|
title: "a group key",
|
||||||
text: `
|
text: `
|
||||||
# a comment
|
# a comment
|
||||||
[a group key.empty]
|
[a group key.empty]
|
||||||
@ -224,7 +224,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "a group key with multiple values",
|
title: "a group key with multiple values",
|
||||||
text: `
|
text: `
|
||||||
[foo.bar.baz]
|
[foo.bar.baz]
|
||||||
= one
|
= one
|
||||||
@ -258,7 +258,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "a group key with multiple values, in a single line",
|
title: "a group key with multiple values, in a single line",
|
||||||
text: "[foo.bar.baz] = one = two = three",
|
text: "[foo.bar.baz] = one = two = three",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "group-key",
|
Name: "group-key",
|
||||||
@ -287,7 +287,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "full example",
|
title: "full example",
|
||||||
text: `
|
text: `
|
||||||
# a keyval document
|
# a keyval document
|
||||||
|
|
||||||
|
252
mml_test.go
252
mml_test.go
@ -9,11 +9,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMML(t *testing.T) {
|
func TestMML(t *testing.T) {
|
||||||
testTrace(t, "mml.parser", "mml", 1, []testItem{{
|
runTestsFile(t, "mml.parser", []testItem{{
|
||||||
msg: "empty",
|
title: "empty",
|
||||||
node: &Node{Name: "mml"},
|
node: &Node{Name: "mml"},
|
||||||
}, {
|
}, {
|
||||||
msg: "single line comment",
|
title: "single line comment",
|
||||||
text: "// foo bar baz",
|
text: "// foo bar baz",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
@ -25,7 +25,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "multiple line comments",
|
title: "multiple line comments",
|
||||||
text: "// foo bar\n// baz qux",
|
text: "// foo bar\n// baz qux",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
@ -41,7 +41,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "block comment",
|
title: "block comment",
|
||||||
text: "/* foo bar baz */",
|
text: "/* foo bar baz */",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
@ -53,7 +53,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "block comments",
|
title: "block comments",
|
||||||
text: "/* foo bar */\n/* baz qux */",
|
text: "/* foo bar */\n/* baz qux */",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
@ -69,7 +69,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "mixed comments",
|
title: "mixed comments",
|
||||||
text: "// foo\n/* bar */\n// baz",
|
text: "// foo\n/* bar */\n// baz",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
@ -89,14 +89,14 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "int",
|
title: "int",
|
||||||
text: "42",
|
text: "42",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "int",
|
Name: "int",
|
||||||
To: 2,
|
To: 2,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "ints",
|
title: "ints",
|
||||||
text: "1; 2; 3",
|
text: "1; 2; 3",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "int",
|
Name: "int",
|
||||||
@ -111,133 +111,133 @@ func TestMML(t *testing.T) {
|
|||||||
To: 7,
|
To: 7,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "int, octal",
|
title: "int, octal",
|
||||||
text: "052",
|
text: "052",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "int",
|
Name: "int",
|
||||||
To: 3,
|
To: 3,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "int, hexa",
|
title: "int, hexa",
|
||||||
text: "0x2a",
|
text: "0x2a",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "int",
|
Name: "int",
|
||||||
To: 4,
|
To: 4,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, 0.",
|
title: "float, 0.",
|
||||||
text: "0.",
|
text: "0.",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 2,
|
To: 2,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, 72.40",
|
title: "float, 72.40",
|
||||||
text: "72.40",
|
text: "72.40",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 5,
|
To: 5,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, 072.40",
|
title: "float, 072.40",
|
||||||
text: "072.40",
|
text: "072.40",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 6,
|
To: 6,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, 2.71828",
|
title: "float, 2.71828",
|
||||||
text: "2.71828",
|
text: "2.71828",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 7,
|
To: 7,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, 6.67428e-11",
|
title: "float, 6.67428e-11",
|
||||||
text: "6.67428e-11",
|
text: "6.67428e-11",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 11,
|
To: 11,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, 1E6",
|
title: "float, 1E6",
|
||||||
text: "1E6",
|
text: "1E6",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 3,
|
To: 3,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, .25",
|
title: "float, .25",
|
||||||
text: ".25",
|
text: ".25",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 3,
|
To: 3,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float, .12345E+5",
|
title: "float, .12345E+5",
|
||||||
text: ".12345E+5",
|
text: ".12345E+5",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "float",
|
Name: "float",
|
||||||
To: 9,
|
To: 9,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "string, empty",
|
title: "string, empty",
|
||||||
text: "\"\"",
|
text: "\"\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
To: 2,
|
To: 2,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "string",
|
title: "string",
|
||||||
text: "\"foo\"",
|
text: "\"foo\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
To: 5,
|
To: 5,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "string, with new line",
|
title: "string, with new line",
|
||||||
text: "\"foo\nbar\"",
|
text: "\"foo\nbar\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
To: 9,
|
To: 9,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "string, with escaped new line",
|
title: "string, with escaped new line",
|
||||||
text: "\"foo\\nbar\"",
|
text: "\"foo\\nbar\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
To: 10,
|
To: 10,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "string, with quotes",
|
title: "string, with quotes",
|
||||||
text: "\"foo \\\"bar\\\" baz\"",
|
text: "\"foo \\\"bar\\\" baz\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
To: 17,
|
To: 17,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "bool, true",
|
title: "bool, true",
|
||||||
text: "true",
|
text: "true",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "true",
|
Name: "true",
|
||||||
To: 4,
|
To: 4,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "bool, false",
|
title: "bool, false",
|
||||||
text: "false",
|
text: "false",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "false",
|
Name: "false",
|
||||||
To: 5,
|
To: 5,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "symbol",
|
title: "symbol",
|
||||||
text: "foo",
|
text: "foo",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
To: 3,
|
To: 3,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "dynamic-symbol",
|
title: "dynamic-symbol",
|
||||||
text: "symbol(a)",
|
text: "symbol(a)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "dynamic-symbol",
|
Name: "dynamic-symbol",
|
||||||
@ -249,14 +249,14 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "empty list",
|
title: "empty list",
|
||||||
text: "[]",
|
text: "[]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
To: 2,
|
To: 2,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "list",
|
title: "list",
|
||||||
text: "[a, b, c]",
|
text: "[a, b, c]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
@ -276,7 +276,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "list, new lines",
|
title: "list, new lines",
|
||||||
text: `[
|
text: `[
|
||||||
a
|
a
|
||||||
b
|
b
|
||||||
@ -300,7 +300,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "list, complex",
|
title: "list, complex",
|
||||||
text: "[a, b, c..., [d, e], [f, [g]]...]",
|
text: "[a, b, c..., [d, e], [f, [g]]...]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
@ -361,7 +361,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "mutable list",
|
title: "mutable list",
|
||||||
text: "~[a, b, c]",
|
text: "~[a, b, c]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "mutable-list",
|
Name: "mutable-list",
|
||||||
@ -381,14 +381,14 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "empty struct",
|
title: "empty struct",
|
||||||
text: "{}",
|
text: "{}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "struct",
|
Name: "struct",
|
||||||
To: 2,
|
To: 2,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "struct",
|
title: "struct",
|
||||||
text: "{foo: 1, \"bar\": 2, symbol(baz): 3, [qux]: 4}",
|
text: "{foo: 1, \"bar\": 2, symbol(baz): 3, [qux]: 4}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "struct",
|
Name: "struct",
|
||||||
@ -458,7 +458,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "struct, complex",
|
title: "struct, complex",
|
||||||
text: "{foo: 1, {bar: 2}..., {baz: {}}...}",
|
text: "{foo: 1, {bar: 2}..., {baz: {}}...}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "struct",
|
Name: "struct",
|
||||||
@ -525,7 +525,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "struct with indexer key",
|
title: "struct with indexer key",
|
||||||
text: "{[a]: b}",
|
text: "{[a]: b}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "struct",
|
Name: "struct",
|
||||||
@ -551,7 +551,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "mutable struct",
|
title: "mutable struct",
|
||||||
text: "~{foo: 1}",
|
text: "~{foo: 1}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "mutable-struct",
|
Name: "mutable-struct",
|
||||||
@ -572,14 +572,14 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "channel",
|
title: "channel",
|
||||||
text: "<>",
|
text: "<>",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "channel",
|
Name: "channel",
|
||||||
To: 2,
|
To: 2,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "buffered channel",
|
title: "buffered channel",
|
||||||
text: "<42>",
|
text: "<42>",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "channel",
|
Name: "channel",
|
||||||
@ -591,7 +591,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "and expression",
|
title: "and expression",
|
||||||
text: "and(a, b, c)",
|
text: "and(a, b, c)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -614,7 +614,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "or expression",
|
title: "or expression",
|
||||||
text: "or(a, b, c)",
|
text: "or(a, b, c)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -637,7 +637,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function",
|
title: "function",
|
||||||
text: "fn () 42",
|
text: "fn () 42",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function",
|
Name: "function",
|
||||||
@ -649,7 +649,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function, noop",
|
title: "function, noop",
|
||||||
text: "fn () {;}",
|
text: "fn () {;}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function",
|
Name: "function",
|
||||||
@ -661,7 +661,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function with args",
|
title: "function with args",
|
||||||
text: "fn (a, b, c) [a, b, c]",
|
text: "fn (a, b, c) [a, b, c]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function",
|
Name: "function",
|
||||||
@ -698,7 +698,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function with args in new lines",
|
title: "function with args in new lines",
|
||||||
text: `fn (
|
text: `fn (
|
||||||
a
|
a
|
||||||
b
|
b
|
||||||
@ -739,7 +739,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function with spread arg",
|
title: "function with spread arg",
|
||||||
text: "fn (a, b, ...c) [a, b, c]",
|
text: "fn (a, b, ...c) [a, b, c]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function",
|
Name: "function",
|
||||||
@ -781,7 +781,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "effect",
|
title: "effect",
|
||||||
text: "fn ~ () 42",
|
text: "fn ~ () 42",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "effect",
|
Name: "effect",
|
||||||
@ -793,7 +793,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "indexer",
|
title: "indexer",
|
||||||
text: "a[42]",
|
text: "a[42]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -808,7 +808,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "range indexer",
|
title: "range indexer",
|
||||||
text: "a[3:9]",
|
text: "a[3:9]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -837,7 +837,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "range indexer, lower unbound",
|
title: "range indexer, lower unbound",
|
||||||
text: "a[:9]",
|
text: "a[:9]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -857,7 +857,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "range indexer, upper unbound",
|
title: "range indexer, upper unbound",
|
||||||
text: "a[3:]",
|
text: "a[3:]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -877,7 +877,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "indexer, chained",
|
title: "indexer, chained",
|
||||||
text: "a[b][c][d]",
|
text: "a[b][c][d]",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -908,7 +908,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "symbol indexer",
|
title: "symbol indexer",
|
||||||
text: "a.b",
|
text: "a.b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -923,7 +923,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "symbol indexer, with string",
|
title: "symbol indexer, with string",
|
||||||
text: "a.\"b\"",
|
text: "a.\"b\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -938,7 +938,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "symbol indexer, with dynamic symbol",
|
title: "symbol indexer, with dynamic symbol",
|
||||||
text: "a.symbol(b)",
|
text: "a.symbol(b)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -958,7 +958,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "chained symbol indexer",
|
title: "chained symbol indexer",
|
||||||
text: "a.b.c.d",
|
text: "a.b.c.d",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -989,7 +989,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "chained symbol indexer on new line",
|
title: "chained symbol indexer on new line",
|
||||||
text: "a\n.b\n.c",
|
text: "a\n.b\n.c",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -1012,7 +1012,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "chained symbol indexer on new line after dot",
|
title: "chained symbol indexer on new line after dot",
|
||||||
text: "a.\nb.\nc",
|
text: "a.\nb.\nc",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
@ -1035,7 +1035,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "float on a new line",
|
title: "float on a new line",
|
||||||
text: "f()\n.9",
|
text: "f()\n.9",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1047,7 +1047,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "function application",
|
title: "function application",
|
||||||
text: "f()",
|
text: "f()",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1058,7 +1058,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function application, single arg",
|
title: "function application, single arg",
|
||||||
text: "f(a)",
|
text: "f(a)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1073,7 +1073,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function application, multiple args",
|
title: "function application, multiple args",
|
||||||
text: "f(a, b, c)",
|
text: "f(a, b, c)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1096,7 +1096,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function application, multiple args, new line",
|
title: "function application, multiple args, new line",
|
||||||
text: "f(a\nb\nc\n)",
|
text: "f(a\nb\nc\n)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1119,7 +1119,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "function application, spread",
|
title: "function application, spread",
|
||||||
text: "f(a, b..., c, d...)",
|
text: "f(a, b..., c, d...)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1156,7 +1156,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "chained function application",
|
title: "chained function application",
|
||||||
text: "f(a)(b)(c)",
|
text: "f(a)(b)(c)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1187,7 +1187,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "embedded function application",
|
title: "embedded function application",
|
||||||
text: "f(g(h(a)))",
|
text: "f(g(h(a)))",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -1220,7 +1220,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "if",
|
title: "if",
|
||||||
text: "if a { b() }",
|
text: "if a { b() }",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "if",
|
Name: "if",
|
||||||
@ -1246,7 +1246,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "if, else",
|
title: "if, else",
|
||||||
text: "if a { b } else { c }",
|
text: "if a { b } else { c }",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "if",
|
Name: "if",
|
||||||
@ -1276,7 +1276,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "if, else if, else if, else",
|
title: "if, else if, else if, else",
|
||||||
text: `
|
text: `
|
||||||
if a { b }
|
if a { b }
|
||||||
else if c { d }
|
else if c { d }
|
||||||
@ -1338,7 +1338,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "switch, empty",
|
title: "switch, empty",
|
||||||
text: "switch {default:}",
|
text: "switch {default:}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "switch",
|
Name: "switch",
|
||||||
@ -1350,7 +1350,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "switch, empty cases",
|
title: "switch, empty cases",
|
||||||
text: `
|
text: `
|
||||||
switch {
|
switch {
|
||||||
case a:
|
case a:
|
||||||
@ -1382,7 +1382,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "switch, single case",
|
title: "switch, single case",
|
||||||
text: "switch a {case b: c}",
|
text: "switch a {case b: c}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "switch",
|
Name: "switch",
|
||||||
@ -1407,7 +1407,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "switch",
|
title: "switch",
|
||||||
text: "switch a {case b: c; case d: e; default: f}",
|
text: "switch a {case b: c; case d: e; default: f}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "switch",
|
Name: "switch",
|
||||||
@ -1453,7 +1453,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "switch, all new lines",
|
title: "switch, all new lines",
|
||||||
text: `switch
|
text: `switch
|
||||||
a
|
a
|
||||||
{
|
{
|
||||||
@ -1513,7 +1513,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "match expression, empty",
|
title: "match expression, empty",
|
||||||
text: "match a {}",
|
text: "match a {}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "match",
|
Name: "match",
|
||||||
@ -1525,7 +1525,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "match expression",
|
title: "match expression",
|
||||||
text: `match a {
|
text: `match a {
|
||||||
case [first, ...rest]: first
|
case [first, ...rest]: first
|
||||||
}`,
|
}`,
|
||||||
@ -1581,7 +1581,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "match expression, multiple cases",
|
title: "match expression, multiple cases",
|
||||||
text: `match a {
|
text: `match a {
|
||||||
case [0]: []
|
case [0]: []
|
||||||
case [2:]: a[2:]
|
case [2:]: a[2:]
|
||||||
@ -1647,7 +1647,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "match function",
|
title: "match function",
|
||||||
text: `match a {
|
text: `match a {
|
||||||
case fn () int: a()
|
case fn () int: a()
|
||||||
default: 42
|
default: 42
|
||||||
@ -1677,7 +1677,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "match expression, combined",
|
title: "match expression, combined",
|
||||||
text: `match a {
|
text: `match a {
|
||||||
case [fn (int)]: a[0]()
|
case [fn (int)]: a[0]()
|
||||||
default: 42
|
default: 42
|
||||||
@ -1721,7 +1721,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "match expression, complex",
|
title: "match expression, complex",
|
||||||
text: `match a {
|
text: `match a {
|
||||||
case [first T int|string, op fn ([T, int, ...T]) int, ...rest T]:
|
case [first T int|string, op fn ([T, int, ...T]) int, ...rest T]:
|
||||||
op([first, now(), rest...])
|
op([first, now(), rest...])
|
||||||
@ -1832,7 +1832,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "receive op",
|
title: "receive op",
|
||||||
text: "<-chan",
|
text: "<-chan",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "unary-expression",
|
Name: "unary-expression",
|
||||||
@ -1845,7 +1845,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "send op",
|
title: "send op",
|
||||||
text: "chan <- a",
|
text: "chan <- a",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "send",
|
Name: "send",
|
||||||
@ -1857,7 +1857,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "select, empty",
|
title: "select, empty",
|
||||||
text: `select {
|
text: `select {
|
||||||
}`,
|
}`,
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
@ -1865,7 +1865,7 @@ func TestMML(t *testing.T) {
|
|||||||
To: 12,
|
To: 12,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "select",
|
title: "select",
|
||||||
text: `select {
|
text: `select {
|
||||||
case let a <-r: s <- a
|
case let a <-r: s <- a
|
||||||
case s <- f(): g()
|
case s <- f(): g()
|
||||||
@ -1922,7 +1922,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "select, call",
|
title: "select, call",
|
||||||
text: `select {
|
text: `select {
|
||||||
case let a receive(r): f()
|
case let a receive(r): f()
|
||||||
case send(s, g()): h()
|
case send(s, g()): h()
|
||||||
@ -1977,7 +1977,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "block",
|
title: "block",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
text: "{ f() }",
|
text: "{ f() }",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
@ -1990,7 +1990,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "go",
|
title: "go",
|
||||||
text: "go f()",
|
text: "go f()",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "go",
|
Name: "go",
|
||||||
@ -2003,7 +2003,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "go, block",
|
title: "go, block",
|
||||||
text: "go { for { f() } }",
|
text: "go { for { f() } }",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "go",
|
Name: "go",
|
||||||
@ -2025,7 +2025,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "require, dot, equal",
|
title: "require, dot, equal",
|
||||||
text: "require . = \"mml/foo\"",
|
text: "require . = \"mml/foo\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "require",
|
Name: "require",
|
||||||
@ -2040,7 +2040,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "require, symbol, equal",
|
title: "require, symbol, equal",
|
||||||
text: "require bar = \"mml/foo\"",
|
text: "require bar = \"mml/foo\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "require",
|
Name: "require",
|
||||||
@ -2055,7 +2055,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "require, symbol",
|
title: "require, symbol",
|
||||||
text: "require bar \"mml/foo\"",
|
text: "require bar \"mml/foo\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "require",
|
Name: "require",
|
||||||
@ -2070,7 +2070,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "require",
|
title: "require",
|
||||||
text: "require \"mml/foo\"",
|
text: "require \"mml/foo\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "require",
|
Name: "require",
|
||||||
@ -2083,7 +2083,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "require, group",
|
title: "require, group",
|
||||||
text: `require (
|
text: `require (
|
||||||
. = "mml/foo"
|
. = "mml/foo"
|
||||||
bar = "mml/foo"
|
bar = "mml/foo"
|
||||||
@ -2130,7 +2130,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "expression group",
|
title: "expression group",
|
||||||
text: "(fn (a) a)(a)",
|
text: "(fn (a) a)(a)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-application",
|
Name: "function-application",
|
||||||
@ -2147,7 +2147,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "unary operator",
|
title: "unary operator",
|
||||||
text: "!foo",
|
text: "!foo",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "unary-expression",
|
Name: "unary-expression",
|
||||||
@ -2159,7 +2159,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "binary 0",
|
title: "binary 0",
|
||||||
text: "a * b",
|
text: "a * b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "binary0",
|
Name: "binary0",
|
||||||
@ -2173,7 +2173,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "binary 1",
|
title: "binary 1",
|
||||||
text: "a * b + c * d",
|
text: "a * b + c * d",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "binary1",
|
Name: "binary1",
|
||||||
@ -2201,7 +2201,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "binary 2",
|
title: "binary 2",
|
||||||
text: "a * b + c * d == e * f",
|
text: "a * b + c * d == e * f",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "binary2",
|
Name: "binary2",
|
||||||
@ -2243,7 +2243,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "binary 3, 4, 5",
|
title: "binary 3, 4, 5",
|
||||||
text: "a * b + c * d == e * f && g || h -> f()",
|
text: "a * b + c * d == e * f && g || h -> f()",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "binary5",
|
Name: "binary5",
|
||||||
@ -2309,7 +2309,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "ternary expression",
|
title: "ternary expression",
|
||||||
text: "a ? b : c",
|
text: "a ? b : c",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "ternary-expression",
|
Name: "ternary-expression",
|
||||||
@ -2328,7 +2328,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "multiple ternary expressions, consequence",
|
title: "multiple ternary expressions, consequence",
|
||||||
text: "a ? b ? c : d : e",
|
text: "a ? b ? c : d : e",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "ternary-expression",
|
Name: "ternary-expression",
|
||||||
@ -2360,7 +2360,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "multiple ternary expressions, alternative",
|
title: "multiple ternary expressions, alternative",
|
||||||
text: "a ? b : c ? d : e",
|
text: "a ? b : c ? d : e",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "ternary-expression",
|
Name: "ternary-expression",
|
||||||
@ -2392,7 +2392,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
msg: "infinite loop",
|
title: "infinite loop",
|
||||||
text: "for {}",
|
text: "for {}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "loop",
|
Name: "loop",
|
||||||
@ -2402,7 +2402,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "conditional loop",
|
title: "conditional loop",
|
||||||
text: "for foo {}",
|
text: "for foo {}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "loop",
|
Name: "loop",
|
||||||
@ -2417,7 +2417,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "in list loop",
|
title: "in list loop",
|
||||||
text: "for i in [1, 2, 3] {}",
|
text: "for i in [1, 2, 3] {}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "loop",
|
Name: "loop",
|
||||||
@ -2444,7 +2444,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "in range loop",
|
title: "in range loop",
|
||||||
text: "for i in -3:42 {}",
|
text: "for i in -3:42 {}",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "loop",
|
Name: "loop",
|
||||||
@ -2477,7 +2477,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "loop control",
|
title: "loop control",
|
||||||
text: `for i in l {
|
text: `for i in l {
|
||||||
if i % 2 == 0 {
|
if i % 2 == 0 {
|
||||||
break
|
break
|
||||||
@ -2526,7 +2526,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "assign, eq",
|
title: "assign, eq",
|
||||||
text: "a = b",
|
text: "a = b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "assignment",
|
Name: "assignment",
|
||||||
@ -2541,7 +2541,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "assign, set, eq",
|
title: "assign, set, eq",
|
||||||
text: "set a = b",
|
text: "set a = b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "assignment",
|
Name: "assignment",
|
||||||
@ -2556,7 +2556,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "assign, set",
|
title: "assign, set",
|
||||||
text: "set a b",
|
text: "set a b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "assignment",
|
Name: "assignment",
|
||||||
@ -2571,7 +2571,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "assign, group",
|
title: "assign, group",
|
||||||
text: `set (
|
text: `set (
|
||||||
a = b
|
a = b
|
||||||
c d
|
c d
|
||||||
@ -2596,7 +2596,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define, eq",
|
title: "define, eq",
|
||||||
text: "let a = b",
|
text: "let a = b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "value-definition",
|
Name: "value-definition",
|
||||||
@ -2611,7 +2611,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define",
|
title: "define",
|
||||||
text: "let a b",
|
text: "let a b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "value-definition",
|
Name: "value-definition",
|
||||||
@ -2626,7 +2626,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define mutable, eq",
|
title: "define mutable, eq",
|
||||||
text: "let ~ a = b",
|
text: "let ~ a = b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "value-definition",
|
Name: "value-definition",
|
||||||
@ -2641,7 +2641,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define mutable",
|
title: "define mutable",
|
||||||
text: "let ~ a b",
|
text: "let ~ a b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "value-definition",
|
Name: "value-definition",
|
||||||
@ -2656,7 +2656,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "mixed define group",
|
title: "mixed define group",
|
||||||
text: `let (
|
text: `let (
|
||||||
a = b
|
a = b
|
||||||
c d
|
c d
|
||||||
@ -2697,7 +2697,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "mutable define group",
|
title: "mutable define group",
|
||||||
text: `let ~ (
|
text: `let ~ (
|
||||||
a = b
|
a = b
|
||||||
c d
|
c d
|
||||||
@ -2722,7 +2722,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define function",
|
title: "define function",
|
||||||
text: "fn a() b",
|
text: "fn a() b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-definition",
|
Name: "function-definition",
|
||||||
@ -2737,7 +2737,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define effect",
|
title: "define effect",
|
||||||
text: "fn ~ a() b",
|
text: "fn ~ a() b",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "function-definition",
|
Name: "function-definition",
|
||||||
@ -2752,7 +2752,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define function group",
|
title: "define function group",
|
||||||
text: `fn (
|
text: `fn (
|
||||||
a() b
|
a() b
|
||||||
~ c() d
|
~ c() d
|
||||||
@ -2777,7 +2777,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "define effect group",
|
title: "define effect group",
|
||||||
text: `fn ~ (
|
text: `fn ~ (
|
||||||
a() b
|
a() b
|
||||||
c() d
|
c() d
|
||||||
@ -2802,7 +2802,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "type constraint",
|
title: "type constraint",
|
||||||
text: `
|
text: `
|
||||||
type a fn ([]) int
|
type a fn ([]) int
|
||||||
fn a(l) len(l)
|
fn a(l) len(l)
|
||||||
@ -2842,7 +2842,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "type alias",
|
title: "type alias",
|
||||||
text: "type alias a int|(fn () int|string)|string",
|
text: "type alias a int|(fn () int|string)|string",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "type-alias",
|
Name: "type-alias",
|
||||||
@ -2863,7 +2863,7 @@ func TestMML(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "statement group",
|
title: "statement group",
|
||||||
text: "(for {})",
|
text: "(for {})",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "loop",
|
Name: "loop",
|
||||||
@ -2882,7 +2882,7 @@ func TestMMLFile(t *testing.T) {
|
|||||||
|
|
||||||
const n = 180
|
const n = 180
|
||||||
|
|
||||||
s, err := testSyntax("mml.parser", 0)
|
s, err := openSyntaxFile("mml.parser")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
45
open_test.go
Normal file
45
open_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package treerack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func openSyntaxReader(r io.Reader) (*Syntax, error) {
|
||||||
|
b, err := bootSyntax()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
doc, err := b.Parse(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := NewSyntax()
|
||||||
|
if err := define(s, doc); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.Init(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func openSyntaxFile(file string) (*Syntax, error) {
|
||||||
|
f, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
return openSyntaxReader(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openSyntaxString(syntax string) (*Syntax, error) {
|
||||||
|
b := bytes.NewBufferString(syntax)
|
||||||
|
return openSyntaxReader(b)
|
||||||
|
}
|
363
parse_test.go
363
parse_test.go
@ -1,216 +1,15 @@
|
|||||||
package treerack
|
package treerack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type testItem struct {
|
|
||||||
msg string
|
|
||||||
text string
|
|
||||||
fail bool
|
|
||||||
node *Node
|
|
||||||
nodes []*Node
|
|
||||||
ignorePosition bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func testSyntaxReader(r io.Reader, traceLevel int) (*Syntax, error) {
|
|
||||||
b, err := bootSyntax()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
doc, err := b.Parse(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var trace Trace
|
|
||||||
if traceLevel >= 0 {
|
|
||||||
trace = NewTrace(traceLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := NewSyntaxTrace(trace)
|
|
||||||
if err := define(s, doc); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.Init(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func testSyntax(file string, traceLevel int) (*Syntax, error) {
|
|
||||||
f, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
return testSyntaxReader(f, traceLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkNodesPosition(t *testing.T, left, right []*Node, position bool) {
|
|
||||||
if len(left) != len(right) {
|
|
||||||
t.Error("length doesn't match", len(left), len(right))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(left) > 0 {
|
|
||||||
checkNodePosition(t, left[0], right[0], position)
|
|
||||||
if t.Failed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
left, right = left[1:], right[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkNodePosition(t *testing.T, left, right *Node, position bool) {
|
|
||||||
if (left == nil) != (right == nil) {
|
|
||||||
t.Error("nil reference doesn't match", left == nil, right == nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if left == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if left.Name != right.Name {
|
|
||||||
t.Error("name doesn't match", left.Name, right.Name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if position && left.From != right.From {
|
|
||||||
t.Error("from doesn't match", left.Name, left.From, right.From)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if position && left.To != right.To {
|
|
||||||
t.Error("to doesn't match", left.Name, left.To, right.To)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(left.Nodes) != len(right.Nodes) {
|
|
||||||
t.Error("length doesn't match", left.Name, len(left.Nodes), len(right.Nodes))
|
|
||||||
t.Log(left)
|
|
||||||
t.Log(right)
|
|
||||||
for {
|
|
||||||
if len(left.Nodes) > 0 {
|
|
||||||
t.Log("<", left.Nodes[0])
|
|
||||||
left.Nodes = left.Nodes[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(right.Nodes) > 0 {
|
|
||||||
t.Log(">", right.Nodes[0])
|
|
||||||
right.Nodes = right.Nodes[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(left.Nodes) == 0 && len(right.Nodes) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
checkNodesPosition(t, left.Nodes, right.Nodes, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkNodes(t *testing.T, left, right []*Node) {
|
|
||||||
checkNodesPosition(t, left, right, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkNode(t *testing.T, left, right *Node) {
|
|
||||||
checkNodePosition(t, left, right, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkNodesIgnorePosition(t *testing.T, left, right []*Node) {
|
|
||||||
checkNodesPosition(t, left, right, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkNodeIgnorePosition(t *testing.T, left, right *Node) {
|
|
||||||
checkNodePosition(t, left, right, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testReaderTrace(t *testing.T, r io.Reader, rootName string, traceLevel int, tests []testItem) {
|
|
||||||
s, err := testSyntaxReader(r, traceLevel)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ti := range tests {
|
|
||||||
t.Run(ti.msg, func(t *testing.T) {
|
|
||||||
b := bytes.NewBufferString(ti.text)
|
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
n, err := s.Parse(b)
|
|
||||||
t.Log("parse duration:", time.Now().Sub(start))
|
|
||||||
|
|
||||||
if ti.fail && err == nil {
|
|
||||||
t.Error("failed to fail")
|
|
||||||
return
|
|
||||||
} else if !ti.fail && err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
} else if ti.fail {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log(n)
|
|
||||||
|
|
||||||
cn := checkNode
|
|
||||||
if ti.ignorePosition {
|
|
||||||
cn = checkNodeIgnorePosition
|
|
||||||
}
|
|
||||||
|
|
||||||
if ti.node != nil {
|
|
||||||
cn(t, n, ti.node)
|
|
||||||
} else {
|
|
||||||
cn(t, n, &Node{
|
|
||||||
Name: rootName,
|
|
||||||
To: len(ti.text),
|
|
||||||
Nodes: ti.nodes,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testStringTrace(t *testing.T, s string, traceLevel int, tests []testItem) {
|
|
||||||
testReaderTrace(t, bytes.NewBufferString(s), "", traceLevel, tests)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testString(t *testing.T, s string, tests []testItem) {
|
|
||||||
testStringTrace(t, s, -1, tests)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testTrace(t *testing.T, file, rootName string, traceLevel int, tests []testItem) {
|
|
||||||
f, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
testReaderTrace(t, f, rootName, traceLevel, tests)
|
|
||||||
}
|
|
||||||
|
|
||||||
func test(t *testing.T, file, rootName string, tests []testItem) {
|
|
||||||
testTrace(t, file, rootName, -1, tests)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRecursion(t *testing.T) {
|
func TestRecursion(t *testing.T) {
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" | A "a"`,
|
`A = "a" | A "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, right, left, commit",
|
title: "recursion in choice, right, left, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -225,11 +24,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" | "a" A`,
|
`A = "a" | "a" A`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, right, right, commit",
|
title: "recursion in choice, right, right, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -244,11 +43,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" A | "a"`,
|
`A = "a" A | "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, left, right, commit",
|
title: "recursion in choice, left, right, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -263,11 +62,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = A "a" | "a"`,
|
`A = A "a" | "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, left, left, commit",
|
title: "recursion in choice, left, left, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -282,11 +81,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A':alias = "a" | A' "a"; A = A'`,
|
`A':alias = "a" | A' "a"; A = A'`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, right, left, alias",
|
title: "recursion in choice, right, left, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -295,11 +94,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A':alias = "a" | "a" A'; A = A'`,
|
`A':alias = "a" | "a" A'; A = A'`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, right, right, alias",
|
title: "recursion in choice, right, right, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -308,11 +107,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A':alias = "a" A' | "a"; A = A'`,
|
`A':alias = "a" A' | "a"; A = A'`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, left, right, alias",
|
title: "recursion in choice, left, right, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -321,11 +120,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A':alias = A' "a" | "a"; A = A'`,
|
`A':alias = A' "a" | "a"; A = A'`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "recursion in choice, left, left, alias",
|
title: "recursion in choice, left, left, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -336,18 +135,18 @@ func TestRecursion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSequence(t *testing.T) {
|
func TestSequence(t *testing.T) {
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`AB = "a" | "a"? "a"? "b" "b"`,
|
`AB = "a" | "a"? "a"? "b" "b"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "sequence with optional items",
|
title: "sequence with optional items",
|
||||||
text: "abb",
|
text: "abb",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "AB",
|
Name: "AB",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "sequence with optional items, none",
|
title: "sequence with optional items, none",
|
||||||
text: "bb",
|
text: "bb",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "AB",
|
Name: "AB",
|
||||||
@ -356,11 +155,11 @@ func TestSequence(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" | (A?)*`,
|
`A = "a" | (A?)*`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "sequence in choice with redundant quantifier",
|
title: "sequence in choice with redundant quantifier",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -376,11 +175,11 @@ func TestSequence(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = ("a"*)*`,
|
`A = ("a"*)*`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "sequence with redundant quantifier",
|
title: "sequence with redundant quantifier",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -391,267 +190,267 @@ func TestSequence(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestQuantifiers(t *testing.T) {
|
func TestQuantifiers(t *testing.T) {
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{0} "a"`,
|
`A = "a" "b"{0} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero, considered as one",
|
title: "zero, considered as one",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero, fail",
|
title: "zero, fail",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{1} "a"`,
|
`A = "a" "b"{1} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "one, missing",
|
title: "one, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
fail: true,
|
fail: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "one",
|
title: "one",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "one, too much",
|
title: "one, too much",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{3} "a"`,
|
`A = "a" "b"{3} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "three, missing",
|
title: "three, missing",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "three",
|
title: "three",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "three, too much",
|
title: "three, too much",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{0,1} "a"`,
|
`A = "a" "b"{0,1} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero or one explicit, missing",
|
title: "zero or one explicit, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or one explicit",
|
title: "zero or one explicit",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or one explicit, too much",
|
title: "zero or one explicit, too much",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{,1} "a"`,
|
`A = "a" "b"{,1} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero or one explicit, omit zero, missing",
|
title: "zero or one explicit, omit zero, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or one explicit, omit zero",
|
title: "zero or one explicit, omit zero",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or one explicit, omit zero, too much",
|
title: "zero or one explicit, omit zero, too much",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"? "a"`,
|
`A = "a" "b"? "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero or one explicit, shortcut, missing",
|
title: "zero or one explicit, shortcut, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or one explicit, shortcut",
|
title: "zero or one explicit, shortcut",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or one explicit, shortcut, too much",
|
title: "zero or one explicit, shortcut, too much",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{0,3} "a"`,
|
`A = "a" "b"{0,3} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero or three, missing",
|
title: "zero or three, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or three",
|
title: "zero or three",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or three",
|
title: "zero or three",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or three, too much",
|
title: "zero or three, too much",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{,3} "a"`,
|
`A = "a" "b"{,3} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero or three, omit zero, missing",
|
title: "zero or three, omit zero, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or three, omit zero",
|
title: "zero or three, omit zero",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or three, omit zero",
|
title: "zero or three, omit zero",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or three, omit zero, too much",
|
title: "zero or three, omit zero, too much",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{1,3} "a"`,
|
`A = "a" "b"{1,3} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "one or three, missing",
|
title: "one or three, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
fail: true,
|
fail: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "one or three",
|
title: "one or three",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "one or three",
|
title: "one or three",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "one or three, too much",
|
title: "one or three, too much",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{3,5} "a"`,
|
`A = "a" "b"{3,5} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "three or five, missing",
|
title: "three or five, missing",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "three or five",
|
title: "three or five",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 6,
|
To: 6,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "three or five",
|
title: "three or five",
|
||||||
text: "abbbbba",
|
text: "abbbbba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 7,
|
To: 7,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "three or five, too much",
|
title: "three or five, too much",
|
||||||
text: "abbbbbba",
|
text: "abbbbbba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{0,} "a"`,
|
`A = "a" "b"{0,} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero or more, explicit, missing",
|
title: "zero or more, explicit, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or more, explicit",
|
title: "zero or more, explicit",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -660,18 +459,18 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"* "a"`,
|
`A = "a" "b"* "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "zero or more, shortcut, missing",
|
title: "zero or more, shortcut, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
msg: "zero or more, shortcut",
|
title: "zero or more, shortcut",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -680,15 +479,15 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{1,} "a"`,
|
`A = "a" "b"{1,} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "one or more, explicit, missing",
|
title: "one or more, explicit, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
fail: true,
|
fail: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "one or more, explicit",
|
title: "one or more, explicit",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -697,15 +496,15 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"+ "a"`,
|
`A = "a" "b"+ "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "one or more, shortcut, missing",
|
title: "one or more, shortcut, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
fail: true,
|
fail: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "one or more, shortcut",
|
title: "one or more, shortcut",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -714,15 +513,15 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
testString(
|
runTests(
|
||||||
t,
|
t,
|
||||||
`A = "a" "b"{3,} "a"`,
|
`A = "a" "b"{3,} "a"`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
msg: "three or more, explicit, missing",
|
title: "three or more, explicit, missing",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
fail: true,
|
fail: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "three or more, explicit",
|
title: "three or more, explicit",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
node: &Node{
|
node: &Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
|
64
run_test.go
Normal file
64
run_test.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package treerack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type testItem struct {
|
||||||
|
title string
|
||||||
|
text string
|
||||||
|
fail bool
|
||||||
|
node *Node
|
||||||
|
nodes []*Node
|
||||||
|
ignorePosition bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTestsSyntax(t *testing.T, s *Syntax, tests []testItem) {
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.title, func(t *testing.T) {
|
||||||
|
b := bytes.NewBufferString(test.text)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
n, err := s.Parse(b)
|
||||||
|
t.Log("parse duration:", time.Now().Sub(start))
|
||||||
|
|
||||||
|
if test.fail && err == nil {
|
||||||
|
t.Error("failed to fail")
|
||||||
|
return
|
||||||
|
} else if !test.fail && err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if test.fail {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.node != nil {
|
||||||
|
checkNode(t, test.ignorePosition, n, test.node)
|
||||||
|
} else {
|
||||||
|
checkNodes(t, test.ignorePosition, n.Nodes, test.nodes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTests(t *testing.T, syntax string, tests []testItem) {
|
||||||
|
s, err := openSyntaxString(syntax)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
runTestsSyntax(t, s, tests)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTestsFile(t *testing.T, file string, tests []testItem) {
|
||||||
|
s, err := openSyntaxFile(file)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
runTestsSyntax(t, s, tests)
|
||||||
|
}
|
@ -3,10 +3,10 @@ package treerack
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestScheme(t *testing.T) {
|
func TestScheme(t *testing.T) {
|
||||||
test(t, "scheme.parser", "scheme", []testItem{{
|
runTestsFile(t, "scheme.parser", []testItem{{
|
||||||
msg: "empty",
|
title: "empty",
|
||||||
}, {
|
}, {
|
||||||
msg: "a function",
|
title: "a function",
|
||||||
text: `
|
text: `
|
||||||
(define (foo a b c)
|
(define (foo a b c)
|
||||||
(let ([bar (+ a b c)]
|
(let ([bar (+ a b c)]
|
||||||
|
@ -3,36 +3,36 @@ package treerack
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestSExpr(t *testing.T) {
|
func TestSExpr(t *testing.T) {
|
||||||
test(t, "sexpr.parser", "s-expression", []testItem{{
|
runTestsFile(t, "sexpr.parser", []testItem{{
|
||||||
msg: "number",
|
title: "number",
|
||||||
text: "42",
|
text: "42",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "number",
|
Name: "number",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "string",
|
title: "string",
|
||||||
text: "\"foo\"",
|
text: "\"foo\"",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "symbol",
|
title: "symbol",
|
||||||
text: "foo",
|
text: "foo",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "nil",
|
title: "nil",
|
||||||
text: "()",
|
text: "()",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "list",
|
title: "list",
|
||||||
text: "(foo bar baz)",
|
text: "(foo bar baz)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
@ -46,7 +46,7 @@ func TestSExpr(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
msg: "embedded list",
|
title: "embedded list",
|
||||||
text: "(foo (bar (baz)) qux)",
|
text: "(foo (bar (baz)) qux)",
|
||||||
nodes: []*Node{{
|
nodes: []*Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
|
Loading…
Reference in New Issue
Block a user