diff --git a/boot.go b/boot.go index ec20b3f..b0328c3 100644 --- a/boot.go +++ b/boot.go @@ -187,21 +187,17 @@ func defineAllBoot(s *Syntax, defs [][]string) error { return nil } -func initBoot(definitions [][]string) (*Syntax, error) { +func createBoot() (*Syntax, error) { s := NewSyntax() - if err := defineAllBoot(s, definitions); err != nil { + if err := defineAllBoot(s, bootSyntaxDefs); err != nil { return nil, err } return s, s.Init() } -func createBoot() (*Syntax, error) { - return initBoot(bootSyntaxDefs) -} - func bootSyntax() (*Syntax, error) { - b, err := initBoot(bootSyntaxDefs) + b, err := createBoot() if err != nil { return nil, err } diff --git a/boot_test.go b/boot_test.go index 1d57173..6ab8ac4 100644 --- a/boot_test.go +++ b/boot_test.go @@ -40,7 +40,7 @@ func testParseFromTree(t *testing.T, n *Node, f io.ReadSeeker) *Node { return nil } - checkNode(t, nn, n) + checkNode(t, false, nn, n) return nn } diff --git a/check_test.go b/check_test.go new file mode 100644 index 0000000..443fd76 --- /dev/null +++ b/check_test.go @@ -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) +} diff --git a/eskip_test.go b/eskip_test.go index bb23efe..5072b71 100644 --- a/eskip_test.go +++ b/eskip_test.go @@ -724,10 +724,12 @@ func eskipTreeToEskip(n *Node) ([]*eskip.Route, error) { } func TestEskip(t *testing.T) { - r := generateEskip(1 << 9) + const count = 1 << 9 + + r := generateEskip(count) e := eskip.Print(true, r...) b := bytes.NewBufferString(e) - s, err := testSyntax("eskip.parser", -1) + s, err := openSyntaxFile("eskip.parser") if err != nil { t.Error(err) return diff --git a/json_test.go b/json_test.go index 0610a8e..dee00e6 100644 --- a/json_test.go +++ b/json_test.go @@ -285,9 +285,9 @@ func jsonTreeToJSON(n *Node) (interface{}, error) { } func TestJSON(t *testing.T) { - test(t, "json.parser", "value", []testItem{{ - msg: "true", - text: "true", + runTestsFile(t, "json.parser", []testItem{{ + title: "true", + text: "true", node: &Node{ Name: "json", Nodes: []*Node{{ @@ -296,8 +296,8 @@ func TestJSON(t *testing.T) { }, ignorePosition: true, }, { - msg: "false", - text: "false", + title: "false", + text: "false", node: &Node{ Name: "json", Nodes: []*Node{{ @@ -306,8 +306,8 @@ func TestJSON(t *testing.T) { }, ignorePosition: true, }, { - msg: "null", - text: "null", + title: "null", + text: "null", node: &Node{ Name: "json", Nodes: []*Node{{ @@ -316,8 +316,8 @@ func TestJSON(t *testing.T) { }, ignorePosition: true, }, { - msg: "string", - text: `"\"\\n\b\t\uabcd"`, + title: "string", + text: `"\"\\n\b\t\uabcd"`, node: &Node{ Name: "json", Nodes: []*Node{{ @@ -326,8 +326,8 @@ func TestJSON(t *testing.T) { }, ignorePosition: true, }, { - msg: "number", - text: "6.62e-34", + title: "number", + text: "6.62e-34", node: &Node{ Name: "json", Nodes: []*Node{{ @@ -336,7 +336,7 @@ func TestJSON(t *testing.T) { }, ignorePosition: true, }, { - msg: "object", + title: "object", text: `{ "true": true, "false": false, @@ -404,7 +404,7 @@ func TestJSON(t *testing.T) { }, ignorePosition: true, }, { - msg: "array", + title: "array", text: `[true, false, null, "string", 42, { "true": true, "false": false, @@ -487,8 +487,8 @@ func TestJSON(t *testing.T) { }, ignorePosition: true, }, { - msg: "bugfix, 100", - text: "100", + title: "bugfix, 100", + text: "100", node: &Node{ Name: "json", Nodes: []*Node{{ @@ -509,7 +509,7 @@ func TestRandomJSON(t *testing.T) { buf := bytes.NewBuffer(b) - s, err := testSyntax("json.parser", -1) + s, err := openSyntaxFile("json.parser") if err != nil { t.Error(err) return diff --git a/keyval_test.go b/keyval_test.go index 2827561..f5a877a 100644 --- a/keyval_test.go +++ b/keyval_test.go @@ -3,14 +3,14 @@ package treerack import "testing" func TestKeyVal(t *testing.T) { - test(t, "keyval.parser", "doc", []testItem{{ - msg: "empty", + runTestsFile(t, "keyval.parser", []testItem{{ + title: "empty", }, { - msg: "a comment", - text: "# a comment", + title: "a comment", + text: "# a comment", }, { - msg: "a key", - text: "a key", + title: "a key", + text: "a key", nodes: []*Node{{ Name: "key-val", To: 5, @@ -24,8 +24,8 @@ func TestKeyVal(t *testing.T) { }}, }}, }, { - msg: "a key with a preceeding whitespace", - text: " a key", + title: "a key with a preceeding whitespace", + text: " a key", nodes: []*Node{{ Name: "key-val", From: 1, @@ -42,7 +42,7 @@ func TestKeyVal(t *testing.T) { }}, }}, }, { - msg: "a key and a comment", + title: "a key and a comment", text: ` # a comment @@ -64,8 +64,8 @@ func TestKeyVal(t *testing.T) { }}, }}, }, { - msg: "a key value pair", - text: "a key = a value", + title: "a key value pair", + text: "a key = a value", nodes: []*Node{{ Name: "key-val", To: 15, @@ -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: ` a key = a value # a comment another key = another value # another comment @@ -126,8 +126,8 @@ func TestKeyVal(t *testing.T) { }}, }}, }, { - msg: "value without a key", - text: "= a value", + title: "value without a key", + text: "= a value", nodes: []*Node{{ Name: "key-val", To: 9, @@ -138,7 +138,7 @@ func TestKeyVal(t *testing.T) { }}, }}, }, { - msg: "a key value pair with comment", + title: "a key value pair with comment", text: ` # a comment a key = a value @@ -167,8 +167,8 @@ func TestKeyVal(t *testing.T) { }}, }}, }, { - msg: "a key with multiple symbols", - text: "a key . with.multiple.symbols=a value", + title: "a key with multiple symbols", + text: "a key . with.multiple.symbols=a value", nodes: []*Node{{ Name: "key-val", To: 37, @@ -200,7 +200,7 @@ func TestKeyVal(t *testing.T) { }}, }}, }, { - msg: "a group key", + title: "a group key", text: ` # a comment [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: ` [foo.bar.baz] = one @@ -258,8 +258,8 @@ func TestKeyVal(t *testing.T) { }}, ignorePosition: true, }, { - msg: "a group key with multiple values, in a single line", - text: "[foo.bar.baz] = one = two = three", + title: "a group key with multiple values, in a single line", + text: "[foo.bar.baz] = one = two = three", nodes: []*Node{{ Name: "group-key", Nodes: []*Node{{ @@ -287,7 +287,7 @@ func TestKeyVal(t *testing.T) { }}, ignorePosition: true, }, { - msg: "full example", + title: "full example", text: ` # a keyval document diff --git a/mml_test.go b/mml_test.go index fb519a5..5cc79d5 100644 --- a/mml_test.go +++ b/mml_test.go @@ -9,12 +9,12 @@ import ( ) func TestMML(t *testing.T) { - testTrace(t, "mml.parser", "mml", 1, []testItem{{ - msg: "empty", - node: &Node{Name: "mml"}, + runTestsFile(t, "mml.parser", []testItem{{ + title: "empty", + node: &Node{Name: "mml"}, }, { - msg: "single line comment", - text: "// foo bar baz", + title: "single line comment", + text: "// foo bar baz", nodes: []*Node{{ Name: "comment", To: 14, @@ -25,8 +25,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "multiple line comments", - text: "// foo bar\n// baz qux", + title: "multiple line comments", + text: "// foo bar\n// baz qux", nodes: []*Node{{ Name: "comment", To: 21, @@ -41,8 +41,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "block comment", - text: "/* foo bar baz */", + title: "block comment", + text: "/* foo bar baz */", nodes: []*Node{{ Name: "comment", To: 17, @@ -53,8 +53,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "block comments", - text: "/* foo bar */\n/* baz qux */", + title: "block comments", + text: "/* foo bar */\n/* baz qux */", nodes: []*Node{{ Name: "comment", To: 27, @@ -69,8 +69,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "mixed comments", - text: "// foo\n/* bar */\n// baz", + title: "mixed comments", + text: "// foo\n/* bar */\n// baz", nodes: []*Node{{ Name: "comment", To: 23, @@ -89,15 +89,15 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "int", - text: "42", + title: "int", + text: "42", nodes: []*Node{{ Name: "int", To: 2, }}, }, { - msg: "ints", - text: "1; 2; 3", + title: "ints", + text: "1; 2; 3", nodes: []*Node{{ Name: "int", To: 1, @@ -111,134 +111,134 @@ func TestMML(t *testing.T) { To: 7, }}, }, { - msg: "int, octal", - text: "052", + title: "int, octal", + text: "052", nodes: []*Node{{ Name: "int", To: 3, }}, }, { - msg: "int, hexa", - text: "0x2a", + title: "int, hexa", + text: "0x2a", nodes: []*Node{{ Name: "int", To: 4, }}, }, { - msg: "float, 0.", - text: "0.", + title: "float, 0.", + text: "0.", nodes: []*Node{{ Name: "float", To: 2, }}, }, { - msg: "float, 72.40", - text: "72.40", + title: "float, 72.40", + text: "72.40", nodes: []*Node{{ Name: "float", To: 5, }}, }, { - msg: "float, 072.40", - text: "072.40", + title: "float, 072.40", + text: "072.40", nodes: []*Node{{ Name: "float", To: 6, }}, }, { - msg: "float, 2.71828", - text: "2.71828", + title: "float, 2.71828", + text: "2.71828", nodes: []*Node{{ Name: "float", To: 7, }}, }, { - msg: "float, 6.67428e-11", - text: "6.67428e-11", + title: "float, 6.67428e-11", + text: "6.67428e-11", nodes: []*Node{{ Name: "float", To: 11, }}, }, { - msg: "float, 1E6", - text: "1E6", + title: "float, 1E6", + text: "1E6", nodes: []*Node{{ Name: "float", To: 3, }}, }, { - msg: "float, .25", - text: ".25", + title: "float, .25", + text: ".25", nodes: []*Node{{ Name: "float", To: 3, }}, }, { - msg: "float, .12345E+5", - text: ".12345E+5", + title: "float, .12345E+5", + text: ".12345E+5", nodes: []*Node{{ Name: "float", To: 9, }}, }, { - msg: "string, empty", - text: "\"\"", + title: "string, empty", + text: "\"\"", nodes: []*Node{{ Name: "string", To: 2, }}, }, { - msg: "string", - text: "\"foo\"", + title: "string", + text: "\"foo\"", nodes: []*Node{{ Name: "string", To: 5, }}, }, { - msg: "string, with new line", - text: "\"foo\nbar\"", + title: "string, with new line", + text: "\"foo\nbar\"", nodes: []*Node{{ Name: "string", To: 9, }}, }, { - msg: "string, with escaped new line", - text: "\"foo\\nbar\"", + title: "string, with escaped new line", + text: "\"foo\\nbar\"", nodes: []*Node{{ Name: "string", To: 10, }}, }, { - msg: "string, with quotes", - text: "\"foo \\\"bar\\\" baz\"", + title: "string, with quotes", + text: "\"foo \\\"bar\\\" baz\"", nodes: []*Node{{ Name: "string", To: 17, }}, }, { - msg: "bool, true", - text: "true", + title: "bool, true", + text: "true", nodes: []*Node{{ Name: "true", To: 4, }}, }, { - msg: "bool, false", - text: "false", + title: "bool, false", + text: "false", nodes: []*Node{{ Name: "false", To: 5, }}, }, { - msg: "symbol", - text: "foo", + title: "symbol", + text: "foo", nodes: []*Node{{ Name: "symbol", To: 3, }}, }, { - msg: "dynamic-symbol", - text: "symbol(a)", + title: "dynamic-symbol", + text: "symbol(a)", nodes: []*Node{{ Name: "dynamic-symbol", To: 9, @@ -249,15 +249,15 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "empty list", - text: "[]", + title: "empty list", + text: "[]", nodes: []*Node{{ Name: "list", To: 2, }}, }, { - msg: "list", - text: "[a, b, c]", + title: "list", + text: "[a, b, c]", nodes: []*Node{{ Name: "list", To: 9, @@ -276,7 +276,7 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "list, new lines", + title: "list, new lines", text: `[ a b @@ -300,8 +300,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "list, complex", - text: "[a, b, c..., [d, e], [f, [g]]...]", + title: "list, complex", + text: "[a, b, c..., [d, e], [f, [g]]...]", nodes: []*Node{{ Name: "list", To: 33, @@ -361,8 +361,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "mutable list", - text: "~[a, b, c]", + title: "mutable list", + text: "~[a, b, c]", nodes: []*Node{{ Name: "mutable-list", To: 10, @@ -381,15 +381,15 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "empty struct", - text: "{}", + title: "empty struct", + text: "{}", nodes: []*Node{{ Name: "struct", To: 2, }}, }, { - msg: "struct", - text: "{foo: 1, \"bar\": 2, symbol(baz): 3, [qux]: 4}", + title: "struct", + text: "{foo: 1, \"bar\": 2, symbol(baz): 3, [qux]: 4}", nodes: []*Node{{ Name: "struct", To: 44, @@ -458,8 +458,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "struct, complex", - text: "{foo: 1, {bar: 2}..., {baz: {}}...}", + title: "struct, complex", + text: "{foo: 1, {bar: 2}..., {baz: {}}...}", nodes: []*Node{{ Name: "struct", To: 35, @@ -525,8 +525,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "struct with indexer key", - text: "{[a]: b}", + title: "struct with indexer key", + text: "{[a]: b}", nodes: []*Node{{ Name: "struct", To: 8, @@ -551,8 +551,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "mutable struct", - text: "~{foo: 1}", + title: "mutable struct", + text: "~{foo: 1}", nodes: []*Node{{ Name: "mutable-struct", To: 9, @@ -572,15 +572,15 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "channel", - text: "<>", + title: "channel", + text: "<>", nodes: []*Node{{ Name: "channel", To: 2, }}, }, { - msg: "buffered channel", - text: "<42>", + title: "buffered channel", + text: "<42>", nodes: []*Node{{ Name: "channel", To: 4, @@ -591,8 +591,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "and expression", - text: "and(a, b, c)", + title: "and expression", + text: "and(a, b, c)", nodes: []*Node{{ Name: "function-application", To: 12, @@ -614,8 +614,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "or expression", - text: "or(a, b, c)", + title: "or expression", + text: "or(a, b, c)", nodes: []*Node{{ Name: "function-application", To: 11, @@ -637,8 +637,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function", - text: "fn () 42", + title: "function", + text: "fn () 42", nodes: []*Node{{ Name: "function", To: 8, @@ -649,8 +649,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function, noop", - text: "fn () {;}", + title: "function, noop", + text: "fn () {;}", nodes: []*Node{{ Name: "function", To: 9, @@ -661,8 +661,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function with args", - text: "fn (a, b, c) [a, b, c]", + title: "function with args", + text: "fn (a, b, c) [a, b, c]", nodes: []*Node{{ Name: "function", To: 22, @@ -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 ( a b @@ -739,8 +739,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function with spread arg", - text: "fn (a, b, ...c) [a, b, c]", + title: "function with spread arg", + text: "fn (a, b, ...c) [a, b, c]", nodes: []*Node{{ Name: "function", To: 25, @@ -781,8 +781,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "effect", - text: "fn ~ () 42", + title: "effect", + text: "fn ~ () 42", nodes: []*Node{{ Name: "effect", To: 10, @@ -793,8 +793,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "indexer", - text: "a[42]", + title: "indexer", + text: "a[42]", nodes: []*Node{{ Name: "indexer", To: 5, @@ -808,8 +808,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "range indexer", - text: "a[3:9]", + title: "range indexer", + text: "a[3:9]", nodes: []*Node{{ Name: "indexer", To: 6, @@ -837,8 +837,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "range indexer, lower unbound", - text: "a[:9]", + title: "range indexer, lower unbound", + text: "a[:9]", nodes: []*Node{{ Name: "indexer", To: 5, @@ -857,8 +857,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "range indexer, upper unbound", - text: "a[3:]", + title: "range indexer, upper unbound", + text: "a[3:]", nodes: []*Node{{ Name: "indexer", To: 5, @@ -877,8 +877,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "indexer, chained", - text: "a[b][c][d]", + title: "indexer, chained", + text: "a[b][c][d]", nodes: []*Node{{ Name: "indexer", To: 10, @@ -908,8 +908,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "symbol indexer", - text: "a.b", + title: "symbol indexer", + text: "a.b", nodes: []*Node{{ Name: "indexer", To: 3, @@ -923,8 +923,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "symbol indexer, with string", - text: "a.\"b\"", + title: "symbol indexer, with string", + text: "a.\"b\"", nodes: []*Node{{ Name: "indexer", To: 5, @@ -938,8 +938,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "symbol indexer, with dynamic symbol", - text: "a.symbol(b)", + title: "symbol indexer, with dynamic symbol", + text: "a.symbol(b)", nodes: []*Node{{ Name: "indexer", To: 11, @@ -958,8 +958,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "chained symbol indexer", - text: "a.b.c.d", + title: "chained symbol indexer", + text: "a.b.c.d", nodes: []*Node{{ Name: "indexer", To: 7, @@ -989,8 +989,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "chained symbol indexer on new line", - text: "a\n.b\n.c", + title: "chained symbol indexer on new line", + text: "a\n.b\n.c", nodes: []*Node{{ Name: "indexer", To: 7, @@ -1012,8 +1012,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "chained symbol indexer on new line after dot", - text: "a.\nb.\nc", + title: "chained symbol indexer on new line after dot", + text: "a.\nb.\nc", nodes: []*Node{{ Name: "indexer", To: 7, @@ -1035,8 +1035,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "float on a new line", - text: "f()\n.9", + title: "float on a new line", + text: "f()\n.9", nodes: []*Node{{ Name: "function-application", Nodes: []*Node{{ @@ -1047,8 +1047,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "function application", - text: "f()", + title: "function application", + text: "f()", nodes: []*Node{{ Name: "function-application", To: 3, @@ -1058,8 +1058,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function application, single arg", - text: "f(a)", + title: "function application, single arg", + text: "f(a)", nodes: []*Node{{ Name: "function-application", To: 4, @@ -1073,8 +1073,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function application, multiple args", - text: "f(a, b, c)", + title: "function application, multiple args", + text: "f(a, b, c)", nodes: []*Node{{ Name: "function-application", To: 10, @@ -1096,8 +1096,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function application, multiple args, new line", - text: "f(a\nb\nc\n)", + title: "function application, multiple args, new line", + text: "f(a\nb\nc\n)", nodes: []*Node{{ Name: "function-application", To: 9, @@ -1119,8 +1119,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "function application, spread", - text: "f(a, b..., c, d...)", + title: "function application, spread", + text: "f(a, b..., c, d...)", nodes: []*Node{{ Name: "function-application", To: 19, @@ -1156,8 +1156,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "chained function application", - text: "f(a)(b)(c)", + title: "chained function application", + text: "f(a)(b)(c)", nodes: []*Node{{ Name: "function-application", To: 10, @@ -1187,8 +1187,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "embedded function application", - text: "f(g(h(a)))", + title: "embedded function application", + text: "f(g(h(a)))", nodes: []*Node{{ Name: "function-application", To: 10, @@ -1220,8 +1220,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "if", - text: "if a { b() }", + title: "if", + text: "if a { b() }", nodes: []*Node{{ Name: "if", To: 12, @@ -1246,8 +1246,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "if, else", - text: "if a { b } else { c }", + title: "if, else", + text: "if a { b } else { c }", nodes: []*Node{{ Name: "if", To: 21, @@ -1276,7 +1276,7 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "if, else if, else if, else", + title: "if, else if, else if, else", text: ` if a { b } else if c { d } @@ -1338,8 +1338,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "switch, empty", - text: "switch {default:}", + title: "switch, empty", + text: "switch {default:}", nodes: []*Node{{ Name: "switch", To: 17, @@ -1350,7 +1350,7 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "switch, empty cases", + title: "switch, empty cases", text: ` switch { case a: @@ -1382,8 +1382,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "switch, single case", - text: "switch a {case b: c}", + title: "switch, single case", + text: "switch a {case b: c}", nodes: []*Node{{ Name: "switch", To: 20, @@ -1407,8 +1407,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "switch", - text: "switch a {case b: c; case d: e; default: f}", + title: "switch", + text: "switch a {case b: c; case d: e; default: f}", nodes: []*Node{{ Name: "switch", To: 43, @@ -1453,7 +1453,7 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "switch, all new lines", + title: "switch, all new lines", text: `switch a { @@ -1513,8 +1513,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "match expression, empty", - text: "match a {}", + title: "match expression, empty", + text: "match a {}", nodes: []*Node{{ Name: "match", To: 10, @@ -1525,7 +1525,7 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "match expression", + title: "match expression", text: `match a { 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 { case [0]: [] case [2:]: a[2:] @@ -1647,7 +1647,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "match function", + title: "match function", text: `match a { case fn () int: a() default: 42 @@ -1677,7 +1677,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "match expression, combined", + title: "match expression, combined", text: `match a { case [fn (int)]: a[0]() default: 42 @@ -1721,7 +1721,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "match expression, complex", + title: "match expression, complex", text: `match a { case [first T int|string, op fn ([T, int, ...T]) int, ...rest T]: op([first, now(), rest...]) @@ -1832,8 +1832,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "receive op", - text: "<-chan", + title: "receive op", + text: "<-chan", nodes: []*Node{{ Name: "unary-expression", Nodes: []*Node{{ @@ -1845,8 +1845,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "send op", - text: "chan <- a", + title: "send op", + text: "chan <- a", nodes: []*Node{{ Name: "send", Nodes: []*Node{{ @@ -1857,7 +1857,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "select, empty", + title: "select, empty", text: `select { }`, nodes: []*Node{{ @@ -1865,7 +1865,7 @@ func TestMML(t *testing.T) { To: 12, }}, }, { - msg: "select", + title: "select", text: `select { case let a <-r: s <- a case s <- f(): g() @@ -1922,7 +1922,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "select, call", + title: "select, call", text: `select { case let a receive(r): f() case send(s, g()): h() @@ -1977,7 +1977,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "block", + title: "block", ignorePosition: true, text: "{ f() }", nodes: []*Node{{ @@ -1990,8 +1990,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "go", - text: "go f()", + title: "go", + text: "go f()", nodes: []*Node{{ Name: "go", Nodes: []*Node{{ @@ -2003,8 +2003,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "go, block", - text: "go { for { f() } }", + title: "go, block", + text: "go { for { f() } }", nodes: []*Node{{ Name: "go", Nodes: []*Node{{ @@ -2025,8 +2025,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "require, dot, equal", - text: "require . = \"mml/foo\"", + title: "require, dot, equal", + text: "require . = \"mml/foo\"", nodes: []*Node{{ Name: "require", Nodes: []*Node{{ @@ -2040,8 +2040,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "require, symbol, equal", - text: "require bar = \"mml/foo\"", + title: "require, symbol, equal", + text: "require bar = \"mml/foo\"", nodes: []*Node{{ Name: "require", Nodes: []*Node{{ @@ -2055,8 +2055,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "require, symbol", - text: "require bar \"mml/foo\"", + title: "require, symbol", + text: "require bar \"mml/foo\"", nodes: []*Node{{ Name: "require", Nodes: []*Node{{ @@ -2070,8 +2070,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "require", - text: "require \"mml/foo\"", + title: "require", + text: "require \"mml/foo\"", nodes: []*Node{{ Name: "require", Nodes: []*Node{{ @@ -2083,7 +2083,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "require, group", + title: "require, group", text: `require ( . = "mml/foo" bar = "mml/foo" @@ -2130,8 +2130,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "expression group", - text: "(fn (a) a)(a)", + title: "expression group", + text: "(fn (a) a)(a)", nodes: []*Node{{ Name: "function-application", Nodes: []*Node{{ @@ -2147,8 +2147,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "unary operator", - text: "!foo", + title: "unary operator", + text: "!foo", nodes: []*Node{{ Name: "unary-expression", Nodes: []*Node{{ @@ -2159,8 +2159,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "binary 0", - text: "a * b", + title: "binary 0", + text: "a * b", nodes: []*Node{{ Name: "binary0", Nodes: []*Node{{ @@ -2173,8 +2173,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "binary 1", - text: "a * b + c * d", + title: "binary 1", + text: "a * b + c * d", nodes: []*Node{{ Name: "binary1", Nodes: []*Node{{ @@ -2201,8 +2201,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "binary 2", - text: "a * b + c * d == e * f", + title: "binary 2", + text: "a * b + c * d == e * f", nodes: []*Node{{ Name: "binary2", Nodes: []*Node{{ @@ -2243,8 +2243,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "binary 3, 4, 5", - text: "a * b + c * d == e * f && g || h -> f()", + title: "binary 3, 4, 5", + text: "a * b + c * d == e * f && g || h -> f()", nodes: []*Node{{ Name: "binary5", Nodes: []*Node{{ @@ -2309,8 +2309,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "ternary expression", - text: "a ? b : c", + title: "ternary expression", + text: "a ? b : c", nodes: []*Node{{ Name: "ternary-expression", To: 9, @@ -2328,8 +2328,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "multiple ternary expressions, consequence", - text: "a ? b ? c : d : e", + title: "multiple ternary expressions, consequence", + text: "a ? b ? c : d : e", nodes: []*Node{{ Name: "ternary-expression", To: 17, @@ -2360,8 +2360,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "multiple ternary expressions, alternative", - text: "a ? b : c ? d : e", + title: "multiple ternary expressions, alternative", + text: "a ? b : c ? d : e", nodes: []*Node{{ Name: "ternary-expression", To: 17, @@ -2392,8 +2392,8 @@ func TestMML(t *testing.T) { }}, }}, }, { - msg: "infinite loop", - text: "for {}", + title: "infinite loop", + text: "for {}", nodes: []*Node{{ Name: "loop", Nodes: []*Node{{ @@ -2402,8 +2402,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "conditional loop", - text: "for foo {}", + title: "conditional loop", + text: "for foo {}", nodes: []*Node{{ Name: "loop", Nodes: []*Node{{ @@ -2417,8 +2417,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "in list loop", - text: "for i in [1, 2, 3] {}", + title: "in list loop", + text: "for i in [1, 2, 3] {}", nodes: []*Node{{ Name: "loop", Nodes: []*Node{{ @@ -2444,8 +2444,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "in range loop", - text: "for i in -3:42 {}", + title: "in range loop", + text: "for i in -3:42 {}", nodes: []*Node{{ Name: "loop", Nodes: []*Node{{ @@ -2477,7 +2477,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "loop control", + title: "loop control", text: `for i in l { if i % 2 == 0 { break @@ -2526,8 +2526,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "assign, eq", - text: "a = b", + title: "assign, eq", + text: "a = b", nodes: []*Node{{ Name: "assignment", Nodes: []*Node{{ @@ -2541,8 +2541,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "assign, set, eq", - text: "set a = b", + title: "assign, set, eq", + text: "set a = b", nodes: []*Node{{ Name: "assignment", Nodes: []*Node{{ @@ -2556,8 +2556,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "assign, set", - text: "set a b", + title: "assign, set", + text: "set a b", nodes: []*Node{{ Name: "assignment", Nodes: []*Node{{ @@ -2571,7 +2571,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "assign, group", + title: "assign, group", text: `set ( a = b c d @@ -2596,8 +2596,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define, eq", - text: "let a = b", + title: "define, eq", + text: "let a = b", nodes: []*Node{{ Name: "value-definition", Nodes: []*Node{{ @@ -2611,8 +2611,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define", - text: "let a b", + title: "define", + text: "let a b", nodes: []*Node{{ Name: "value-definition", Nodes: []*Node{{ @@ -2626,8 +2626,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define mutable, eq", - text: "let ~ a = b", + title: "define mutable, eq", + text: "let ~ a = b", nodes: []*Node{{ Name: "value-definition", Nodes: []*Node{{ @@ -2641,8 +2641,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define mutable", - text: "let ~ a b", + title: "define mutable", + text: "let ~ a b", nodes: []*Node{{ Name: "value-definition", Nodes: []*Node{{ @@ -2656,7 +2656,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "mixed define group", + title: "mixed define group", text: `let ( a = b c d @@ -2697,7 +2697,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "mutable define group", + title: "mutable define group", text: `let ~ ( a = b c d @@ -2722,8 +2722,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define function", - text: "fn a() b", + title: "define function", + text: "fn a() b", nodes: []*Node{{ Name: "function-definition", Nodes: []*Node{{ @@ -2737,8 +2737,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define effect", - text: "fn ~ a() b", + title: "define effect", + text: "fn ~ a() b", nodes: []*Node{{ Name: "function-definition", Nodes: []*Node{{ @@ -2752,7 +2752,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define function group", + title: "define function group", text: `fn ( a() b ~ c() d @@ -2777,7 +2777,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "define effect group", + title: "define effect group", text: `fn ~ ( a() b c() d @@ -2802,7 +2802,7 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "type constraint", + title: "type constraint", text: ` type a fn ([]) int fn a(l) len(l) @@ -2842,8 +2842,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "type alias", - text: "type alias a int|(fn () int|string)|string", + title: "type alias", + text: "type alias a int|(fn () int|string)|string", nodes: []*Node{{ Name: "type-alias", Nodes: []*Node{{ @@ -2863,8 +2863,8 @@ func TestMML(t *testing.T) { }}, ignorePosition: true, }, { - msg: "statement group", - text: "(for {})", + title: "statement group", + text: "(for {})", nodes: []*Node{{ Name: "loop", Nodes: []*Node{{ @@ -2882,7 +2882,7 @@ func TestMMLFile(t *testing.T) { const n = 180 - s, err := testSyntax("mml.parser", 0) + s, err := openSyntaxFile("mml.parser") if err != nil { t.Error(err) return diff --git a/open_test.go b/open_test.go new file mode 100644 index 0000000..960237d --- /dev/null +++ b/open_test.go @@ -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) +} diff --git a/parse_test.go b/parse_test.go index 4ab988e..edb3e52 100644 --- a/parse_test.go +++ b/parse_test.go @@ -1,217 +1,16 @@ package treerack import ( - "bytes" - "io" - "os" "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) { - testString( + runTests( t, `A = "a" | A "a"`, []testItem{{ - msg: "recursion in choice, right, left, commit", - text: "aaa", + title: "recursion in choice, right, left, commit", + text: "aaa", node: &Node{ Name: "A", Nodes: []*Node{{ @@ -225,12 +24,12 @@ func TestRecursion(t *testing.T) { }}, ) - testString( + runTests( t, `A = "a" | "a" A`, []testItem{{ - msg: "recursion in choice, right, right, commit", - text: "aaa", + title: "recursion in choice, right, right, commit", + text: "aaa", node: &Node{ Name: "A", Nodes: []*Node{{ @@ -244,12 +43,12 @@ func TestRecursion(t *testing.T) { }}, ) - testString( + runTests( t, `A = "a" A | "a"`, []testItem{{ - msg: "recursion in choice, left, right, commit", - text: "aaa", + title: "recursion in choice, left, right, commit", + text: "aaa", node: &Node{ Name: "A", Nodes: []*Node{{ @@ -263,12 +62,12 @@ func TestRecursion(t *testing.T) { }}, ) - testString( + runTests( t, `A = A "a" | "a"`, []testItem{{ - msg: "recursion in choice, left, left, commit", - text: "aaa", + title: "recursion in choice, left, left, commit", + text: "aaa", node: &Node{ Name: "A", Nodes: []*Node{{ @@ -282,12 +81,12 @@ func TestRecursion(t *testing.T) { }}, ) - testString( + runTests( t, `A':alias = "a" | A' "a"; A = A'`, []testItem{{ - msg: "recursion in choice, right, left, alias", - text: "aaa", + title: "recursion in choice, right, left, alias", + text: "aaa", node: &Node{ Name: "A", To: 3, @@ -295,12 +94,12 @@ func TestRecursion(t *testing.T) { }}, ) - testString( + runTests( t, `A':alias = "a" | "a" A'; A = A'`, []testItem{{ - msg: "recursion in choice, right, right, alias", - text: "aaa", + title: "recursion in choice, right, right, alias", + text: "aaa", node: &Node{ Name: "A", To: 3, @@ -308,12 +107,12 @@ func TestRecursion(t *testing.T) { }}, ) - testString( + runTests( t, `A':alias = "a" A' | "a"; A = A'`, []testItem{{ - msg: "recursion in choice, left, right, alias", - text: "aaa", + title: "recursion in choice, left, right, alias", + text: "aaa", node: &Node{ Name: "A", To: 3, @@ -321,12 +120,12 @@ func TestRecursion(t *testing.T) { }}, ) - testString( + runTests( t, `A':alias = A' "a" | "a"; A = A'`, []testItem{{ - msg: "recursion in choice, left, left, alias", - text: "aaa", + title: "recursion in choice, left, left, alias", + text: "aaa", node: &Node{ Name: "A", To: 3, @@ -336,19 +135,19 @@ func TestRecursion(t *testing.T) { } func TestSequence(t *testing.T) { - testString( + runTests( t, `AB = "a" | "a"? "a"? "b" "b"`, []testItem{{ - msg: "sequence with optional items", - text: "abb", + title: "sequence with optional items", + text: "abb", node: &Node{ Name: "AB", To: 3, }, }, { - msg: "sequence with optional items, none", - text: "bb", + title: "sequence with optional items, none", + text: "bb", node: &Node{ Name: "AB", To: 2, @@ -356,12 +155,12 @@ func TestSequence(t *testing.T) { }}, ) - testString( + runTests( t, `A = "a" | (A?)*`, []testItem{{ - msg: "sequence in choice with redundant quantifier", - text: "aaa", + title: "sequence in choice with redundant quantifier", + text: "aaa", node: &Node{ Name: "A", Nodes: []*Node{{ @@ -376,12 +175,12 @@ func TestSequence(t *testing.T) { }}, ) - testString( + runTests( t, `A = ("a"*)*`, []testItem{{ - msg: "sequence with redundant quantifier", - text: "aaa", + title: "sequence with redundant quantifier", + text: "aaa", node: &Node{ Name: "A", To: 3, @@ -391,268 +190,268 @@ func TestSequence(t *testing.T) { } func TestQuantifiers(t *testing.T) { - testString( + runTests( t, `A = "a" "b"{0} "a"`, []testItem{{ - msg: "zero, considered as one", - text: "aba", + title: "zero, considered as one", + text: "aba", node: &Node{ Name: "A", To: 3, }, }, { - msg: "zero, fail", - text: "aa", - fail: true, + title: "zero, fail", + text: "aa", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{1} "a"`, []testItem{{ - msg: "one, missing", - text: "aa", - fail: true, + title: "one, missing", + text: "aa", + fail: true, }, { - msg: "one", - text: "aba", + title: "one", + text: "aba", node: &Node{ Name: "A", To: 3, }, }, { - msg: "one, too much", - text: "abba", - fail: true, + title: "one, too much", + text: "abba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{3} "a"`, []testItem{{ - msg: "three, missing", - text: "abba", - fail: true, + title: "three, missing", + text: "abba", + fail: true, }, { - msg: "three", - text: "abbba", + title: "three", + text: "abbba", node: &Node{ Name: "A", To: 5, }, }, { - msg: "three, too much", - text: "abbbba", - fail: true, + title: "three, too much", + text: "abbbba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{0,1} "a"`, []testItem{{ - msg: "zero or one explicit, missing", - text: "aa", + title: "zero or one explicit, missing", + text: "aa", node: &Node{ Name: "A", To: 2, }, }, { - msg: "zero or one explicit", - text: "aba", + title: "zero or one explicit", + text: "aba", node: &Node{ Name: "A", To: 3, }, }, { - msg: "zero or one explicit, too much", - text: "abba", - fail: true, + title: "zero or one explicit, too much", + text: "abba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{,1} "a"`, []testItem{{ - msg: "zero or one explicit, omit zero, missing", - text: "aa", + title: "zero or one explicit, omit zero, missing", + text: "aa", node: &Node{ Name: "A", To: 2, }, }, { - msg: "zero or one explicit, omit zero", - text: "aba", + title: "zero or one explicit, omit zero", + text: "aba", node: &Node{ Name: "A", To: 3, }, }, { - msg: "zero or one explicit, omit zero, too much", - text: "abba", - fail: true, + title: "zero or one explicit, omit zero, too much", + text: "abba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"? "a"`, []testItem{{ - msg: "zero or one explicit, shortcut, missing", - text: "aa", + title: "zero or one explicit, shortcut, missing", + text: "aa", node: &Node{ Name: "A", To: 2, }, }, { - msg: "zero or one explicit, shortcut", - text: "aba", + title: "zero or one explicit, shortcut", + text: "aba", node: &Node{ Name: "A", To: 3, }, }, { - msg: "zero or one explicit, shortcut, too much", - text: "abba", - fail: true, + title: "zero or one explicit, shortcut, too much", + text: "abba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{0,3} "a"`, []testItem{{ - msg: "zero or three, missing", - text: "aa", + title: "zero or three, missing", + text: "aa", node: &Node{ Name: "A", To: 2, }, }, { - msg: "zero or three", - text: "abba", + title: "zero or three", + text: "abba", node: &Node{ Name: "A", To: 4, }, }, { - msg: "zero or three", - text: "abbba", + title: "zero or three", + text: "abbba", node: &Node{ Name: "A", To: 5, }, }, { - msg: "zero or three, too much", - text: "abbbba", - fail: true, + title: "zero or three, too much", + text: "abbbba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{,3} "a"`, []testItem{{ - msg: "zero or three, omit zero, missing", - text: "aa", + title: "zero or three, omit zero, missing", + text: "aa", node: &Node{ Name: "A", To: 2, }, }, { - msg: "zero or three, omit zero", - text: "abba", + title: "zero or three, omit zero", + text: "abba", node: &Node{ Name: "A", To: 4, }, }, { - msg: "zero or three, omit zero", - text: "abbba", + title: "zero or three, omit zero", + text: "abbba", node: &Node{ Name: "A", To: 5, }, }, { - msg: "zero or three, omit zero, too much", - text: "abbbba", - fail: true, + title: "zero or three, omit zero, too much", + text: "abbbba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{1,3} "a"`, []testItem{{ - msg: "one or three, missing", - text: "aa", - fail: true, + title: "one or three, missing", + text: "aa", + fail: true, }, { - msg: "one or three", - text: "abba", + title: "one or three", + text: "abba", node: &Node{ Name: "A", To: 4, }, }, { - msg: "one or three", - text: "abbba", + title: "one or three", + text: "abbba", node: &Node{ Name: "A", To: 5, }, }, { - msg: "one or three, too much", - text: "abbbba", - fail: true, + title: "one or three, too much", + text: "abbbba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{3,5} "a"`, []testItem{{ - msg: "three or five, missing", - text: "abba", - fail: true, + title: "three or five, missing", + text: "abba", + fail: true, }, { - msg: "three or five", - text: "abbbba", + title: "three or five", + text: "abbbba", node: &Node{ Name: "A", To: 6, }, }, { - msg: "three or five", - text: "abbbbba", + title: "three or five", + text: "abbbbba", node: &Node{ Name: "A", To: 7, }, }, { - msg: "three or five, too much", - text: "abbbbbba", - fail: true, + title: "three or five, too much", + text: "abbbbbba", + fail: true, }}, ) - testString( + runTests( t, `A = "a" "b"{0,} "a"`, []testItem{{ - msg: "zero or more, explicit, missing", - text: "aa", + title: "zero or more, explicit, missing", + text: "aa", node: &Node{ Name: "A", To: 2, }, }, { - msg: "zero or more, explicit", - text: "abba", + title: "zero or more, explicit", + text: "abba", node: &Node{ Name: "A", To: 4, @@ -660,19 +459,19 @@ func TestQuantifiers(t *testing.T) { }}, ) - testString( + runTests( t, `A = "a" "b"* "a"`, []testItem{{ - msg: "zero or more, shortcut, missing", - text: "aa", + title: "zero or more, shortcut, missing", + text: "aa", node: &Node{ Name: "A", To: 2, }, }, { - msg: "zero or more, shortcut", - text: "abba", + title: "zero or more, shortcut", + text: "abba", node: &Node{ Name: "A", To: 4, @@ -680,16 +479,16 @@ func TestQuantifiers(t *testing.T) { }}, ) - testString( + runTests( t, `A = "a" "b"{1,} "a"`, []testItem{{ - msg: "one or more, explicit, missing", - text: "aa", - fail: true, + title: "one or more, explicit, missing", + text: "aa", + fail: true, }, { - msg: "one or more, explicit", - text: "abba", + title: "one or more, explicit", + text: "abba", node: &Node{ Name: "A", To: 4, @@ -697,16 +496,16 @@ func TestQuantifiers(t *testing.T) { }}, ) - testString( + runTests( t, `A = "a" "b"+ "a"`, []testItem{{ - msg: "one or more, shortcut, missing", - text: "aa", - fail: true, + title: "one or more, shortcut, missing", + text: "aa", + fail: true, }, { - msg: "one or more, shortcut", - text: "abba", + title: "one or more, shortcut", + text: "abba", node: &Node{ Name: "A", To: 4, @@ -714,16 +513,16 @@ func TestQuantifiers(t *testing.T) { }}, ) - testString( + runTests( t, `A = "a" "b"{3,} "a"`, []testItem{{ - msg: "three or more, explicit, missing", - text: "abba", - fail: true, + title: "three or more, explicit, missing", + text: "abba", + fail: true, }, { - msg: "three or more, explicit", - text: "abbbba", + title: "three or more, explicit", + text: "abbbba", node: &Node{ Name: "A", To: 6, diff --git a/run_test.go b/run_test.go new file mode 100644 index 0000000..6bfafce --- /dev/null +++ b/run_test.go @@ -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) +} diff --git a/scheme_test.go b/scheme_test.go index 7ffd837..7b87898 100644 --- a/scheme_test.go +++ b/scheme_test.go @@ -3,10 +3,10 @@ package treerack import "testing" func TestScheme(t *testing.T) { - test(t, "scheme.parser", "scheme", []testItem{{ - msg: "empty", + runTestsFile(t, "scheme.parser", []testItem{{ + title: "empty", }, { - msg: "a function", + title: "a function", text: ` (define (foo a b c) (let ([bar (+ a b c)] diff --git a/sexpr_test.go b/sexpr_test.go index e41f385..d28e92d 100644 --- a/sexpr_test.go +++ b/sexpr_test.go @@ -3,37 +3,37 @@ package treerack import "testing" func TestSExpr(t *testing.T) { - test(t, "sexpr.parser", "s-expression", []testItem{{ - msg: "number", - text: "42", + runTestsFile(t, "sexpr.parser", []testItem{{ + title: "number", + text: "42", nodes: []*Node{{ Name: "number", }}, ignorePosition: true, }, { - msg: "string", - text: "\"foo\"", + title: "string", + text: "\"foo\"", nodes: []*Node{{ Name: "string", }}, ignorePosition: true, }, { - msg: "symbol", - text: "foo", + title: "symbol", + text: "foo", nodes: []*Node{{ Name: "symbol", }}, ignorePosition: true, }, { - msg: "nil", - text: "()", + title: "nil", + text: "()", nodes: []*Node{{ Name: "list", }}, ignorePosition: true, }, { - msg: "list", - text: "(foo bar baz)", + title: "list", + text: "(foo bar baz)", nodes: []*Node{{ Name: "list", Nodes: []*Node{{ @@ -46,8 +46,8 @@ func TestSExpr(t *testing.T) { }}, ignorePosition: true, }, { - msg: "embedded list", - text: "(foo (bar (baz)) qux)", + title: "embedded list", + text: "(foo (bar (baz)) qux)", nodes: []*Node{{ Name: "list", Nodes: []*Node{{