From 76ebeb09489faa6bc8164e1e532118ed802ee081 Mon Sep 17 00:00:00 2001 From: Arpad Ryszka Date: Mon, 1 Jun 2026 22:26:27 +0200 Subject: [PATCH] replace Node pointers with values --- boot_test.go | 12 +- char.go | 2 +- check_test.go | 13 +- choice.go | 4 +- cmd/treerack/show.go | 2 +- define.go | 34 +- format.go | 30 +- head.go | 2 +- headexported.go | 2 +- internal/self/self.go | 32 +- json_test.go | 74 ++-- keyval_test.go | 108 +++--- keyword_test.go | 12 +- mml_test.go | 638 ++++++++++++++++---------------- mmlexp2_test.go | 16 +- mmlexp3_test.go | 12 +- mmlexp_test.go | 840 +++++++++++++++++++++--------------------- node.go | 12 +- nodehead.go | 8 +- parse_test.go | 127 +++---- run_test.go | 10 +- scheme_test.go | 21 +- sequence.go | 8 +- sexpr_test.go | 28 +- syntax.go | 12 +- syntaxhead.go | 8 +- whitespace_test.go | 80 ++-- 27 files changed, 1070 insertions(+), 1077 deletions(-) diff --git a/boot_test.go b/boot_test.go index 09af372..7b1d74f 100644 --- a/boot_test.go +++ b/boot_test.go @@ -6,15 +6,15 @@ import ( "testing" ) -func parseWithSyntax(s *Syntax, f io.ReadSeeker) (*Node, error) { +func parseWithSyntax(s *Syntax, f io.ReadSeeker) (Node, error) { if _, err := f.Seek(0, 0); err != nil { - return nil, err + return Node{}, err } return s.Parse(f) } -func syntaxFromTree(n *Node) (*Syntax, error) { +func syntaxFromTree(n Node) (*Syntax, error) { s := &Syntax{} if err := define(s, n); err != nil { return nil, err @@ -27,17 +27,17 @@ func syntaxFromTree(n *Node) (*Syntax, error) { return s, nil } -func testParseFromTree(t *testing.T, n *Node, f io.ReadSeeker) *Node { +func testParseFromTree(t *testing.T, n Node, f io.ReadSeeker) Node { s, err := syntaxFromTree(n) if err != nil { t.Error(err) - return nil + return Node{} } nn, err := parseWithSyntax(s, f) if err != nil { t.Error(err) - return nil + return Node{} } checkNode(t, false, nn, n) diff --git a/char.go b/char.go index 0ed206c..52e16ce 100644 --- a/char.go +++ b/char.go @@ -54,6 +54,6 @@ func (p *charParser) parse(c *context) { func (b *charBuilder) nodeName() string { return b.name } func (b *charBuilder) nodeID() int { return b.id } -func (b *charBuilder) build(c *context) ([]*Node, bool) { +func (b *charBuilder) build(c *context) ([]Node, bool) { return nil, false } diff --git a/check_test.go b/check_test.go index 3d33fbb..b17a8a3 100644 --- a/check_test.go +++ b/check_test.go @@ -2,7 +2,7 @@ package treerack import "testing" -func checkNodes(t *testing.T, ignorePosition bool, left, right []*Node) { +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)) t.Log(left) @@ -20,16 +20,7 @@ func checkNodes(t *testing.T, ignorePosition bool, left, right []*Node) { } } -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 - } - +func checkNode(t *testing.T, ignorePosition bool, left, right Node) { if left.Name != right.Name { t.Error("name doesn't match", left.Name, right.Name) return diff --git a/choice.go b/choice.go index c50f71c..9f12c98 100644 --- a/choice.go +++ b/choice.go @@ -126,7 +126,7 @@ func (p *choiceParser) parse(c *context) { func (b *choiceBuilder) nodeName() string { return b.name } func (b *choiceBuilder) nodeID() int { return b.id } -func (b *choiceBuilder) build(c *context) ([]*Node, bool) { +func (b *choiceBuilder) build(c *context) ([]Node, bool) { to, ok := c.results.longestMatch(c.offset, b.id) if !ok { return nil, false @@ -171,7 +171,7 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) { return n, true } - return []*Node{{ + return []Node{{ Name: b.name, From: from, To: to, diff --git a/cmd/treerack/show.go b/cmd/treerack/show.go index 912a53d..adc1cbe 100644 --- a/cmd/treerack/show.go +++ b/cmd/treerack/show.go @@ -35,7 +35,7 @@ type node struct { Nodes []node `json:"nodes,omitempty"` } -func mapNode(n *treerack.Node) node { +func mapNode(n treerack.Node) node { var nn node nn.Name = n.Name nn.From = n.From diff --git a/define.go b/define.go index 354e8b0..f6e05f3 100644 --- a/define.go +++ b/define.go @@ -2,15 +2,13 @@ package treerack import "strconv" -func dropComments(n *Node) *Node { - ncc := *n - nc := &ncc - nc.Nodes = filterNodes(func(n *Node) bool { return n.Name != "comment" }, n.Nodes) - nc.Nodes = mapNodes(dropComments, nc.Nodes) - return nc +func dropComments(n Node) Node { + n.Nodes = filterNodes(func(n Node) bool { return n.Name != "comment" }, n.Nodes) + n.Nodes = mapNodes(dropComments, n.Nodes) + return n } -func flagsToCommitType(n []*Node) CommitType { +func flagsToCommitType(n []Node) CommitType { var ct CommitType for _, ni := range n { switch ni.Name { @@ -38,7 +36,7 @@ func toRune(c string) rune { return []rune(c)[0] } -func nodeChar(n *Node) rune { +func nodeChar(n Node) rune { s := n.Text() if s[0] == '\\' { return unescapeChar(toRune(s[1:])) @@ -47,7 +45,7 @@ func nodeChar(n *Node) rune { return toRune(s) } -func defineMember(s *Syntax, defaultName string, ct CommitType, n *Node) (string, error) { +func defineMember(s *Syntax, defaultName string, ct CommitType, n Node) (string, error) { switch n.Name { case "symbol": return n.Text(), nil @@ -56,7 +54,7 @@ func defineMember(s *Syntax, defaultName string, ct CommitType, n *Node) (string } } -func defineClass(s *Syntax, name string, ct CommitType, n []*Node) error { +func defineClass(s *Syntax, name string, ct CommitType, n []Node) error { var ( not bool chars []rune @@ -79,7 +77,7 @@ func defineClass(s *Syntax, name string, ct CommitType, n []*Node) error { return s.class(name, ct, not, chars, ranges) } -func defineCharSequence(s *Syntax, name string, ct CommitType, charNodes []*Node) error { +func defineCharSequence(s *Syntax, name string, ct CommitType, charNodes []Node) error { var chars []rune for _, ci := range charNodes { chars = append(chars, nodeChar(ci)) @@ -88,7 +86,7 @@ func defineCharSequence(s *Syntax, name string, ct CommitType, charNodes []*Node return s.charSequence(name, ct, chars) } -func getQuantity(n *Node) (min int, max int, err error) { +func getQuantity(n Node) (min int, max int, err error) { switch n.Name { case "count-quantifier": min, err = strconv.Atoi(n.Nodes[0].Text()) @@ -125,11 +123,11 @@ func getQuantity(n *Node) (min int, max int, err error) { return } -func defineSymbol(s *Syntax, name string, ct CommitType, n *Node) error { +func defineSymbol(s *Syntax, name string, ct CommitType, n Node) error { return s.sequence(name, ct, SequenceItem{Name: n.Text()}) } -func defineSequence(s *Syntax, name string, ct CommitType, n ...*Node) error { +func defineSequence(s *Syntax, name string, ct CommitType, n ...Node) error { nows := ct & NoWhitespace var items []SequenceItem for i, ni := range n { @@ -157,7 +155,7 @@ func defineSequence(s *Syntax, name string, ct CommitType, n ...*Node) error { return s.sequence(name, ct, items...) } -func defineChoice(s *Syntax, name string, ct CommitType, n ...*Node) error { +func defineChoice(s *Syntax, name string, ct CommitType, n ...Node) error { var refs []string memberCT := ct&NoWhitespace | Alias for i, ni := range n { @@ -173,7 +171,7 @@ func defineChoice(s *Syntax, name string, ct CommitType, n ...*Node) error { return s.choice(name, ct, refs...) } -func defineExpression(s *Syntax, name string, ct CommitType, expression *Node) error { +func defineExpression(s *Syntax, name string, ct CommitType, expression Node) error { var err error switch expression.Name { case "any-char": @@ -193,7 +191,7 @@ func defineExpression(s *Syntax, name string, ct CommitType, expression *Node) e return err } -func addDefinition(s *Syntax, n *Node) error { +func addDefinition(s *Syntax, n Node) error { return defineExpression( s, n.Nodes[0].Text(), @@ -202,7 +200,7 @@ func addDefinition(s *Syntax, n *Node) error { ) } -func define(s *Syntax, syntaxTree *Node) error { +func define(s *Syntax, syntaxTree Node) error { syntaxTree = dropComments(syntaxTree) for _, n := range syntaxTree.Nodes { if err := addDefinition(s, n); err != nil { diff --git a/format.go b/format.go index b3304f7..e3c3a3e 100644 --- a/format.go +++ b/format.go @@ -22,14 +22,14 @@ const ( type formatItem struct { commentFormat commentFormat - node *Node + node Node } type formatGroup struct { items []formatItem } -func topLevelCommentFormat(ast *Node, i int, n *Node) commentFormat { +func topLevelCommentFormat(ast Node, i int, n Node) commentFormat { if n.Name != "comment" { return commentFormatNone } @@ -64,7 +64,7 @@ func topLevelCommentFormat(ast *Node, i int, n *Node) commentFormat { return headerComment } -func groupASTByComments(ast *Node) []formatGroup { +func groupASTByComments(ast Node) []formatGroup { var ( groups []formatGroup currentGroup formatGroup @@ -174,7 +174,7 @@ func trimComment(text string, withBlockBody bool) string { return strings.Join(lines, "\n") } -func formatComment(out io.Writer, n *Node, withBlockBody bool) error { +func formatComment(out io.Writer, n Node, withBlockBody bool) error { text := n.Text() text = trimComment(text, withBlockBody) _, err := fmt.Fprint(out, text) @@ -221,17 +221,17 @@ func formatAnyChar(out io.Writer) error { return err } -func formatCharClass(out io.Writer, n *Node) error { +func formatCharClass(out io.Writer, n Node) error { _, err := fmt.Fprint(out, n.Text()) return err } -func formatCharSequence(out io.Writer, n *Node) error { +func formatCharSequence(out io.Writer, n Node) error { _, err := fmt.Fprint(out, n.Text()) return err } -func formatSymbol(out io.Writer, n *Node) error { +func formatSymbol(out io.Writer, n Node) error { _, err := fmt.Fprint(out, n.Text()) return err } @@ -249,7 +249,7 @@ func decTargetWidth(w, by int) int { return w } -func formatSequenceItemNode(out io.Writer, targetWidth int, n *Node) error { +func formatSequenceItemNode(out io.Writer, targetWidth int, n Node) error { var ( min, max int err error @@ -345,7 +345,7 @@ func formatSequenceItemNode(out io.Writer, targetWidth int, n *Node) error { return err } -func formatSequenceItemNodes(out io.Writer, targetWidth int, n []*Node) error { +func formatSequenceItemNodes(out io.Writer, targetWidth int, n []Node) error { sep := " " if targetWidth >= 0 { sep = "\n " @@ -374,7 +374,7 @@ func formatSequenceItemNodes(out io.Writer, targetWidth int, n []*Node) error { return nil } -func formatSequence(out io.Writer, targetWidth int, n []*Node) error { +func formatSequence(out io.Writer, targetWidth int, n []Node) error { var hasComments bool for _, ni := range n { if ni.Name == "comment" { @@ -403,7 +403,7 @@ func formatSequence(out io.Writer, targetWidth int, n []*Node) error { return err } -func formatChoiceOptionNodes(out io.Writer, targetWidth int, n []*Node) error { +func formatChoiceOptionNodes(out io.Writer, targetWidth int, n []Node) error { sep, commentSep := " | ", " " if targetWidth >= 0 { sep, commentSep = "\n| ", "\n" @@ -438,7 +438,7 @@ func formatChoiceOptionNodes(out io.Writer, targetWidth int, n []*Node) error { return nil } -func formatChoice(out io.Writer, targetWidth int, n []*Node) error { +func formatChoice(out io.Writer, targetWidth int, n []Node) error { var hasComments bool for _, ni := range n { if ni.Name == "comment" { @@ -467,7 +467,7 @@ func formatChoice(out io.Writer, targetWidth int, n []*Node) error { return err } -func formatExpression(out io.Writer, targetWidth int, n *Node) error { +func formatExpression(out io.Writer, targetWidth int, n Node) error { var err error switch n.Name { case "comment": @@ -489,7 +489,7 @@ func formatExpression(out io.Writer, targetWidth int, n *Node) error { return err } -func formatDefinition(out io.Writer, targetWidth, namesWidth int, pad, name string, n *Node) error { +func formatDefinition(out io.Writer, targetWidth, namesWidth int, pad, name string, n Node) error { var ( buf bytes.Buffer foundComment bool @@ -616,7 +616,7 @@ func formatASTGroup(out io.Writer, g formatGroup) error { return nil } -func formatAST(out io.Writer, ast *Node) error { +func formatAST(out io.Writer, ast Node) error { // drop whitespace comments // use line comments by default // comment types: diff --git a/head.go b/head.go index 7ab216d..2c01c31 100644 --- a/head.go +++ b/head.go @@ -1,4 +1,4 @@ package treerack // generated with script/createhead.go -const headCode = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() commitType {\n\treturn alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]*node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount\tint\n\t\tparsed\t\tbool\n\t)\n\titemIndex := 0\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]*node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []*node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]*node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []*node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&whitespace == 0 && p.commitType()&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]*node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []*node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = errInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &parseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype node struct {\n\tName\tstring\n\tNodes\t[]*node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n *node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n *node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n *node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype commitType int\n\nconst (\n\tnone\tcommitType\t= 0\n\talias\tcommitType\t= 1 << iota\n\twhitespace\n\tnoWhitespace\n\tkeyword\n\tnoKeyword\n\tfailPass\n\troot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype parseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() commitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]*node, bool)\n}\n\nvar errInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *parseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (*node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn nil, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*parseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn nil, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" +const headCode = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() commitType {\n\treturn alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount\tint\n\t\tparsed\t\tbool\n\t)\n\titemIndex := 0\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&whitespace == 0 && p.commitType()&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = errInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &parseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype node struct {\n\tName\tstring\n\tNodes\t[]node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype commitType int\n\nconst (\n\tnone\tcommitType\t= 0\n\talias\tcommitType\t= 1 << iota\n\twhitespace\n\tnoWhitespace\n\tkeyword\n\tnoKeyword\n\tfailPass\n\troot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype parseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() commitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]node, bool)\n}\n\nvar errInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *parseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn node{}, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*parseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn node{}, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" diff --git a/headexported.go b/headexported.go index a090798..9defe65 100644 --- a/headexported.go +++ b/headexported.go @@ -1,4 +1,4 @@ package treerack // generated with script/createhead.go -const headCodeExported = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() CommitType {\n\treturn Alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]*Node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount\tint\n\t\tparsed\t\tbool\n\t)\n\titemIndex := 0\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]*Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&Alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []*Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]*Node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []*Node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&Whitespace == 0 && p.commitType()&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]*Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []*Node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = ErrInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &ParseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype Node struct {\n\tName\tstring\n\tNodes\t[]*Node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n *Node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n *Node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n *Node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype CommitType int\n\nconst (\n\tNone\tCommitType\t= 0\n\tAlias\tCommitType\t= 1 << iota\n\tWhitespace\n\tNoWhitespace\n\tKeyword\n\tNoKeyword\n\tFailPass\n\tRoot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype ParseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() CommitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]*Node, bool)\n}\n\nvar ErrInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *ParseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (*Node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn nil, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*ParseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn nil, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" +const headCodeExported = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() CommitType {\n\treturn Alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]Node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount\tint\n\t\tparsed\t\tbool\n\t)\n\titemIndex := 0\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&Alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]Node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []Node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&Whitespace == 0 && p.commitType()&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []Node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = ErrInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &ParseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype Node struct {\n\tName\tstring\n\tNodes\t[]Node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n Node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n Node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n Node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype CommitType int\n\nconst (\n\tNone\tCommitType\t= 0\n\tAlias\tCommitType\t= 1 << iota\n\tWhitespace\n\tNoWhitespace\n\tKeyword\n\tNoKeyword\n\tFailPass\n\tRoot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype ParseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() CommitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]Node, bool)\n}\n\nvar ErrInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *ParseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (Node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn Node{}, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*ParseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn Node{}, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" diff --git a/internal/self/self.go b/internal/self/self.go index 6b07a9e..91bfb62 100644 --- a/internal/self/self.go +++ b/internal/self/self.go @@ -83,7 +83,7 @@ func (b *charBuilder) nodeName() string { func (b *charBuilder) nodeID() int { return b.id } -func (b *charBuilder) build(c *context) ([]*Node, bool) { +func (b *charBuilder) build(c *context) ([]Node, bool) { return nil, false } @@ -199,7 +199,7 @@ func (b *sequenceBuilder) nodeName() string { func (b *sequenceBuilder) nodeID() int { return b.id } -func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { +func (b *sequenceBuilder) build(c *context) ([]Node, bool) { to, ok := c.results.longestMatch(c.offset, b.id) if !ok { return nil, false @@ -211,7 +211,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { if b.commit&Alias != 0 { return nil, true } - return []*Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true + return []Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true } else if parsed { c.results.dropMatchTo(c.offset, b.id, to) for _, g := range b.generalizations { @@ -229,7 +229,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { var ( itemIndex int currentCount int - nodes []*Node + nodes []Node ) for itemIndex < len(b.items) { itemFrom := c.offset @@ -265,7 +265,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { if b.commit&Alias != 0 { return nodes, true } - return []*Node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true + return []Node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true } type choiceParser struct { @@ -378,7 +378,7 @@ func (b *choiceBuilder) nodeName() string { func (b *choiceBuilder) nodeID() int { return b.id } -func (b *choiceBuilder) build(c *context) ([]*Node, bool) { +func (b *choiceBuilder) build(c *context) ([]Node, bool) { to, ok := c.results.longestMatch(c.offset, b.id) if !ok { return nil, false @@ -416,7 +416,7 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) { if b.commit&Alias != 0 { return n, true } - return []*Node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true + return []Node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true } type idSet struct{ ids []uint } @@ -733,19 +733,19 @@ func (c *context) finalizeParse(root parser) error { type Node struct { Name string - Nodes []*Node + Nodes []Node From int To int tokens []rune } -func (n *Node) Tokens() []rune { +func (n Node) Tokens() []rune { return n.tokens } -func (n *Node) String() string { +func (n Node) String() string { return fmt.Sprintf("%s:%d:%d:%s", n.Name, n.From, n.To, n.Text()) } -func (n *Node) Text() string { +func (n Node) Text() string { return string(n.Tokens()[n.From:n.To]) } @@ -791,7 +791,7 @@ type parser interface { type builder interface { nodeName() string nodeID() int - build(*context) ([]*Node, bool) + build(*context) ([]Node, bool) } var ErrInvalidUnicodeCharacter = errors.New("invalid unicode character") @@ -799,17 +799,17 @@ var ErrInvalidUnicodeCharacter = errors.New("invalid unicode character") func (pe *ParseError) Error() string { return fmt.Sprintf("%s:%d:%d:parse failed, parsing: %s", pe.Input, pe.Line+1, pe.Column+1, pe.Definition) } -func parseInput(r io.Reader, p parser, b builder, kw []parser) (*Node, error) { +func parseInput(r io.Reader, p parser, b builder, kw []parser) (Node, error) { c := newContext(bufio.NewReader(r), kw) p.parse(c) if c.readErr != nil { - return nil, c.readErr + return Node{}, c.readErr } if err := c.finalizeParse(p); err != nil { if perr, ok := err.(*ParseError); ok { perr.Input = "" } - return nil, err + return Node{}, err } c.offset = 0 c.results.resetPending() @@ -819,7 +819,7 @@ func parseInput(r io.Reader, p parser, b builder, kw []parser) (*Node, error) { // eo head -func Parse(r io.Reader) (*Node, error) { +func Parse(r io.Reader) (Node, error) { var p172 = sequenceParser{id: 172, commit: 128, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} var p170 = choiceParser{id: 170, commit: 2} diff --git a/json_test.go b/json_test.go index 8376e32..ac19a48 100644 --- a/json_test.go +++ b/json_test.go @@ -142,7 +142,7 @@ func parseJSONNumber(t string) (interface{}, error) { return n.Float64() } -func nodeToJSONObject(n *Node) (map[string]interface{}, error) { +func nodeToJSONObject(n Node) (map[string]interface{}, error) { o := make(map[string]interface{}) for _, ni := range n.Nodes { if len(ni.Nodes) != 2 { @@ -165,7 +165,7 @@ func nodeToJSONObject(n *Node) (map[string]interface{}, error) { return o, nil } -func nodeToJSONArray(n *Node) ([]interface{}, error) { +func nodeToJSONArray(n Node) ([]interface{}, error) { a := make([]interface{}, 0, len(n.Nodes)) for _, ni := range n.Nodes { item, err := treeToJSON(ni) @@ -179,7 +179,7 @@ func nodeToJSONArray(n *Node) ([]interface{}, error) { return a, nil } -func treeToJSON(n *Node) (interface{}, error) { +func treeToJSON(n Node) (interface{}, error) { switch n.Name { case "true": return true, nil @@ -272,7 +272,7 @@ func checkJSON(t *testing.T, got, expected interface{}) { } } -func jsonTreeToJSON(n *Node) (interface{}, error) { +func jsonTreeToJSON(n Node) (interface{}, error) { if n.Name != "json" { return nil, fmt.Errorf("invalid root node name: %s", n.Name) } @@ -288,9 +288,9 @@ func TestJSON(t *testing.T) { runTestsFile(t, "doc/example/json.treerack", []testItem{{ title: "true", text: "true", - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "true", }}, }, @@ -298,9 +298,9 @@ func TestJSON(t *testing.T) { }, { title: "false", text: "false", - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "false", }}, }, @@ -308,9 +308,9 @@ func TestJSON(t *testing.T) { }, { title: "null", text: "null", - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "null", }}, }, @@ -318,9 +318,9 @@ func TestJSON(t *testing.T) { }, { title: "string", text: `"\"\\n\b\t\uabcd"`, - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }}, }, @@ -328,9 +328,9 @@ func TestJSON(t *testing.T) { }, { title: "number", text: "6.62e-34", - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "number", }}, }, @@ -346,55 +346,55 @@ func TestJSON(t *testing.T) { "object": {}, "array": [] }`, - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "object", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "true", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "false", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "null", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "string", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "number", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "object", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "array", @@ -414,11 +414,11 @@ func TestJSON(t *testing.T) { "object": {}, "array": [] }, []]`, - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "array", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "true", }, { Name: "false", @@ -430,51 +430,51 @@ func TestJSON(t *testing.T) { Name: "number", }, { Name: "object", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "true", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "false", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "null", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "string", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "number", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "object", }}, }, { Name: "entry", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }, { Name: "array", @@ -489,9 +489,9 @@ func TestJSON(t *testing.T) { }, { title: "bugfix, 100", text: "100", - node: &Node{ + node: Node{ Name: "json", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "number", }}, }, diff --git a/keyval_test.go b/keyval_test.go index 368d1b1..e4acfcd 100644 --- a/keyval_test.go +++ b/keyval_test.go @@ -5,19 +5,21 @@ import "testing" func TestKeyVal(t *testing.T) { runTestsFile(t, "doc/example/keyval.treerack", []testItem{{ title: "empty", + node: Node{Name: "doc"}, }, { title: "a comment", text: "# a comment", + node: Node{Name: "doc", To: 11}, }, { title: "a key", text: "a key", - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 5, }}, @@ -26,15 +28,15 @@ func TestKeyVal(t *testing.T) { }, { title: "a key with a preceeding whitespace", text: " a key", - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", From: 1, To: 6, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", From: 1, To: 6, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 6, @@ -48,15 +50,15 @@ func TestKeyVal(t *testing.T) { a key `, - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", From: 20, To: 25, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", From: 20, To: 25, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 20, To: 25, @@ -66,13 +68,13 @@ func TestKeyVal(t *testing.T) { }, { title: "a key value pair", text: "a key = a value", - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", To: 15, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 5, }}, @@ -86,15 +88,15 @@ func TestKeyVal(t *testing.T) { title: "key value pairs with a comment at the end of line", text: "a key = a value # a comment\n" + "another key = another value # another comment", - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", From: 0, To: 39, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", From: 0, To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 0, To: 5, @@ -108,11 +110,11 @@ func TestKeyVal(t *testing.T) { Name: "key-val", From: 40, To: 85, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", From: 40, To: 51, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 40, To: 51, @@ -126,10 +128,10 @@ func TestKeyVal(t *testing.T) { }, { title: "value without a key", text: "= a value", - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value", From: 2, To: 9, @@ -141,11 +143,11 @@ func TestKeyVal(t *testing.T) { # a comment a key = a value `, - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", From: 4, To: 34, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "comment", From: 4, To: 15, @@ -153,7 +155,7 @@ func TestKeyVal(t *testing.T) { Name: "key", From: 19, To: 24, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 19, To: 24, @@ -167,14 +169,14 @@ func TestKeyVal(t *testing.T) { }, { title: "a key with multiple symbols", text: "a key . with.multiple.symbols=a value", - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", To: 37, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", From: 0, To: 29, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 0, To: 5, @@ -203,11 +205,11 @@ func TestKeyVal(t *testing.T) { # a comment [a group key.empty] `, - nodes: []*Node{{ + nodes: []Node{{ Name: "group-key", From: 4, To: 38, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "comment", From: 4, To: 15, @@ -229,9 +231,9 @@ func TestKeyVal(t *testing.T) { = two = three `, - nodes: []*Node{{ + nodes: []Node{{ Name: "group-key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -240,17 +242,17 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value", }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value", }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value", }}, }}, @@ -258,9 +260,9 @@ func TestKeyVal(t *testing.T) { }, { title: "a group key with multiple values, in a single line", text: "[foo.bar.baz] = one = two = three", - nodes: []*Node{{ + nodes: []Node{{ Name: "group-key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -269,17 +271,17 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value", }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value", }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value", }}, }}, @@ -301,11 +303,11 @@ func TestKeyVal(t *testing.T) { b = 2 # even c = 3 `, - nodes: []*Node{{ + nodes: []Node{{ Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -313,9 +315,9 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -325,9 +327,9 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -337,9 +339,9 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -347,7 +349,7 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "group-key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "comment", }, { Name: "symbol", @@ -358,9 +360,9 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -368,9 +370,9 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -378,9 +380,9 @@ func TestKeyVal(t *testing.T) { }}, }, { Name: "key-val", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "key", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { diff --git a/keyword_test.go b/keyword_test.go index d5f41ec..0a3438d 100644 --- a/keyword_test.go +++ b/keyword_test.go @@ -14,9 +14,9 @@ func TestKeyword(t *testing.T) { title: "not keyword", text: "baz", ignorePosition: true, - node: &Node{ + node: Node{ Name: "doc", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, @@ -24,9 +24,9 @@ func TestKeyword(t *testing.T) { title: "keyword", text: "foo", ignorePosition: true, - node: &Node{ + node: Node{ Name: "doc", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "keyword", }}, }, @@ -34,9 +34,9 @@ func TestKeyword(t *testing.T) { title: "mixed", text: "foo bar baz bar foo baz bar", ignorePosition: true, - node: &Node{ + node: Node{ Name: "doc", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "keyword", }, { Name: "keyword", diff --git a/mml_test.go b/mml_test.go index b9c9874..a25f1f7 100644 --- a/mml_test.go +++ b/mml_test.go @@ -12,11 +12,11 @@ func TestMML(t *testing.T) { t.Run("comment", func(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "empty", - node: &Node{Name: "mml"}, + node: Node{Name: "mml"}, }, { title: "single line comment", text: "// foo bar baz", - nodes: []*Node{{ + nodes: []Node{{ Name: "line-comment-content", From: 2, To: 14, @@ -24,7 +24,7 @@ func TestMML(t *testing.T) { }, { title: "multiple line comments", text: "// foo bar\n// baz qux", - nodes: []*Node{{ + nodes: []Node{{ Name: "line-comment-content", From: 2, To: 10, @@ -36,7 +36,7 @@ func TestMML(t *testing.T) { }, { title: "block comment", text: "/* foo bar baz */", - nodes: []*Node{{ + nodes: []Node{{ Name: "block-comment-content", From: 2, To: 15, @@ -44,7 +44,7 @@ func TestMML(t *testing.T) { }, { title: "block comments", text: "/* foo bar */\n/* baz qux */", - nodes: []*Node{{ + nodes: []Node{{ Name: "block-comment-content", From: 2, To: 11, @@ -56,7 +56,7 @@ func TestMML(t *testing.T) { }, { title: "mixed comments", text: "// foo\n/* bar */\n// baz", - nodes: []*Node{{ + nodes: []Node{{ Name: "line-comment-content", From: 2, To: 6, @@ -76,14 +76,14 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "int", text: "42", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 2, }}, }, { title: "ints", text: "1; 2; 3", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 1, }, { @@ -98,14 +98,14 @@ func TestMML(t *testing.T) { }, { title: "int, octal", text: "052", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 3, }}, }, { title: "int, hexa", text: "0x2a", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 4, }}, @@ -116,56 +116,56 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "float, 0.", text: "0.", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 2, }}, }, { title: "float, 72.40", text: "72.40", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 5, }}, }, { title: "float, 072.40", text: "072.40", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 6, }}, }, { title: "float, 2.71828", text: "2.71828", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 7, }}, }, { title: "float, 6.67428e-11", text: "6.67428e-11", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 11, }}, }, { title: "float, 1E6", text: "1E6", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 3, }}, }, { title: "float, .25", text: ".25", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 3, }}, }, { title: "float, .12345E+5", text: ".12345E+5", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 9, }}, @@ -173,9 +173,9 @@ func TestMML(t *testing.T) { title: "float on a new line", text: "f()\n.9", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -189,35 +189,35 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "string, empty", text: "\"\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 2, }}, }, { title: "string", text: "\"foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 5, }}, }, { title: "string, with new line", text: "\"foo\nbar\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 9, }}, }, { title: "string, with escaped new line", text: "\"foo\\nbar\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 10, }}, }, { title: "string, with quotes", text: "\"foo \\\"bar\\\" baz\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 17, }}, @@ -228,14 +228,14 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "bool, true", text: "true", - nodes: []*Node{{ + nodes: []Node{{ Name: "true", To: 4, }}, }, { title: "bool, false", text: "false", - nodes: []*Node{{ + nodes: []Node{{ Name: "false", To: 5, }}, @@ -246,7 +246,7 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "symbol", text: "foo", - nodes: []*Node{{ + nodes: []Node{{ Name: "symbol", To: 3, }}, @@ -257,17 +257,17 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "empty list", text: "[]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 2, }}, }, { title: "list", text: "[a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 2, @@ -284,10 +284,10 @@ func TestMML(t *testing.T) { }, { title: "list, new lines", text: "[ \n a \n b \n c \n ]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -304,10 +304,10 @@ func TestMML(t *testing.T) { }, { title: "list, complex", text: "[a, b, c..., [d, e], [f, [g]]...]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 33, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 2, @@ -319,7 +319,7 @@ func TestMML(t *testing.T) { Name: "spread-expression", From: 7, To: 11, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -328,7 +328,7 @@ func TestMML(t *testing.T) { Name: "list", From: 13, To: 19, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 14, To: 15, @@ -341,11 +341,11 @@ func TestMML(t *testing.T) { Name: "spread-expression", From: 21, To: 32, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list", From: 21, To: 29, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 22, To: 23, @@ -353,7 +353,7 @@ func TestMML(t *testing.T) { Name: "list", From: 25, To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 26, To: 27, @@ -369,10 +369,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "mutable list", text: "~[a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "mutable-list", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 3, @@ -393,21 +393,21 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "empty struct", text: "{}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 2, }}, }, { title: "struct", text: "{foo: 1, \"bar\": 2}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 18, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 1, To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 4, @@ -420,7 +420,7 @@ func TestMML(t *testing.T) { Name: "entry", From: 9, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", From: 9, To: 14, @@ -434,14 +434,14 @@ func TestMML(t *testing.T) { }, { title: "struct, complex", text: "{foo: 1, {bar: 2}..., {baz: {}}...}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 35, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 1, To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 4, @@ -454,15 +454,15 @@ func TestMML(t *testing.T) { Name: "spread-expression", From: 9, To: 20, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "struct", From: 9, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 10, To: 16, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 10, To: 13, @@ -477,15 +477,15 @@ func TestMML(t *testing.T) { Name: "spread-expression", From: 22, To: 34, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "struct", From: 22, To: 31, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 23, To: 30, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 23, To: 26, @@ -501,18 +501,18 @@ func TestMML(t *testing.T) { }, { title: "with indexer key", text: "{[a]: b}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 1, To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "expression-key", From: 1, To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 3, @@ -531,14 +531,14 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "mutable struct", text: "~{foo: 1}", - nodes: []*Node{{ + nodes: []Node{{ Name: "mutable-struct", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 2, To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 5, @@ -556,17 +556,17 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "channel", text: "<>", - nodes: []*Node{{ + nodes: []Node{{ Name: "channel", To: 2, }}, }, { title: "buffered channel", text: "<42>", - nodes: []*Node{{ + nodes: []Node{{ Name: "channel", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 1, To: 3, @@ -579,10 +579,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "and expression", text: "and(a, b, c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 12, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 3, }, { @@ -602,10 +602,10 @@ func TestMML(t *testing.T) { }, { title: "or expression", text: "or(a, b, c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 11, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 2, }, { @@ -629,10 +629,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "function", text: "fn () 42", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 6, To: 8, @@ -641,10 +641,10 @@ func TestMML(t *testing.T) { }, { title: "function, noop", text: "fn () {;}", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "block", From: 6, To: 9, @@ -653,10 +653,10 @@ func TestMML(t *testing.T) { }, { title: "function with args", text: "fn (a, b, c) [a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 22, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -672,7 +672,7 @@ func TestMML(t *testing.T) { Name: "list", From: 13, To: 22, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 14, To: 15, @@ -690,10 +690,10 @@ func TestMML(t *testing.T) { }, { title: "function with args in new lines", text: "fn ( \n a \n b \n c ) [a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -709,7 +709,7 @@ func TestMML(t *testing.T) { Name: "list", From: 19, To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 20, To: 21, @@ -727,10 +727,10 @@ func TestMML(t *testing.T) { }, { title: "function with spread arg", text: "fn (a, b, ...c) [a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 25, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -742,7 +742,7 @@ func TestMML(t *testing.T) { Name: "collect-parameter", From: 10, To: 14, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 13, To: 14, @@ -751,7 +751,7 @@ func TestMML(t *testing.T) { Name: "list", From: 16, To: 25, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 17, To: 18, @@ -773,10 +773,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "effect", text: "fn ~ () 42", - nodes: []*Node{{ + nodes: []Node{{ Name: "effect", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 8, To: 10, @@ -789,10 +789,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "indexer", text: "a[42]", - nodes: []*Node{{ + nodes: []Node{{ Name: "expression-indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -804,17 +804,17 @@ func TestMML(t *testing.T) { }, { title: "range indexer", text: "a[3:9]", - nodes: []*Node{{ + nodes: []Node{{ Name: "expression-indexer", To: 6, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "range-from", From: 2, To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 2, To: 3, @@ -823,7 +823,7 @@ func TestMML(t *testing.T) { Name: "range-to", From: 4, To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 4, To: 5, @@ -833,17 +833,17 @@ func TestMML(t *testing.T) { }, { title: "range indexer, lower unbound", text: "a[:9]", - nodes: []*Node{{ + nodes: []Node{{ Name: "expression-indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "range-to", From: 3, To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 3, To: 4, @@ -853,17 +853,17 @@ func TestMML(t *testing.T) { }, { title: "range indexer, upper unbound", text: "a[3:]", - nodes: []*Node{{ + nodes: []Node{{ Name: "expression-indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "range-from", From: 2, To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 2, To: 3, @@ -873,16 +873,16 @@ func TestMML(t *testing.T) { }, { title: "indexer, chained", text: "a[b][c][d]", - nodes: []*Node{{ + nodes: []Node{{ Name: "expression-indexer", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "expression-indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "expression-indexer", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -908,10 +908,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "symbol indexer", text: "a.b", - nodes: []*Node{{ + nodes: []Node{{ Name: "symbol-indexer", To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -923,16 +923,16 @@ func TestMML(t *testing.T) { }, { title: "chained symbol indexer", text: "a.b.c.d", - nodes: []*Node{{ + nodes: []Node{{ Name: "symbol-indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol-indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol-indexer", To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -954,13 +954,13 @@ func TestMML(t *testing.T) { }, { title: "chained symbol indexer on new line", text: "a\n.b\n.c", - nodes: []*Node{{ + nodes: []Node{{ Name: "symbol-indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol-indexer", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -977,13 +977,13 @@ func TestMML(t *testing.T) { }, { title: "chained symbol indexer on new line after dot", text: "a.\nb.\nc", - nodes: []*Node{{ + nodes: []Node{{ Name: "symbol-indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol-indexer", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1004,10 +1004,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "function application", text: "f()", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }}, @@ -1015,10 +1015,10 @@ func TestMML(t *testing.T) { }, { title: "function application, single arg", text: "f(a)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1030,10 +1030,10 @@ func TestMML(t *testing.T) { }, { title: "function application, multiple args", text: "f(a, b, c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1053,10 +1053,10 @@ func TestMML(t *testing.T) { }, { title: "function application, multiple args, new line", text: "f(a\nb\nc\n)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1076,10 +1076,10 @@ func TestMML(t *testing.T) { }, { title: "function application, spread", text: "f(a, b..., c, d...)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 19, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1090,7 +1090,7 @@ func TestMML(t *testing.T) { Name: "spread-expression", From: 5, To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 5, To: 6, @@ -1103,7 +1103,7 @@ func TestMML(t *testing.T) { Name: "spread-expression", From: 14, To: 18, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 14, To: 15, @@ -1113,16 +1113,16 @@ func TestMML(t *testing.T) { }, { title: "chained function application", text: "f(a)(b)(c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1144,17 +1144,17 @@ func TestMML(t *testing.T) { }, { title: "embedded function application", text: "f(g(h(a)))", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "function-application", From: 2, To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 3, @@ -1162,7 +1162,7 @@ func TestMML(t *testing.T) { Name: "function-application", From: 4, To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -1181,10 +1181,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "if", text: "if a { b() }", - nodes: []*Node{{ + nodes: []Node{{ Name: "if", To: 12, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 3, To: 4, @@ -1192,11 +1192,11 @@ func TestMML(t *testing.T) { Name: "block", From: 5, To: 12, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", From: 7, To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1207,10 +1207,10 @@ func TestMML(t *testing.T) { }, { title: "if, else", text: "if a { b } else { c }", - nodes: []*Node{{ + nodes: []Node{{ Name: "if", To: 21, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 3, To: 4, @@ -1218,7 +1218,7 @@ func TestMML(t *testing.T) { Name: "block", From: 5, To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1227,7 +1227,7 @@ func TestMML(t *testing.T) { Name: "block", From: 16, To: 21, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 18, To: 19, @@ -1237,11 +1237,11 @@ func TestMML(t *testing.T) { }, { title: "if, else if, else if, else", text: "if a { b }\nelse if c { d }\nelse if e { f }\nelse { g }", - nodes: []*Node{{ + nodes: []Node{{ Name: "if", From: 0, To: 53, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 3, To: 4, @@ -1249,7 +1249,7 @@ func TestMML(t *testing.T) { Name: "block", From: 5, To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1262,7 +1262,7 @@ func TestMML(t *testing.T) { Name: "block", From: 21, To: 26, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 23, To: 24, @@ -1275,7 +1275,7 @@ func TestMML(t *testing.T) { Name: "block", From: 37, To: 42, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 39, To: 40, @@ -1284,7 +1284,7 @@ func TestMML(t *testing.T) { Name: "block", From: 48, To: 53, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 50, To: 51, @@ -1298,10 +1298,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "switch, empty", text: "switch {default:}", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "default", From: 8, To: 16, @@ -1317,23 +1317,23 @@ func TestMML(t *testing.T) { f() } `, - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "default", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1342,10 +1342,10 @@ func TestMML(t *testing.T) { }, { title: "switch, single case", text: "switch a {case b: c}", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 20, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1353,7 +1353,7 @@ func TestMML(t *testing.T) { Name: "case", From: 10, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 15, To: 16, @@ -1367,10 +1367,10 @@ func TestMML(t *testing.T) { }, { title: "switch", text: "switch a {case b: c; case d: e; default: f}", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 43, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1378,7 +1378,7 @@ func TestMML(t *testing.T) { Name: "case", From: 10, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 15, To: 16, @@ -1391,7 +1391,7 @@ func TestMML(t *testing.T) { Name: "case", From: 21, To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 26, To: 27, @@ -1413,10 +1413,10 @@ func TestMML(t *testing.T) { }, { title: "switch, all new lines", text: "switch \n a \n { \n case \n b \n : \n c \n case \n d \n : \n e \n default \n : \n f \n }", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 74, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 9, To: 10, @@ -1424,7 +1424,7 @@ func TestMML(t *testing.T) { Name: "case", From: 17, To: 29, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 24, To: 25, @@ -1437,7 +1437,7 @@ func TestMML(t *testing.T) { Name: "case", From: 36, To: 48, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 43, To: 44, @@ -1463,9 +1463,9 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "receive op", text: "<<>chan", - nodes: []*Node{{ + nodes: []Node{{ Name: "receive", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1473,9 +1473,9 @@ func TestMML(t *testing.T) { }, { title: "send op", text: "chan <<> a", - nodes: []*Node{{ + nodes: []Node{{ Name: "send", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -1489,7 +1489,7 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "select, empty", text: "select {\n}", - nodes: []*Node{{ + nodes: []Node{{ Name: "select", To: 10, }}, @@ -1500,51 +1500,51 @@ func TestMML(t *testing.T) { case s <<> f(): g() default: h() }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "select", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "select-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "receive-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "receive", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, }}, }, { Name: "send", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "select-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "send", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "default", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1557,11 +1557,11 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "go", text: "go f()", - nodes: []*Node{{ + nodes: []Node{{ Name: "go", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1574,11 +1574,11 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "require, dot, equal", text: "require . = \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-inline", }, { Name: "string", @@ -1589,11 +1589,11 @@ func TestMML(t *testing.T) { }, { title: "require, symbol, equal", text: "require bar = \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", @@ -1604,11 +1604,11 @@ func TestMML(t *testing.T) { }, { title: "require, symbol", text: "require bar \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", @@ -1619,11 +1619,11 @@ func TestMML(t *testing.T) { }, { title: "require", text: "require \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }}, }}, @@ -1638,39 +1638,39 @@ func TestMML(t *testing.T) { bar "mml/foo" "mml/foo" )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-inline", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-inline", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }}, }}, @@ -1683,11 +1683,11 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "expression group", text: "(fn (a) a)(a)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -1704,9 +1704,9 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "unary operator", text: "!foo", - nodes: []*Node{{ + nodes: []Node{{ Name: "unary-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "logical-not", }, { Name: "symbol", @@ -1720,9 +1720,9 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "binary 0", text: "a * b", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1734,11 +1734,11 @@ func TestMML(t *testing.T) { }, { title: "binary 1", text: "a * b + c * d", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1749,7 +1749,7 @@ func TestMML(t *testing.T) { Name: "add", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1762,13 +1762,13 @@ func TestMML(t *testing.T) { }, { title: "binary 2", text: "a * b + c * d == e * f", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary2", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1779,7 +1779,7 @@ func TestMML(t *testing.T) { Name: "add", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1791,7 +1791,7 @@ func TestMML(t *testing.T) { Name: "eq", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1804,9 +1804,9 @@ func TestMML(t *testing.T) { }, { title: "binary 1, 1, 1", text: "a + b + c", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "add", @@ -1822,19 +1822,19 @@ func TestMML(t *testing.T) { }, { title: "binary 3, 4, 5", text: "a * b + c * d == e * f && g || h -> f()", - nodes: []*Node{{ + nodes: []Node{{ Name: "chaining", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary4", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary3", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary2", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1845,7 +1845,7 @@ func TestMML(t *testing.T) { Name: "add", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1857,7 +1857,7 @@ func TestMML(t *testing.T) { Name: "eq", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -1877,7 +1877,7 @@ func TestMML(t *testing.T) { }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1890,10 +1890,10 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "ternary expression", text: "a ? b : c", - nodes: []*Node{{ + nodes: []Node{{ Name: "ternary-expression", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1909,17 +1909,17 @@ func TestMML(t *testing.T) { }, { title: "multiple ternary expressions, consequence", text: "a ? b ? c : d : e", - nodes: []*Node{{ + nodes: []Node{{ Name: "ternary-expression", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "ternary-expression", From: 4, To: 13, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -1941,10 +1941,10 @@ func TestMML(t *testing.T) { }, { title: "multiple ternary expressions, alternative", text: "a ? b : c ? d : e", - nodes: []*Node{{ + nodes: []Node{{ Name: "ternary-expression", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1955,7 +1955,7 @@ func TestMML(t *testing.T) { Name: "ternary-expression", From: 8, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 8, To: 9, @@ -1977,9 +1977,9 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "infinite loop", text: "for {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "block", }}, }}, @@ -1987,9 +1987,9 @@ func TestMML(t *testing.T) { }, { title: "conditional loop", text: "for foo {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "block", @@ -1999,15 +1999,15 @@ func TestMML(t *testing.T) { }, { title: "in list loop", text: "for i in [1, 2, 3] {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "range-over-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", }, { Name: "int", @@ -2023,17 +2023,17 @@ func TestMML(t *testing.T) { }, { title: "in range loop", text: "for i in -3:42 {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "range-over-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "range-from", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "unary-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "minus", }, { Name: "int", @@ -2041,7 +2041,7 @@ func TestMML(t *testing.T) { }}, }, { Name: "range-to", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", }}, }}, @@ -2057,24 +2057,24 @@ func TestMML(t *testing.T) { break } }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "range-over-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "block", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "if", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary2", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mod", @@ -2088,7 +2088,7 @@ func TestMML(t *testing.T) { }}, }, { Name: "block", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -2103,9 +2103,9 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "assign, eq", text: "a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2115,9 +2115,9 @@ func TestMML(t *testing.T) { }, { title: "assign, set, eq", text: "set a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2127,9 +2127,9 @@ func TestMML(t *testing.T) { }, { title: "assign, set", text: "set a b", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2142,9 +2142,9 @@ func TestMML(t *testing.T) { a = b c d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2158,11 +2158,11 @@ func TestMML(t *testing.T) { }, { title: "assign to struct field", text: "set a.b c", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol-indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2175,11 +2175,11 @@ func TestMML(t *testing.T) { }, { title: "indexer", text: "set a[1] 42", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "expression-indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "int", @@ -2192,11 +2192,11 @@ func TestMML(t *testing.T) { }, { title: "indexer, eq", text: "a[1] = 42", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "expression-indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "int", @@ -2209,11 +2209,11 @@ func TestMML(t *testing.T) { }, { title: "indexer, set, eq", text: "set a[1] = 42", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "expression-indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "int", @@ -2230,11 +2230,11 @@ func TestMML(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "define, eq", text: "let a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2245,11 +2245,11 @@ func TestMML(t *testing.T) { }, { title: "define", text: "let a b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2260,11 +2260,11 @@ func TestMML(t *testing.T) { }, { title: "define mutable, eq", text: "let ~ a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2275,11 +2275,11 @@ func TestMML(t *testing.T) { }, { title: "define mutable", text: "let ~ a b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2295,32 +2295,32 @@ func TestMML(t *testing.T) { ~ e f ~ g h )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2334,18 +2334,18 @@ func TestMML(t *testing.T) { a = b c d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "mutable-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2356,11 +2356,11 @@ func TestMML(t *testing.T) { }, { title: "define function", text: "fn a() b", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2371,11 +2371,11 @@ func TestMML(t *testing.T) { }, { title: "define effect", text: "fn ~ a() b", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "effect-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2389,18 +2389,18 @@ func TestMML(t *testing.T) { a() b ~ c() d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "function-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "effect-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2414,18 +2414,18 @@ func TestMML(t *testing.T) { a() b c() d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "effect-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", diff --git a/mmlexp2_test.go b/mmlexp2_test.go index 73e8f6f..502fa60 100644 --- a/mmlexp2_test.go +++ b/mmlexp2_test.go @@ -16,18 +16,18 @@ func TestMMLExp2(t *testing.T) { title: "mixed indexer", text: "a.b[c]", ignorePosition: true, - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol-index", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "expression-index", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -38,18 +38,18 @@ func TestMMLExp2(t *testing.T) { title: "mixed indexer inverted", text: "a[b].c", ignorePosition: true, - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "expression-index", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "symbol-index", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, diff --git a/mmlexp3_test.go b/mmlexp3_test.go index 887b6a2..dc72498 100644 --- a/mmlexp3_test.go +++ b/mmlexp3_test.go @@ -16,21 +16,21 @@ func TestMMLExp3(t *testing.T) { title: "assignment", text: "fn f() a.b = c", ignorePosition: true, - nodes: []*Node{{ + nodes: []Node{{ Name: "function-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol-index", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, diff --git a/mmlexp_test.go b/mmlexp_test.go index bddd05d..ce587fa 100644 --- a/mmlexp_test.go +++ b/mmlexp_test.go @@ -18,11 +18,11 @@ func TestMMLExp(t *testing.T) { t.Run("comment", func(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "empty", - node: &Node{Name: "mml"}, + node: Node{Name: "mml"}, }, { title: "single line comment", text: "// foo bar baz", - nodes: []*Node{{ + nodes: []Node{{ Name: "line-comment-content", From: 2, To: 14, @@ -30,7 +30,7 @@ func TestMMLExp(t *testing.T) { }, { title: "multiple line comments", text: "// foo bar\n// baz qux", - nodes: []*Node{{ + nodes: []Node{{ Name: "line-comment-content", From: 2, To: 10, @@ -42,7 +42,7 @@ func TestMMLExp(t *testing.T) { }, { title: "block comment", text: "/* foo bar baz */", - nodes: []*Node{{ + nodes: []Node{{ Name: "block-comment-content", From: 2, To: 15, @@ -50,7 +50,7 @@ func TestMMLExp(t *testing.T) { }, { title: "block comments", text: "/* foo bar */\n/* baz qux */", - nodes: []*Node{{ + nodes: []Node{{ Name: "block-comment-content", From: 2, To: 11, @@ -62,7 +62,7 @@ func TestMMLExp(t *testing.T) { }, { title: "mixed comments", text: "// foo\n/* bar */\n// baz", - nodes: []*Node{{ + nodes: []Node{{ Name: "line-comment-content", From: 2, To: 6, @@ -82,14 +82,14 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "int", text: "42", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 2, }}, }, { title: "ints", text: "1; 2; 3", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 1, }, { @@ -104,14 +104,14 @@ func TestMMLExp(t *testing.T) { }, { title: "int, octal", text: "052", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 3, }}, }, { title: "int, hexa", text: "0x2a", - nodes: []*Node{{ + nodes: []Node{{ Name: "int", To: 4, }}, @@ -122,56 +122,56 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "float, 0.", text: "0.", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 2, }}, }, { title: "float, 72.40", text: "72.40", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 5, }}, }, { title: "float, 072.40", text: "072.40", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 6, }}, }, { title: "float, 2.71828", text: "2.71828", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 7, }}, }, { title: "float, 6.67428e-11", text: "6.67428e-11", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 11, }}, }, { title: "float, 1E6", text: "1E6", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 3, }}, }, { title: "float, .25", text: ".25", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 3, }}, }, { title: "float, .12345E+5", text: ".12345E+5", - nodes: []*Node{{ + nodes: []Node{{ Name: "float", To: 9, }}, @@ -179,9 +179,9 @@ func TestMMLExp(t *testing.T) { title: "float on a new line", text: "f()\n.9", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -195,35 +195,35 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "string, empty", text: "\"\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 2, }}, }, { title: "string", text: "\"foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 5, }}, }, { title: "string, with new line", text: "\"foo\nbar\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 9, }}, }, { title: "string, with escaped new line", text: "\"foo\\nbar\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 10, }}, }, { title: "string, with quotes", text: "\"foo \\\"bar\\\" baz\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", To: 17, }}, @@ -234,14 +234,14 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "bool, true", text: "true", - nodes: []*Node{{ + nodes: []Node{{ Name: "true", To: 4, }}, }, { title: "bool, false", text: "false", - nodes: []*Node{{ + nodes: []Node{{ Name: "false", To: 5, }}, @@ -252,17 +252,17 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "symbol", text: "foo", - nodes: []*Node{{ + nodes: []Node{{ Name: "symbol", To: 3, }}, }, { title: "dynamic-symbol", text: "symbol(a)", - nodes: []*Node{{ + nodes: []Node{{ Name: "dynamic-symbol", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -275,17 +275,17 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "empty list", text: "[]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 2, }}, }, { title: "list", text: "[a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 2, @@ -302,10 +302,10 @@ func TestMMLExp(t *testing.T) { }, { title: "list, new lines", text: "[ \n a \n b \n c \n ]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -322,10 +322,10 @@ func TestMMLExp(t *testing.T) { }, { title: "list, complex", text: "[a, b, c..., [d, e], [f, [g]]...]", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", To: 33, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 2, @@ -337,7 +337,7 @@ func TestMMLExp(t *testing.T) { Name: "spread-expression", From: 7, To: 11, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -346,7 +346,7 @@ func TestMMLExp(t *testing.T) { Name: "list", From: 13, To: 19, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 14, To: 15, @@ -359,11 +359,11 @@ func TestMMLExp(t *testing.T) { Name: "spread-expression", From: 21, To: 32, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list", From: 21, To: 29, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 22, To: 23, @@ -371,7 +371,7 @@ func TestMMLExp(t *testing.T) { Name: "list", From: 25, To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 26, To: 27, @@ -387,10 +387,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "mutable list", text: "~[a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "mutable-list", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 3, @@ -411,21 +411,21 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "empty struct", text: "{}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 2, }}, }, { title: "struct", text: "{foo: 1, \"bar\": 2, symbol(baz): 3, [qux]: 4}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 44, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 1, To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 4, @@ -438,7 +438,7 @@ func TestMMLExp(t *testing.T) { Name: "entry", From: 9, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", From: 9, To: 14, @@ -451,11 +451,11 @@ func TestMMLExp(t *testing.T) { Name: "entry", From: 19, To: 33, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "dynamic-symbol", From: 19, To: 30, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 26, To: 29, @@ -469,11 +469,11 @@ func TestMMLExp(t *testing.T) { Name: "entry", From: 35, To: 43, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer-symbol", From: 35, To: 40, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 36, To: 39, @@ -488,14 +488,14 @@ func TestMMLExp(t *testing.T) { }, { title: "struct, complex", text: "{foo: 1, {bar: 2}..., {baz: {}}...}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 35, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 1, To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 1, To: 4, @@ -508,15 +508,15 @@ func TestMMLExp(t *testing.T) { Name: "spread-expression", From: 9, To: 20, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "struct", From: 9, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 10, To: 16, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 10, To: 13, @@ -531,15 +531,15 @@ func TestMMLExp(t *testing.T) { Name: "spread-expression", From: 22, To: 34, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "struct", From: 22, To: 31, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 23, To: 30, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 23, To: 26, @@ -555,18 +555,18 @@ func TestMMLExp(t *testing.T) { }, { title: "struct with indexer key", text: "{[a]: b}", - nodes: []*Node{{ + nodes: []Node{{ Name: "struct", To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 1, To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer-symbol", From: 1, To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 3, @@ -585,14 +585,14 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "mutable struct", text: "~{foo: 1}", - nodes: []*Node{{ + nodes: []Node{{ Name: "mutable-struct", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "entry", From: 2, To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 5, @@ -610,17 +610,17 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "channel", text: "<>", - nodes: []*Node{{ + nodes: []Node{{ Name: "channel", To: 2, }}, }, { title: "buffered channel", text: "<42>", - nodes: []*Node{{ + nodes: []Node{{ Name: "channel", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 1, To: 3, @@ -633,10 +633,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "and expression", text: "and(a, b, c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 12, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 3, }, { @@ -656,10 +656,10 @@ func TestMMLExp(t *testing.T) { }, { title: "or expression", text: "or(a, b, c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 11, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 2, }, { @@ -683,10 +683,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "function", text: "fn () 42", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 6, To: 8, @@ -695,10 +695,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function, noop", text: "fn () {;}", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "block", From: 6, To: 9, @@ -707,10 +707,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function with args", text: "fn (a, b, c) [a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 22, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -726,7 +726,7 @@ func TestMMLExp(t *testing.T) { Name: "list", From: 13, To: 22, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 14, To: 15, @@ -744,10 +744,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function with args in new lines", text: "fn ( \n a \n b \n c ) [a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -763,7 +763,7 @@ func TestMMLExp(t *testing.T) { Name: "list", From: 19, To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 20, To: 21, @@ -781,10 +781,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function with spread arg", text: "fn (a, b, ...c) [a, b, c]", - nodes: []*Node{{ + nodes: []Node{{ Name: "function", To: 25, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -796,7 +796,7 @@ func TestMMLExp(t *testing.T) { Name: "collect-symbol", From: 10, To: 14, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 13, To: 14, @@ -805,7 +805,7 @@ func TestMMLExp(t *testing.T) { Name: "list", From: 16, To: 25, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 17, To: 18, @@ -827,10 +827,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "effect", text: "fn ~ () 42", - nodes: []*Node{{ + nodes: []Node{{ Name: "effect", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 8, To: 10, @@ -843,10 +843,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "indexer", text: "a[42]", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -858,17 +858,17 @@ func TestMMLExp(t *testing.T) { }, { title: "range indexer", text: "a[3:9]", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 6, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "range-from", From: 2, To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 2, To: 3, @@ -877,7 +877,7 @@ func TestMMLExp(t *testing.T) { Name: "range-to", From: 4, To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 4, To: 5, @@ -887,17 +887,17 @@ func TestMMLExp(t *testing.T) { }, { title: "range indexer, lower unbound", text: "a[:9]", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "range-to", From: 3, To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 3, To: 4, @@ -907,17 +907,17 @@ func TestMMLExp(t *testing.T) { }, { title: "range indexer, upper unbound", text: "a[3:]", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "range-from", From: 2, To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", From: 2, To: 3, @@ -927,16 +927,16 @@ func TestMMLExp(t *testing.T) { }, { title: "indexer, chained", text: "a[b][c][d]", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -962,10 +962,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "symbol indexer", text: "a.b", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -977,10 +977,10 @@ func TestMMLExp(t *testing.T) { }, { title: "symbol indexer, with string", text: "a.\"b\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -992,17 +992,17 @@ func TestMMLExp(t *testing.T) { }, { title: "symbol indexer, with dynamic symbol", text: "a.symbol(b)", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 11, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "dynamic-symbol", From: 2, To: 11, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 9, To: 10, @@ -1012,16 +1012,16 @@ func TestMMLExp(t *testing.T) { }, { title: "chained symbol indexer", text: "a.b.c.d", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", To: 5, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1043,13 +1043,13 @@ func TestMMLExp(t *testing.T) { }, { title: "chained symbol indexer on new line", text: "a\n.b\n.c", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1066,13 +1066,13 @@ func TestMMLExp(t *testing.T) { }, { title: "chained symbol indexer on new line after dot", text: "a.\nb.\nc", - nodes: []*Node{{ + nodes: []Node{{ Name: "indexer", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1093,10 +1093,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "function application", text: "f()", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 3, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }}, @@ -1104,10 +1104,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function application, single arg", text: "f(a)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1119,10 +1119,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function application, multiple args", text: "f(a, b, c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1142,10 +1142,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function application, multiple args, new line", text: "f(a\nb\nc\n)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1165,10 +1165,10 @@ func TestMMLExp(t *testing.T) { }, { title: "function application, spread", text: "f(a, b..., c, d...)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 19, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1179,7 +1179,7 @@ func TestMMLExp(t *testing.T) { Name: "spread-expression", From: 5, To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 5, To: 6, @@ -1192,7 +1192,7 @@ func TestMMLExp(t *testing.T) { Name: "spread-expression", From: 14, To: 18, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 14, To: 15, @@ -1202,16 +1202,16 @@ func TestMMLExp(t *testing.T) { }, { title: "chained function application", text: "f(a)(b)(c)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", To: 7, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", To: 4, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -1233,17 +1233,17 @@ func TestMMLExp(t *testing.T) { }, { title: "embedded function application", text: "f(g(h(a)))", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "function-application", From: 2, To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 2, To: 3, @@ -1251,7 +1251,7 @@ func TestMMLExp(t *testing.T) { Name: "function-application", From: 4, To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -1270,10 +1270,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "if", text: "if a { b() }", - nodes: []*Node{{ + nodes: []Node{{ Name: "if", To: 12, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 3, To: 4, @@ -1281,11 +1281,11 @@ func TestMMLExp(t *testing.T) { Name: "block", From: 5, To: 12, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", From: 7, To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1296,10 +1296,10 @@ func TestMMLExp(t *testing.T) { }, { title: "if, else", text: "if a { b } else { c }", - nodes: []*Node{{ + nodes: []Node{{ Name: "if", To: 21, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 3, To: 4, @@ -1307,7 +1307,7 @@ func TestMMLExp(t *testing.T) { Name: "block", From: 5, To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1316,7 +1316,7 @@ func TestMMLExp(t *testing.T) { Name: "block", From: 16, To: 21, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 18, To: 19, @@ -1326,11 +1326,11 @@ func TestMMLExp(t *testing.T) { }, { title: "if, else if, else if, else", text: "if a { b }\nelse if c { d }\nelse if e { f }\nelse { g }", - nodes: []*Node{{ + nodes: []Node{{ Name: "if", From: 0, To: 53, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 3, To: 4, @@ -1338,7 +1338,7 @@ func TestMMLExp(t *testing.T) { Name: "block", From: 5, To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1351,7 +1351,7 @@ func TestMMLExp(t *testing.T) { Name: "block", From: 21, To: 26, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 23, To: 24, @@ -1364,7 +1364,7 @@ func TestMMLExp(t *testing.T) { Name: "block", From: 37, To: 42, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 39, To: 40, @@ -1373,7 +1373,7 @@ func TestMMLExp(t *testing.T) { Name: "block", From: 48, To: 53, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 50, To: 51, @@ -1387,10 +1387,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "switch, empty", text: "switch {default:}", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "default", From: 8, To: 16, @@ -1406,23 +1406,23 @@ func TestMMLExp(t *testing.T) { f() } `, - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "default", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1431,10 +1431,10 @@ func TestMMLExp(t *testing.T) { }, { title: "switch, single case", text: "switch a {case b: c}", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 20, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1442,7 +1442,7 @@ func TestMMLExp(t *testing.T) { Name: "case", From: 10, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 15, To: 16, @@ -1456,10 +1456,10 @@ func TestMMLExp(t *testing.T) { }, { title: "switch", text: "switch a {case b: c; case d: e; default: f}", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 43, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 7, To: 8, @@ -1467,7 +1467,7 @@ func TestMMLExp(t *testing.T) { Name: "case", From: 10, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 15, To: 16, @@ -1480,7 +1480,7 @@ func TestMMLExp(t *testing.T) { Name: "case", From: 21, To: 28, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 26, To: 27, @@ -1502,10 +1502,10 @@ func TestMMLExp(t *testing.T) { }, { title: "switch, all new lines", text: "switch \n a \n { \n case \n b \n : \n c \n case \n d \n : \n e \n default \n : \n f \n }", - nodes: []*Node{{ + nodes: []Node{{ Name: "switch", To: 74, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 9, To: 10, @@ -1513,7 +1513,7 @@ func TestMMLExp(t *testing.T) { Name: "case", From: 17, To: 29, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 24, To: 25, @@ -1526,7 +1526,7 @@ func TestMMLExp(t *testing.T) { Name: "case", From: 36, To: 48, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 43, To: 44, @@ -1552,10 +1552,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "match expression, empty", text: "match a {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "match", To: 10, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 6, To: 7, @@ -1564,10 +1564,10 @@ func TestMMLExp(t *testing.T) { }, { title: "match expression", text: "match a {\ncase [first, ...rest]: first\n}", - nodes: []*Node{{ + nodes: []Node{{ Name: "match", To: 40, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 6, To: 7, @@ -1575,19 +1575,19 @@ func TestMMLExp(t *testing.T) { Name: "match-case", From: 10, To: 32, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-type", From: 15, To: 31, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-destructure-type", From: 16, To: 30, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "destructure-item", From: 16, To: 21, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 16, To: 21, @@ -1596,11 +1596,11 @@ func TestMMLExp(t *testing.T) { Name: "collect-destructure-item", From: 23, To: 30, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "destructure-item", From: 26, To: 30, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 26, To: 30, @@ -1622,19 +1622,19 @@ func TestMMLExp(t *testing.T) { case [2:]: a[2:] default: error("invalid length") }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "match", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "match-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "items-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "items-quantifier", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", }}, }}, @@ -1644,15 +1644,15 @@ func TestMMLExp(t *testing.T) { Name: "list", }, { Name: "match-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "items-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "items-quantifier", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "static-range-from", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", }}, }}, @@ -1661,11 +1661,11 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "range-from", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", }}, }}, @@ -1673,7 +1673,7 @@ func TestMMLExp(t *testing.T) { Name: "default", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", @@ -1687,21 +1687,21 @@ func TestMMLExp(t *testing.T) { case fn () int: a() default: 42 }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "match", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "match-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int-type", }}, }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -1717,21 +1717,21 @@ func TestMMLExp(t *testing.T) { case [fn (int)]: a[0]() default: 42 }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "match", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "match-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "items-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "arg-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int-type", }}, }}, @@ -1740,9 +1740,9 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "indexer", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "int", @@ -1763,19 +1763,19 @@ func TestMMLExp(t *testing.T) { default: error("invalid list") }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "match", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "match-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-match", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-destructure-match", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "destructure-match-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -1786,31 +1786,31 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "destructure-match-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "function-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "arg-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-destructure-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "destructure-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "destructure-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int-type", }}, }, { Name: "collect-destructure-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "destructure-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1823,9 +1823,9 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "collect-destructure-match-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "destructure-match-item", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -1836,20 +1836,20 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "spread-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1858,7 +1858,7 @@ func TestMMLExp(t *testing.T) { Name: "default", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", @@ -1873,11 +1873,11 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "receive op", text: "<-chan", - nodes: []*Node{{ + nodes: []Node{{ Name: "unary-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "receive-op", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1886,9 +1886,9 @@ func TestMMLExp(t *testing.T) { }, { title: "send op", text: "chan <- a", - nodes: []*Node{{ + nodes: []Node{{ Name: "send", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -1902,7 +1902,7 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "select, empty", text: "select {\n}", - nodes: []*Node{{ + nodes: []Node{{ Name: "select", To: 10, }}, @@ -1913,51 +1913,51 @@ func TestMMLExp(t *testing.T) { case s <- f(): g() default: h() }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "select", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "select-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "receive-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "receive-op", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, }}, }, { Name: "send", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "select-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "send", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "default", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -1970,49 +1970,49 @@ func TestMMLExp(t *testing.T) { case send(s, g()): h() default: i() }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "select", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "select-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "receive-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "receive-call", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "select-case", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "send", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, }}, }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { Name: "default", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -2026,11 +2026,11 @@ func TestMMLExp(t *testing.T) { title: "block", ignorePosition: true, text: "{ f() }", - nodes: []*Node{{ + nodes: []Node{{ Name: "block", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -2042,11 +2042,11 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "go", text: "go f()", - nodes: []*Node{{ + nodes: []Node{{ Name: "go", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -2055,17 +2055,17 @@ func TestMMLExp(t *testing.T) { }, { title: "go, block", text: "go { for { f() } }", - nodes: []*Node{{ + nodes: []Node{{ Name: "go", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "block", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "block", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -2081,11 +2081,11 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "require, dot, equal", text: "require . = \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-inline", }, { Name: "string", @@ -2096,11 +2096,11 @@ func TestMMLExp(t *testing.T) { }, { title: "require, symbol, equal", text: "require bar = \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", @@ -2111,11 +2111,11 @@ func TestMMLExp(t *testing.T) { }, { title: "require, symbol", text: "require bar \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", @@ -2126,11 +2126,11 @@ func TestMMLExp(t *testing.T) { }, { title: "require", text: "require \"mml/foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }}, }}, @@ -2145,39 +2145,39 @@ func TestMMLExp(t *testing.T) { bar "mml/foo" "mml/foo" )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "require", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-inline", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "require-inline", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "string", }}, }, { Name: "require-fact", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "string", }}, }}, @@ -2190,11 +2190,11 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "expression group", text: "(fn (a) a)(a)", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2211,9 +2211,9 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "unary operator", text: "!foo", - nodes: []*Node{{ + nodes: []Node{{ Name: "unary-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "logical-not", }, { Name: "symbol", @@ -2227,9 +2227,9 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "binary 0", text: "a * b", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2241,11 +2241,11 @@ func TestMMLExp(t *testing.T) { }, { title: "binary 1", text: "a * b + c * d", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2256,7 +2256,7 @@ func TestMMLExp(t *testing.T) { Name: "add", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2269,13 +2269,13 @@ func TestMMLExp(t *testing.T) { }, { title: "binary 2", text: "a * b + c * d == e * f", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary2", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2286,7 +2286,7 @@ func TestMMLExp(t *testing.T) { Name: "add", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2298,7 +2298,7 @@ func TestMMLExp(t *testing.T) { Name: "eq", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2311,9 +2311,9 @@ func TestMMLExp(t *testing.T) { }, { title: "binary 1, 1, 1", text: "a + b + c", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "add", @@ -2329,19 +2329,19 @@ func TestMMLExp(t *testing.T) { }, { title: "binary 3, 4, 5", text: "a * b + c * d == e * f && g || h -> f()", - nodes: []*Node{{ + nodes: []Node{{ Name: "binary5", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary4", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary3", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary2", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary1", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2352,7 +2352,7 @@ func TestMMLExp(t *testing.T) { Name: "add", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2364,7 +2364,7 @@ func TestMMLExp(t *testing.T) { Name: "eq", }, { Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mul", @@ -2386,7 +2386,7 @@ func TestMMLExp(t *testing.T) { Name: "chain", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -2399,10 +2399,10 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "ternary expression", text: "a ? b : c", - nodes: []*Node{{ + nodes: []Node{{ Name: "ternary-expression", To: 9, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -2418,17 +2418,17 @@ func TestMMLExp(t *testing.T) { }, { title: "multiple ternary expressions, consequence", text: "a ? b ? c : d : e", - nodes: []*Node{{ + nodes: []Node{{ Name: "ternary-expression", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { Name: "ternary-expression", From: 4, To: 13, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 4, To: 5, @@ -2450,10 +2450,10 @@ func TestMMLExp(t *testing.T) { }, { title: "multiple ternary expressions, alternative", text: "a ? b : c ? d : e", - nodes: []*Node{{ + nodes: []Node{{ Name: "ternary-expression", To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", To: 1, }, { @@ -2464,7 +2464,7 @@ func TestMMLExp(t *testing.T) { Name: "ternary-expression", From: 8, To: 17, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", From: 8, To: 9, @@ -2486,9 +2486,9 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "infinite loop", text: "for {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "block", }}, }}, @@ -2496,11 +2496,11 @@ func TestMMLExp(t *testing.T) { }, { title: "conditional loop", text: "for foo {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "loop-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }, { @@ -2511,17 +2511,17 @@ func TestMMLExp(t *testing.T) { }, { title: "in list loop", text: "for i in [1, 2, 3] {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "loop-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "in-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", }, { Name: "int", @@ -2538,19 +2538,19 @@ func TestMMLExp(t *testing.T) { }, { title: "in range loop", text: "for i in -3:42 {}", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "loop-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "in-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "range-from", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "unary-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "minus", }, { Name: "int", @@ -2558,7 +2558,7 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "range-to", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int", }}, }}, @@ -2575,13 +2575,13 @@ func TestMMLExp(t *testing.T) { break } }`, - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "loop-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "in-expression", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2589,13 +2589,13 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "block", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "if", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary2", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "binary0", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "mod", @@ -2609,7 +2609,7 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "block", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "break", }}, }}, @@ -2624,11 +2624,11 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "assign, eq", text: "a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "assign-equal", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2639,11 +2639,11 @@ func TestMMLExp(t *testing.T) { }, { title: "assign, set, eq", text: "set a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "assign-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2654,11 +2654,11 @@ func TestMMLExp(t *testing.T) { }, { title: "assign, set", text: "set a b", - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "assign-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2672,18 +2672,18 @@ func TestMMLExp(t *testing.T) { a = b c d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "assignment", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "assign-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "assign-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2698,11 +2698,11 @@ func TestMMLExp(t *testing.T) { runTestsSyntax(t, s, []testItem{{ title: "define, eq", text: "let a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2713,11 +2713,11 @@ func TestMMLExp(t *testing.T) { }, { title: "define", text: "let a b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2728,11 +2728,11 @@ func TestMMLExp(t *testing.T) { }, { title: "define mutable, eq", text: "let ~ a = b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2743,11 +2743,11 @@ func TestMMLExp(t *testing.T) { }, { title: "define mutable", text: "let ~ a b", - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2763,32 +2763,32 @@ func TestMMLExp(t *testing.T) { ~ e f ~ g h )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "value-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "mutable-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2802,18 +2802,18 @@ func TestMMLExp(t *testing.T) { a = b c d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "mutable-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "value-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2824,11 +2824,11 @@ func TestMMLExp(t *testing.T) { }, { title: "define function", text: "fn a() b", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2839,11 +2839,11 @@ func TestMMLExp(t *testing.T) { }, { title: "define effect", text: "fn ~ a() b", - nodes: []*Node{{ + nodes: []Node{{ Name: "function-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "effect-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2857,18 +2857,18 @@ func TestMMLExp(t *testing.T) { a() b ~ c() d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "function-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "effect-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2882,18 +2882,18 @@ func TestMMLExp(t *testing.T) { a() b c() d )`, - nodes: []*Node{{ + nodes: []Node{{ Name: "effect-definition-group", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }}, }, { Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2911,15 +2911,15 @@ func TestMMLExp(t *testing.T) { type a fn ([]) int fn a(l) len(l) `, - nodes: []*Node{{ + nodes: []Node{{ Name: "type-constraint", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "function-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "arg-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list-type", }}, }, { @@ -2928,15 +2928,15 @@ func TestMMLExp(t *testing.T) { }}, }, { Name: "function-definition", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "function-capture", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", }, { Name: "function-application", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -2948,15 +2948,15 @@ func TestMMLExp(t *testing.T) { }, { title: "type alias", text: "type alias a int|(fn () int|string)|string", - nodes: []*Node{{ + nodes: []Node{{ Name: "type-alias", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "int-type", }, { Name: "function-type", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "int-type", }, { Name: "string-type", @@ -2969,9 +2969,9 @@ func TestMMLExp(t *testing.T) { }, { title: "statement group", text: "(for {})", - nodes: []*Node{{ + nodes: []Node{{ Name: "loop", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "block", }}, }}, diff --git a/node.go b/node.go index 0508161..62cde30 100644 --- a/node.go +++ b/node.go @@ -2,8 +2,8 @@ package treerack import "code.squareroundforest.org/arpio/treerack/internal/self" -func mapNodes(m func(n *Node) *Node, n []*Node) []*Node { - var nn []*Node +func mapNodes(m func(n Node) Node, n []Node) []Node { + var nn []Node for i := range n { nn = append(nn, m(n[i])) } @@ -11,8 +11,8 @@ func mapNodes(m func(n *Node) *Node, n []*Node) []*Node { return nn } -func filterNodes(f func(n *Node) bool, n []*Node) []*Node { - var nn []*Node +func filterNodes(f func(n Node) bool, n []Node) []Node { + var nn []Node for i := range n { if f(n[i]) { nn = append(nn, n[i]) @@ -22,7 +22,7 @@ func filterNodes(f func(n *Node) bool, n []*Node) []*Node { return nn } -func mapSelfNode(n *self.Node) *Node { +func mapSelfNode(n self.Node) Node { nn := Node{ Name: n.Name, From: n.From, @@ -34,5 +34,5 @@ func mapSelfNode(n *self.Node) *Node { nn.Nodes = append(nn.Nodes, mapSelfNode(n.Nodes[i])) } - return &nn + return nn } diff --git a/nodehead.go b/nodehead.go index d90d190..a46b3b4 100644 --- a/nodehead.go +++ b/nodehead.go @@ -10,7 +10,7 @@ type Node struct { Name string // Nodes contains the child nodes representing the substructures of this node. - Nodes []*Node + Nodes []Node // From is the inclusive character offset of the starting position in the input stream. From int @@ -24,17 +24,17 @@ type Node struct { // Tokens returns the raw slice of runes from the input stream represented by this node. // // Note: This returns a reference to the underlying buffer, not a copy. It should not be modified. -func (n *Node) Tokens() []rune { +func (n Node) Tokens() []rune { return n.tokens } // String returns the string representation of the node, including its name, position range (From/To), and the // captured text content. -func (n *Node) String() string { +func (n Node) String() string { return fmt.Sprintf("%s:%d:%d:%s", n.Name, n.From, n.To, n.Text()) } // Text returns the actual string segment from the input stream represented by this node. -func (n *Node) Text() string { +func (n Node) Text() string { return string(n.Tokens()[n.From:n.To]) } diff --git a/parse_test.go b/parse_test.go index 81b3080..020a6f9 100644 --- a/parse_test.go +++ b/parse_test.go @@ -13,11 +13,11 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, right, left, commit", text: "aaa", - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }}, }}, @@ -32,11 +32,11 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, right, right, commit", text: "aaa", - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }}, }}, @@ -51,11 +51,11 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, left, right, commit", text: "aaa", - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }}, }}, @@ -70,11 +70,11 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, left, left, commit", text: "aaa", - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }}, }}, @@ -89,7 +89,7 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, right, left, alias", text: "aaa", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -102,7 +102,7 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, right, right, alias", text: "aaa", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -115,7 +115,7 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, left, right, alias", text: "aaa", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -128,7 +128,7 @@ func TestRecursion(t *testing.T) { []testItem{{ title: "recursion in choice, left, left, alias", text: "aaa", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -142,17 +142,17 @@ func TestRecursion(t *testing.T) { title: "recursive sequence in choice", text: "aaaa", ignorePosition: true, - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }, { Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }, { Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }, { Name: "A", @@ -204,14 +204,14 @@ func TestSequence(t *testing.T) { []testItem{{ title: "sequence with optional items", text: "abb", - node: &Node{ + node: Node{ Name: "AB", To: 3, }, }, { title: "sequence with optional items, none", text: "bb", - node: &Node{ + node: Node{ Name: "AB", To: 2, }, @@ -224,9 +224,9 @@ func TestSequence(t *testing.T) { []testItem{{ title: "recursive sequence in choice with redundant quantifier", text: "aaa", - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "A", }, { Name: "A", @@ -244,7 +244,7 @@ func TestSequence(t *testing.T) { []testItem{{ title: "sequence with redundant quantifier", text: "aaa", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -258,9 +258,9 @@ func TestSequence(t *testing.T) { title: "single or zero-or-more optional in choice", text: "aaa", ignorePosition: true, - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "a", }, { Name: "a", @@ -282,21 +282,21 @@ func TestSequence(t *testing.T) { title: "just min", text: "aaa", ignorePosition: true, - node: &Node{ + node: Node{ Name: "a", }, }, { title: "less than max", text: "aaaa", ignorePosition: true, - node: &Node{ + node: Node{ Name: "a", }, }, { title: "just max", text: "aaaaa", ignorePosition: true, - node: &Node{ + node: Node{ Name: "a", }, }, { @@ -314,7 +314,7 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero, considered as one", text: "aba", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -335,7 +335,7 @@ func TestQuantifiers(t *testing.T) { }, { title: "one", text: "aba", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -356,7 +356,7 @@ func TestQuantifiers(t *testing.T) { }, { title: "three", text: "abbba", - node: &Node{ + node: Node{ Name: "A", To: 5, }, @@ -373,14 +373,14 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero or one explicit, missing", text: "aa", - node: &Node{ + node: Node{ Name: "A", To: 2, }, }, { title: "zero or one explicit", text: "aba", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -397,14 +397,14 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero or one explicit, omit zero, missing", text: "aa", - node: &Node{ + node: Node{ Name: "A", To: 2, }, }, { title: "zero or one explicit, omit zero", text: "aba", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -421,14 +421,14 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero or one explicit, shortcut, missing", text: "aa", - node: &Node{ + node: Node{ Name: "A", To: 2, }, }, { title: "zero or one explicit, shortcut", text: "aba", - node: &Node{ + node: Node{ Name: "A", To: 3, }, @@ -445,21 +445,21 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero or three, missing", text: "aa", - node: &Node{ + node: Node{ Name: "A", To: 2, }, }, { title: "zero or three", text: "abba", - node: &Node{ + node: Node{ Name: "A", To: 4, }, }, { title: "zero or three", text: "abbba", - node: &Node{ + node: Node{ Name: "A", To: 5, }, @@ -476,21 +476,21 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero or three, omit zero, missing", text: "aa", - node: &Node{ + node: Node{ Name: "A", To: 2, }, }, { title: "zero or three, omit zero", text: "abba", - node: &Node{ + node: Node{ Name: "A", To: 4, }, }, { title: "zero or three, omit zero", text: "abbba", - node: &Node{ + node: Node{ Name: "A", To: 5, }, @@ -511,14 +511,14 @@ func TestQuantifiers(t *testing.T) { }, { title: "one or three", text: "abba", - node: &Node{ + node: Node{ Name: "A", To: 4, }, }, { title: "one or three", text: "abbba", - node: &Node{ + node: Node{ Name: "A", To: 5, }, @@ -539,14 +539,14 @@ func TestQuantifiers(t *testing.T) { }, { title: "three or five", text: "abbbba", - node: &Node{ + node: Node{ Name: "A", To: 6, }, }, { title: "three or five", text: "abbbbba", - node: &Node{ + node: Node{ Name: "A", To: 7, }, @@ -563,14 +563,14 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero or more, explicit, missing", text: "aa", - node: &Node{ + node: Node{ Name: "A", To: 2, }, }, { title: "zero or more, explicit", text: "abba", - node: &Node{ + node: Node{ Name: "A", To: 4, }, @@ -583,14 +583,14 @@ func TestQuantifiers(t *testing.T) { []testItem{{ title: "zero or more, shortcut, missing", text: "aa", - node: &Node{ + node: Node{ Name: "A", To: 2, }, }, { title: "zero or more, shortcut", text: "abba", - node: &Node{ + node: Node{ Name: "A", To: 4, }, @@ -607,7 +607,7 @@ func TestQuantifiers(t *testing.T) { }, { title: "one or more, explicit", text: "abba", - node: &Node{ + node: Node{ Name: "A", To: 4, }, @@ -624,7 +624,7 @@ func TestQuantifiers(t *testing.T) { }, { title: "one or more, shortcut", text: "abba", - node: &Node{ + node: Node{ Name: "A", To: 4, }, @@ -641,7 +641,7 @@ func TestQuantifiers(t *testing.T) { }, { title: "three or more, explicit", text: "abbbba", - node: &Node{ + node: Node{ Name: "A", To: 6, }, @@ -664,6 +664,7 @@ func TestEmpty(t *testing.T) { `A = "1"?`, []testItem{{ title: "empty primitive, succeed", + node: Node{Name: "A"}, }}, ) @@ -672,9 +673,9 @@ func TestEmpty(t *testing.T) { `a = "1"?; A = a a`, []testItem{{ title: "empty document with quantifiers in the item", - node: &Node{ + node: Node{ Name: "A", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "a", }, { Name: "a", @@ -688,7 +689,7 @@ func TestEmpty(t *testing.T) { `a = "1"; A = a? a?`, []testItem{{ title: "empty document with quantifiers in the reference", - node: &Node{ + node: Node{ Name: "A", }, }}, @@ -701,9 +702,9 @@ func TestEmpty(t *testing.T) { title: "no a", text: "b", ignorePosition: true, - node: &Node{ + node: Node{ Name: "a''", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "a", }}, }, @@ -719,7 +720,7 @@ func TestCharAsRoot(t *testing.T) { title: "char as root", text: "a", ignorePosition: true, - node: &Node{ + node: Node{ Name: "A", }, }}, @@ -766,7 +767,7 @@ func TestChoiceSequencePriority(t *testing.T) { title: "bc", text: "bc", ignorePosition: true, - node: &Node{Name: "A"}, + node: Node{Name: "A"}, }}, ) } diff --git a/run_test.go b/run_test.go index 0e1d798..e81fbed 100644 --- a/run_test.go +++ b/run_test.go @@ -10,8 +10,8 @@ type testItem struct { title string text string fail bool - node *Node - nodes []*Node + node Node + nodes []Node ignorePosition bool } @@ -43,10 +43,10 @@ func runTestsGetSyntax(t *testing.T, getSyntax func(t *testing.T) *Syntax, tests return } - if test.node != nil { - checkNode(t, test.ignorePosition, n, test.node) - } else { + if len(test.nodes) > 0 { checkNodes(t, test.ignorePosition, n.Nodes, test.nodes) + } else { + checkNode(t, test.ignorePosition, n, test.node) } }) } diff --git a/scheme_test.go b/scheme_test.go index 4884e09..7430eb2 100644 --- a/scheme_test.go +++ b/scheme_test.go @@ -5,6 +5,7 @@ import "testing" func TestScheme(t *testing.T) { runTestsFile(t, "doc/example/scheme.treerack", []testItem{{ title: "empty", + node: Node{Name: "scheme"}, }, { title: "a function", text: ` @@ -13,13 +14,13 @@ func TestScheme(t *testing.T) { [baz (- a b c)]) (* bar baz))) `, - nodes: []*Node{{ + nodes: []Node{{ Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -30,17 +31,17 @@ func TestScheme(t *testing.T) { }}, }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -52,11 +53,11 @@ func TestScheme(t *testing.T) { }}, }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -69,7 +70,7 @@ func TestScheme(t *testing.T) { }}, }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", diff --git a/sequence.go b/sequence.go index 190be11..497623a 100644 --- a/sequence.go +++ b/sequence.go @@ -131,7 +131,7 @@ func (p *sequenceParser) parse(c *context) { func (b *sequenceBuilder) nodeName() string { return b.name } func (b *sequenceBuilder) nodeID() int { return b.id } -func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { +func (b *sequenceBuilder) build(c *context) ([]Node, bool) { to, ok := c.results.longestMatch(c.offset, b.id) if !ok { return nil, false @@ -146,7 +146,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { return nil, true } - return []*Node{{ + return []Node{{ Name: b.name, From: from, To: to, @@ -172,7 +172,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { var ( itemIndex int currentCount int - nodes []*Node + nodes []Node ) for itemIndex < len(b.items) { @@ -217,7 +217,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { return nodes, true } - return []*Node{{ + return []Node{{ Name: b.name, From: from, To: to, diff --git a/sexpr_test.go b/sexpr_test.go index d3b45b9..5d479a0 100644 --- a/sexpr_test.go +++ b/sexpr_test.go @@ -6,37 +6,37 @@ func TestSExpr(t *testing.T) { runTestsFile(t, "doc/example/sexpr.treerack", []testItem{{ title: "number", text: "42", - nodes: []*Node{{ + nodes: []Node{{ Name: "number", }}, ignorePosition: true, }, { title: "string", text: "\"foo\"", - nodes: []*Node{{ + nodes: []Node{{ Name: "string", }}, ignorePosition: true, }, { title: "symbol", text: "foo", - nodes: []*Node{{ + nodes: []Node{{ Name: "symbol", }}, ignorePosition: true, }, { title: "nil", text: "()", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", }}, ignorePosition: true, }, { title: "list", text: "(foo bar baz)", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -48,17 +48,17 @@ func TestSExpr(t *testing.T) { }, { title: "embedded list", text: "(foo (bar (baz)) qux)", - nodes: []*Node{{ + nodes: []Node{{ Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }}, }}, @@ -72,9 +72,9 @@ func TestSExpr(t *testing.T) { text: `; some comment (some expression)`, ignorePosition: true, - nodes: []*Node{{ + nodes: []Node{{ Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -85,9 +85,9 @@ func TestSExpr(t *testing.T) { text: `; (some expression)`, ignorePosition: true, - nodes: []*Node{{ + nodes: []Node{{ Name: "list", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", diff --git a/syntax.go b/syntax.go index b0372f8..2dd46fc 100644 --- a/syntax.go +++ b/syntax.go @@ -381,7 +381,7 @@ func (s *Syntax) ReadSyntax(r io.Reader) error { } n := mapSelfNode(sn) - s.ast = n + s.ast = &n return define(s, n) } @@ -498,9 +498,9 @@ func (s *Syntax) Generate(o GeneratorOptions, w io.Writer) error { fprintln() if o.Export { - fprint(`func Parse(r io.Reader) (*Node, error) {`) + fprint(`func Parse(r io.Reader) (Node, error) {`) } else { - fprint(`func parse(r io.Reader) (*node, error) {`) + fprint(`func parse(r io.Reader) (node, error) {`) } fprintln() @@ -541,9 +541,9 @@ func (s *Syntax) Generate(o GeneratorOptions, w io.Writer) error { } // Parse reads from the input stream and constructs an AST based on the defined syntax. -func (s *Syntax) Parse(r io.Reader) (*Node, error) { +func (s *Syntax) Parse(r io.Reader) (Node, error) { if err := s.Init(); err != nil { - return nil, err + return Node{}, err } return parseInput(r, s.root.parser(), s.root.builder(), s.keywordParsers()) @@ -555,5 +555,5 @@ func (s *Syntax) Format(out io.Writer) error { return formatDefinitions(out, s) } - return formatAST(out, s.ast) + return formatAST(out, *s.ast) } diff --git a/syntaxhead.go b/syntaxhead.go index 39bb351..6f43ed6 100644 --- a/syntaxhead.go +++ b/syntaxhead.go @@ -89,7 +89,7 @@ type parser interface { type builder interface { nodeName() string nodeID() int - build(*context) ([]*Node, bool) + build(*context) ([]Node, bool) } // ErrInvalidUnicodeCharacter indicates that the input content contains invalid UTF-8 sequences. @@ -106,11 +106,11 @@ func (pe *ParseError) Error() string { ) } -func parseInput(r io.Reader, p parser, b builder, kw []parser) (*Node, error) { +func parseInput(r io.Reader, p parser, b builder, kw []parser) (Node, error) { c := newContext(bufio.NewReader(r), kw) p.parse(c) if c.readErr != nil { - return nil, c.readErr + return Node{}, c.readErr } if err := c.finalizeParse(p); err != nil { @@ -118,7 +118,7 @@ func parseInput(r io.Reader, p parser, b builder, kw []parser) (*Node, error) { perr.Input = "" } - return nil, err + return Node{}, err } c.offset = 0 diff --git a/whitespace_test.go b/whitespace_test.go index d7afb71..46234a2 100644 --- a/whitespace_test.go +++ b/whitespace_test.go @@ -25,18 +25,18 @@ func TestCSVWhitespace(t *testing.T) { tests := []testItem{{ title: "empty", ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", }, }, { title: "only a cell", text: "abc", ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }}, }}, @@ -45,11 +45,11 @@ func TestCSVWhitespace(t *testing.T) { title: "single line", text: `a, b, c`, ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }, { Name: "cell", @@ -63,11 +63,11 @@ func TestCSVWhitespace(t *testing.T) { text: `a, b, c d, e, f`, ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }, { Name: "cell", @@ -76,7 +76,7 @@ func TestCSVWhitespace(t *testing.T) { }}, }, { Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }, { Name: "cell", @@ -90,11 +90,11 @@ func TestCSVWhitespace(t *testing.T) { text: `a,, b, c, d, ,,,,`, ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }, { Name: "cell", @@ -107,7 +107,7 @@ func TestCSVWhitespace(t *testing.T) { }}, }, { Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }, { Name: "cell", @@ -126,11 +126,11 @@ func TestCSVWhitespace(t *testing.T) { title: "too many commas", text: `a,,`, ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }, { Name: "cell", @@ -143,11 +143,11 @@ func TestCSVWhitespace(t *testing.T) { title: "csv with tabs", text: "a,\tb, c", ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }, { Name: "cell", @@ -159,14 +159,14 @@ func TestCSVWhitespace(t *testing.T) { }, { title: "whitespace between lines", text: " a, b, c \n d, e, f ", - node: &Node{ + node: Node{ Name: "document", To: 19, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", From: 1, To: 8, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", From: 1, To: 2, @@ -183,7 +183,7 @@ func TestCSVWhitespace(t *testing.T) { Name: "line", From: 11, To: 18, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", From: 11, To: 12, @@ -202,19 +202,19 @@ func TestCSVWhitespace(t *testing.T) { title: "just a space", text: " ", ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", }, }, { title: "cell with spaces in it", text: "cell content 1/1, cell content 1/2\ncell content 2/1, cell content 2/2", - node: &Node{ + node: Node{ Name: "document", To: 69, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", To: 34, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", To: 16, }, { @@ -226,7 +226,7 @@ func TestCSVWhitespace(t *testing.T) { Name: "line", From: 35, To: 69, - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", From: 35, To: 51, @@ -241,21 +241,21 @@ func TestCSVWhitespace(t *testing.T) { title: "multiple empty lines", text: "\n\n", ignorePosition: true, - node: &Node{ + node: Node{ Name: "document", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }}, }, { Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }}, }, { Name: "line", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "cell", }}, }}, @@ -296,9 +296,9 @@ func TestWhitespace(t *testing.T) { title: "multiple symbols", text: "a b c", ignorePosition: true, - node: &Node{ + node: Node{ Name: "symbols", - Nodes: []*Node{{ + Nodes: []Node{{ Name: "symbol", }, { Name: "symbol", @@ -322,21 +322,21 @@ func TestWhitespace(t *testing.T) { title: "just min", text: "a a a", ignorePosition: true, - node: &Node{ + node: Node{ Name: "a", }, }, { title: "less than max", text: "a a a a", ignorePosition: true, - node: &Node{ + node: Node{ Name: "a", }, }, { title: "just max", text: "a a a a a", ignorePosition: true, - node: &Node{ + node: Node{ Name: "a", }, }, {