1
0

replace Node pointers with values

This commit is contained in:
Arpad Ryszka 2026-06-01 22:26:27 +02:00
parent f61ea7dac7
commit 76ebeb0948
27 changed files with 1070 additions and 1077 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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 {

View File

@ -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:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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 = "<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}

View File

@ -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",
}},
},

View File

@ -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",
}},
}, {

View File

@ -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",

File diff suppressed because it is too large Load Diff

View File

@ -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",
}},
}},

View File

@ -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",
}},
}},

File diff suppressed because it is too large Load Diff

12
node.go
View File

@ -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
}

View File

@ -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])
}

View File

@ -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"},
}},
)
}

View File

@ -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)
}
})
}

View File

@ -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",

View File

@ -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,

View File

@ -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",

View File

@ -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)
}

View File

@ -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 = "<input>"
}
return nil, err
return Node{}, err
}
c.offset = 0

View File

@ -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",
},
}, {