replace Node pointers with values
This commit is contained in:
parent
f61ea7dac7
commit
76ebeb0948
12
boot_test.go
12
boot_test.go
@ -6,15 +6,15 @@ import (
|
|||||||
"testing"
|
"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 {
|
if _, err := f.Seek(0, 0); err != nil {
|
||||||
return nil, err
|
return Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.Parse(f)
|
return s.Parse(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func syntaxFromTree(n *Node) (*Syntax, error) {
|
func syntaxFromTree(n Node) (*Syntax, error) {
|
||||||
s := &Syntax{}
|
s := &Syntax{}
|
||||||
if err := define(s, n); err != nil {
|
if err := define(s, n); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -27,17 +27,17 @@ func syntaxFromTree(n *Node) (*Syntax, error) {
|
|||||||
return s, nil
|
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)
|
s, err := syntaxFromTree(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return nil
|
return Node{}
|
||||||
}
|
}
|
||||||
|
|
||||||
nn, err := parseWithSyntax(s, f)
|
nn, err := parseWithSyntax(s, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return nil
|
return Node{}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNode(t, false, nn, n)
|
checkNode(t, false, nn, n)
|
||||||
|
|||||||
2
char.go
2
char.go
@ -54,6 +54,6 @@ func (p *charParser) parse(c *context) {
|
|||||||
func (b *charBuilder) nodeName() string { return b.name }
|
func (b *charBuilder) nodeName() string { return b.name }
|
||||||
func (b *charBuilder) nodeID() int { return b.id }
|
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
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package treerack
|
|||||||
|
|
||||||
import "testing"
|
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) {
|
if len(left) != len(right) {
|
||||||
t.Error("length doesn't match", len(left), len(right))
|
t.Error("length doesn't match", len(left), len(right))
|
||||||
t.Log(left)
|
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) {
|
func checkNode(t *testing.T, ignorePosition bool, left, right Node) {
|
||||||
if (left == nil) != (right == nil) {
|
|
||||||
t.Error("nil reference doesn't match", left == nil, right == nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if left == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if left.Name != right.Name {
|
if left.Name != right.Name {
|
||||||
t.Error("name doesn't match", left.Name, right.Name)
|
t.Error("name doesn't match", left.Name, right.Name)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -126,7 +126,7 @@ func (p *choiceParser) parse(c *context) {
|
|||||||
func (b *choiceBuilder) nodeName() string { return b.name }
|
func (b *choiceBuilder) nodeName() string { return b.name }
|
||||||
func (b *choiceBuilder) nodeID() int { return b.id }
|
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)
|
to, ok := c.results.longestMatch(c.offset, b.id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -171,7 +171,7 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
return n, true
|
return n, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return []*Node{{
|
return []Node{{
|
||||||
Name: b.name,
|
Name: b.name,
|
||||||
From: from,
|
From: from,
|
||||||
To: to,
|
To: to,
|
||||||
|
|||||||
@ -35,7 +35,7 @@ type node struct {
|
|||||||
Nodes []node `json:"nodes,omitempty"`
|
Nodes []node `json:"nodes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapNode(n *treerack.Node) node {
|
func mapNode(n treerack.Node) node {
|
||||||
var nn node
|
var nn node
|
||||||
nn.Name = n.Name
|
nn.Name = n.Name
|
||||||
nn.From = n.From
|
nn.From = n.From
|
||||||
|
|||||||
34
define.go
34
define.go
@ -2,15 +2,13 @@ package treerack
|
|||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
func dropComments(n *Node) *Node {
|
func dropComments(n Node) Node {
|
||||||
ncc := *n
|
n.Nodes = filterNodes(func(n Node) bool { return n.Name != "comment" }, n.Nodes)
|
||||||
nc := &ncc
|
n.Nodes = mapNodes(dropComments, n.Nodes)
|
||||||
nc.Nodes = filterNodes(func(n *Node) bool { return n.Name != "comment" }, n.Nodes)
|
return n
|
||||||
nc.Nodes = mapNodes(dropComments, nc.Nodes)
|
|
||||||
return nc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func flagsToCommitType(n []*Node) CommitType {
|
func flagsToCommitType(n []Node) CommitType {
|
||||||
var ct CommitType
|
var ct CommitType
|
||||||
for _, ni := range n {
|
for _, ni := range n {
|
||||||
switch ni.Name {
|
switch ni.Name {
|
||||||
@ -38,7 +36,7 @@ func toRune(c string) rune {
|
|||||||
return []rune(c)[0]
|
return []rune(c)[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeChar(n *Node) rune {
|
func nodeChar(n Node) rune {
|
||||||
s := n.Text()
|
s := n.Text()
|
||||||
if s[0] == '\\' {
|
if s[0] == '\\' {
|
||||||
return unescapeChar(toRune(s[1:]))
|
return unescapeChar(toRune(s[1:]))
|
||||||
@ -47,7 +45,7 @@ func nodeChar(n *Node) rune {
|
|||||||
return toRune(s)
|
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 {
|
switch n.Name {
|
||||||
case "symbol":
|
case "symbol":
|
||||||
return n.Text(), nil
|
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 (
|
var (
|
||||||
not bool
|
not bool
|
||||||
chars []rune
|
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)
|
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
|
var chars []rune
|
||||||
for _, ci := range charNodes {
|
for _, ci := range charNodes {
|
||||||
chars = append(chars, nodeChar(ci))
|
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)
|
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 {
|
switch n.Name {
|
||||||
case "count-quantifier":
|
case "count-quantifier":
|
||||||
min, err = strconv.Atoi(n.Nodes[0].Text())
|
min, err = strconv.Atoi(n.Nodes[0].Text())
|
||||||
@ -125,11 +123,11 @@ func getQuantity(n *Node) (min int, max int, err error) {
|
|||||||
return
|
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()})
|
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
|
nows := ct & NoWhitespace
|
||||||
var items []SequenceItem
|
var items []SequenceItem
|
||||||
for i, ni := range n {
|
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...)
|
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
|
var refs []string
|
||||||
memberCT := ct&NoWhitespace | Alias
|
memberCT := ct&NoWhitespace | Alias
|
||||||
for i, ni := range n {
|
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...)
|
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
|
var err error
|
||||||
switch expression.Name {
|
switch expression.Name {
|
||||||
case "any-char":
|
case "any-char":
|
||||||
@ -193,7 +191,7 @@ func defineExpression(s *Syntax, name string, ct CommitType, expression *Node) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDefinition(s *Syntax, n *Node) error {
|
func addDefinition(s *Syntax, n Node) error {
|
||||||
return defineExpression(
|
return defineExpression(
|
||||||
s,
|
s,
|
||||||
n.Nodes[0].Text(),
|
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)
|
syntaxTree = dropComments(syntaxTree)
|
||||||
for _, n := range syntaxTree.Nodes {
|
for _, n := range syntaxTree.Nodes {
|
||||||
if err := addDefinition(s, n); err != nil {
|
if err := addDefinition(s, n); err != nil {
|
||||||
|
|||||||
30
format.go
30
format.go
@ -22,14 +22,14 @@ const (
|
|||||||
|
|
||||||
type formatItem struct {
|
type formatItem struct {
|
||||||
commentFormat commentFormat
|
commentFormat commentFormat
|
||||||
node *Node
|
node Node
|
||||||
}
|
}
|
||||||
|
|
||||||
type formatGroup struct {
|
type formatGroup struct {
|
||||||
items []formatItem
|
items []formatItem
|
||||||
}
|
}
|
||||||
|
|
||||||
func topLevelCommentFormat(ast *Node, i int, n *Node) commentFormat {
|
func topLevelCommentFormat(ast Node, i int, n Node) commentFormat {
|
||||||
if n.Name != "comment" {
|
if n.Name != "comment" {
|
||||||
return commentFormatNone
|
return commentFormatNone
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ func topLevelCommentFormat(ast *Node, i int, n *Node) commentFormat {
|
|||||||
return headerComment
|
return headerComment
|
||||||
}
|
}
|
||||||
|
|
||||||
func groupASTByComments(ast *Node) []formatGroup {
|
func groupASTByComments(ast Node) []formatGroup {
|
||||||
var (
|
var (
|
||||||
groups []formatGroup
|
groups []formatGroup
|
||||||
currentGroup formatGroup
|
currentGroup formatGroup
|
||||||
@ -174,7 +174,7 @@ func trimComment(text string, withBlockBody bool) string {
|
|||||||
return strings.Join(lines, "\n")
|
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 := n.Text()
|
||||||
text = trimComment(text, withBlockBody)
|
text = trimComment(text, withBlockBody)
|
||||||
_, err := fmt.Fprint(out, text)
|
_, err := fmt.Fprint(out, text)
|
||||||
@ -221,17 +221,17 @@ func formatAnyChar(out io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatCharClass(out io.Writer, n *Node) error {
|
func formatCharClass(out io.Writer, n Node) error {
|
||||||
_, err := fmt.Fprint(out, n.Text())
|
_, err := fmt.Fprint(out, n.Text())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatCharSequence(out io.Writer, n *Node) error {
|
func formatCharSequence(out io.Writer, n Node) error {
|
||||||
_, err := fmt.Fprint(out, n.Text())
|
_, err := fmt.Fprint(out, n.Text())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatSymbol(out io.Writer, n *Node) error {
|
func formatSymbol(out io.Writer, n Node) error {
|
||||||
_, err := fmt.Fprint(out, n.Text())
|
_, err := fmt.Fprint(out, n.Text())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -249,7 +249,7 @@ func decTargetWidth(w, by int) int {
|
|||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatSequenceItemNode(out io.Writer, targetWidth int, n *Node) error {
|
func formatSequenceItemNode(out io.Writer, targetWidth int, n Node) error {
|
||||||
var (
|
var (
|
||||||
min, max int
|
min, max int
|
||||||
err error
|
err error
|
||||||
@ -345,7 +345,7 @@ func formatSequenceItemNode(out io.Writer, targetWidth int, n *Node) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatSequenceItemNodes(out io.Writer, targetWidth int, n []*Node) error {
|
func formatSequenceItemNodes(out io.Writer, targetWidth int, n []Node) error {
|
||||||
sep := " "
|
sep := " "
|
||||||
if targetWidth >= 0 {
|
if targetWidth >= 0 {
|
||||||
sep = "\n "
|
sep = "\n "
|
||||||
@ -374,7 +374,7 @@ func formatSequenceItemNodes(out io.Writer, targetWidth int, n []*Node) error {
|
|||||||
return nil
|
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
|
var hasComments bool
|
||||||
for _, ni := range n {
|
for _, ni := range n {
|
||||||
if ni.Name == "comment" {
|
if ni.Name == "comment" {
|
||||||
@ -403,7 +403,7 @@ func formatSequence(out io.Writer, targetWidth int, n []*Node) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatChoiceOptionNodes(out io.Writer, targetWidth int, n []*Node) error {
|
func formatChoiceOptionNodes(out io.Writer, targetWidth int, n []Node) error {
|
||||||
sep, commentSep := " | ", " "
|
sep, commentSep := " | ", " "
|
||||||
if targetWidth >= 0 {
|
if targetWidth >= 0 {
|
||||||
sep, commentSep = "\n| ", "\n"
|
sep, commentSep = "\n| ", "\n"
|
||||||
@ -438,7 +438,7 @@ func formatChoiceOptionNodes(out io.Writer, targetWidth int, n []*Node) error {
|
|||||||
return nil
|
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
|
var hasComments bool
|
||||||
for _, ni := range n {
|
for _, ni := range n {
|
||||||
if ni.Name == "comment" {
|
if ni.Name == "comment" {
|
||||||
@ -467,7 +467,7 @@ func formatChoice(out io.Writer, targetWidth int, n []*Node) error {
|
|||||||
return err
|
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
|
var err error
|
||||||
switch n.Name {
|
switch n.Name {
|
||||||
case "comment":
|
case "comment":
|
||||||
@ -489,7 +489,7 @@ func formatExpression(out io.Writer, targetWidth int, n *Node) error {
|
|||||||
return err
|
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 (
|
var (
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
foundComment bool
|
foundComment bool
|
||||||
@ -616,7 +616,7 @@ func formatASTGroup(out io.Writer, g formatGroup) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatAST(out io.Writer, ast *Node) error {
|
func formatAST(out io.Writer, ast Node) error {
|
||||||
// drop whitespace comments
|
// drop whitespace comments
|
||||||
// use line comments by default
|
// use line comments by default
|
||||||
// comment types:
|
// comment types:
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -83,7 +83,7 @@ func (b *charBuilder) nodeName() string {
|
|||||||
func (b *charBuilder) nodeID() int {
|
func (b *charBuilder) nodeID() int {
|
||||||
return b.id
|
return b.id
|
||||||
}
|
}
|
||||||
func (b *charBuilder) build(c *context) ([]*Node, bool) {
|
func (b *charBuilder) build(c *context) ([]Node, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ func (b *sequenceBuilder) nodeName() string {
|
|||||||
func (b *sequenceBuilder) nodeID() int {
|
func (b *sequenceBuilder) nodeID() int {
|
||||||
return b.id
|
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)
|
to, ok := c.results.longestMatch(c.offset, b.id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -211,7 +211,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
if b.commit&Alias != 0 {
|
if b.commit&Alias != 0 {
|
||||||
return nil, true
|
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 {
|
} else if parsed {
|
||||||
c.results.dropMatchTo(c.offset, b.id, to)
|
c.results.dropMatchTo(c.offset, b.id, to)
|
||||||
for _, g := range b.generalizations {
|
for _, g := range b.generalizations {
|
||||||
@ -229,7 +229,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
var (
|
var (
|
||||||
itemIndex int
|
itemIndex int
|
||||||
currentCount int
|
currentCount int
|
||||||
nodes []*Node
|
nodes []Node
|
||||||
)
|
)
|
||||||
for itemIndex < len(b.items) {
|
for itemIndex < len(b.items) {
|
||||||
itemFrom := c.offset
|
itemFrom := c.offset
|
||||||
@ -265,7 +265,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
if b.commit&Alias != 0 {
|
if b.commit&Alias != 0 {
|
||||||
return nodes, true
|
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 {
|
type choiceParser struct {
|
||||||
@ -378,7 +378,7 @@ func (b *choiceBuilder) nodeName() string {
|
|||||||
func (b *choiceBuilder) nodeID() int {
|
func (b *choiceBuilder) nodeID() int {
|
||||||
return b.id
|
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)
|
to, ok := c.results.longestMatch(c.offset, b.id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -416,7 +416,7 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
if b.commit&Alias != 0 {
|
if b.commit&Alias != 0 {
|
||||||
return n, true
|
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 }
|
type idSet struct{ ids []uint }
|
||||||
@ -733,19 +733,19 @@ func (c *context) finalizeParse(root parser) error {
|
|||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Name string
|
Name string
|
||||||
Nodes []*Node
|
Nodes []Node
|
||||||
From int
|
From int
|
||||||
To int
|
To int
|
||||||
tokens []rune
|
tokens []rune
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) Tokens() []rune {
|
func (n Node) Tokens() []rune {
|
||||||
return n.tokens
|
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())
|
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])
|
return string(n.Tokens()[n.From:n.To])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +791,7 @@ type parser interface {
|
|||||||
type builder interface {
|
type builder interface {
|
||||||
nodeName() string
|
nodeName() string
|
||||||
nodeID() int
|
nodeID() int
|
||||||
build(*context) ([]*Node, bool)
|
build(*context) ([]Node, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrInvalidUnicodeCharacter = errors.New("invalid unicode character")
|
var ErrInvalidUnicodeCharacter = errors.New("invalid unicode character")
|
||||||
@ -799,17 +799,17 @@ var ErrInvalidUnicodeCharacter = errors.New("invalid unicode character")
|
|||||||
func (pe *ParseError) Error() string {
|
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)
|
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)
|
c := newContext(bufio.NewReader(r), kw)
|
||||||
p.parse(c)
|
p.parse(c)
|
||||||
if c.readErr != nil {
|
if c.readErr != nil {
|
||||||
return nil, c.readErr
|
return Node{}, c.readErr
|
||||||
}
|
}
|
||||||
if err := c.finalizeParse(p); err != nil {
|
if err := c.finalizeParse(p); err != nil {
|
||||||
if perr, ok := err.(*ParseError); ok {
|
if perr, ok := err.(*ParseError); ok {
|
||||||
perr.Input = "<input>"
|
perr.Input = "<input>"
|
||||||
}
|
}
|
||||||
return nil, err
|
return Node{}, err
|
||||||
}
|
}
|
||||||
c.offset = 0
|
c.offset = 0
|
||||||
c.results.resetPending()
|
c.results.resetPending()
|
||||||
@ -819,7 +819,7 @@ func parseInput(r io.Reader, p parser, b builder, kw []parser) (*Node, error) {
|
|||||||
|
|
||||||
// eo head
|
// 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 p172 = sequenceParser{id: 172, commit: 128, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
||||||
var p170 = choiceParser{id: 170, commit: 2}
|
var p170 = choiceParser{id: 170, commit: 2}
|
||||||
|
|||||||
74
json_test.go
74
json_test.go
@ -142,7 +142,7 @@ func parseJSONNumber(t string) (interface{}, error) {
|
|||||||
return n.Float64()
|
return n.Float64()
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeToJSONObject(n *Node) (map[string]interface{}, error) {
|
func nodeToJSONObject(n Node) (map[string]interface{}, error) {
|
||||||
o := make(map[string]interface{})
|
o := make(map[string]interface{})
|
||||||
for _, ni := range n.Nodes {
|
for _, ni := range n.Nodes {
|
||||||
if len(ni.Nodes) != 2 {
|
if len(ni.Nodes) != 2 {
|
||||||
@ -165,7 +165,7 @@ func nodeToJSONObject(n *Node) (map[string]interface{}, error) {
|
|||||||
return o, nil
|
return o, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeToJSONArray(n *Node) ([]interface{}, error) {
|
func nodeToJSONArray(n Node) ([]interface{}, error) {
|
||||||
a := make([]interface{}, 0, len(n.Nodes))
|
a := make([]interface{}, 0, len(n.Nodes))
|
||||||
for _, ni := range n.Nodes {
|
for _, ni := range n.Nodes {
|
||||||
item, err := treeToJSON(ni)
|
item, err := treeToJSON(ni)
|
||||||
@ -179,7 +179,7 @@ func nodeToJSONArray(n *Node) ([]interface{}, error) {
|
|||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func treeToJSON(n *Node) (interface{}, error) {
|
func treeToJSON(n Node) (interface{}, error) {
|
||||||
switch n.Name {
|
switch n.Name {
|
||||||
case "true":
|
case "true":
|
||||||
return true, nil
|
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" {
|
if n.Name != "json" {
|
||||||
return nil, fmt.Errorf("invalid root node name: %s", n.Name)
|
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{{
|
runTestsFile(t, "doc/example/json.treerack", []testItem{{
|
||||||
title: "true",
|
title: "true",
|
||||||
text: "true",
|
text: "true",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "true",
|
Name: "true",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -298,9 +298,9 @@ func TestJSON(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "false",
|
title: "false",
|
||||||
text: "false",
|
text: "false",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "false",
|
Name: "false",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -308,9 +308,9 @@ func TestJSON(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "null",
|
title: "null",
|
||||||
text: "null",
|
text: "null",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "null",
|
Name: "null",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -318,9 +318,9 @@ func TestJSON(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "string",
|
title: "string",
|
||||||
text: `"\"\\n\b\t\uabcd"`,
|
text: `"\"\\n\b\t\uabcd"`,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -328,9 +328,9 @@ func TestJSON(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "number",
|
title: "number",
|
||||||
text: "6.62e-34",
|
text: "6.62e-34",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "number",
|
Name: "number",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -346,55 +346,55 @@ func TestJSON(t *testing.T) {
|
|||||||
"object": {},
|
"object": {},
|
||||||
"array": []
|
"array": []
|
||||||
}`,
|
}`,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "object",
|
Name: "object",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "true",
|
Name: "true",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "false",
|
Name: "false",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "null",
|
Name: "null",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "number",
|
Name: "number",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "object",
|
Name: "object",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "array",
|
Name: "array",
|
||||||
@ -414,11 +414,11 @@ func TestJSON(t *testing.T) {
|
|||||||
"object": {},
|
"object": {},
|
||||||
"array": []
|
"array": []
|
||||||
}, []]`,
|
}, []]`,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "array",
|
Name: "array",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "true",
|
Name: "true",
|
||||||
}, {
|
}, {
|
||||||
Name: "false",
|
Name: "false",
|
||||||
@ -430,51 +430,51 @@ func TestJSON(t *testing.T) {
|
|||||||
Name: "number",
|
Name: "number",
|
||||||
}, {
|
}, {
|
||||||
Name: "object",
|
Name: "object",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "true",
|
Name: "true",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "false",
|
Name: "false",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "null",
|
Name: "null",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "number",
|
Name: "number",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "object",
|
Name: "object",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "entry",
|
Name: "entry",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}, {
|
}, {
|
||||||
Name: "array",
|
Name: "array",
|
||||||
@ -489,9 +489,9 @@ func TestJSON(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "bugfix, 100",
|
title: "bugfix, 100",
|
||||||
text: "100",
|
text: "100",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "number",
|
Name: "number",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
|||||||
108
keyval_test.go
108
keyval_test.go
@ -5,19 +5,21 @@ import "testing"
|
|||||||
func TestKeyVal(t *testing.T) {
|
func TestKeyVal(t *testing.T) {
|
||||||
runTestsFile(t, "doc/example/keyval.treerack", []testItem{{
|
runTestsFile(t, "doc/example/keyval.treerack", []testItem{{
|
||||||
title: "empty",
|
title: "empty",
|
||||||
|
node: Node{Name: "doc"},
|
||||||
}, {
|
}, {
|
||||||
title: "a comment",
|
title: "a comment",
|
||||||
text: "# a comment",
|
text: "# a comment",
|
||||||
|
node: Node{Name: "doc", To: 11},
|
||||||
}, {
|
}, {
|
||||||
title: "a key",
|
title: "a key",
|
||||||
text: "a key",
|
text: "a key",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
To: 5,
|
To: 5,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
To: 5,
|
To: 5,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
To: 5,
|
To: 5,
|
||||||
}},
|
}},
|
||||||
@ -26,15 +28,15 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "a key with a preceeding whitespace",
|
title: "a key with a preceeding whitespace",
|
||||||
text: " a key",
|
text: " a key",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
From: 1,
|
From: 1,
|
||||||
To: 6,
|
To: 6,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
From: 1,
|
From: 1,
|
||||||
To: 6,
|
To: 6,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
From: 1,
|
From: 1,
|
||||||
To: 6,
|
To: 6,
|
||||||
@ -48,15 +50,15 @@ func TestKeyVal(t *testing.T) {
|
|||||||
|
|
||||||
a key
|
a key
|
||||||
`,
|
`,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
From: 20,
|
From: 20,
|
||||||
To: 25,
|
To: 25,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
From: 20,
|
From: 20,
|
||||||
To: 25,
|
To: 25,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
From: 20,
|
From: 20,
|
||||||
To: 25,
|
To: 25,
|
||||||
@ -66,13 +68,13 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "a key value pair",
|
title: "a key value pair",
|
||||||
text: "a key = a value",
|
text: "a key = a value",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
To: 15,
|
To: 15,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
To: 5,
|
To: 5,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
To: 5,
|
To: 5,
|
||||||
}},
|
}},
|
||||||
@ -86,15 +88,15 @@ func TestKeyVal(t *testing.T) {
|
|||||||
title: "key value pairs with a comment at the end of line",
|
title: "key value pairs with a comment at the end of line",
|
||||||
text: "a key = a value # a comment\n" +
|
text: "a key = a value # a comment\n" +
|
||||||
"another key = another value # another comment",
|
"another key = another value # another comment",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 39,
|
To: 39,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 5,
|
To: 5,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 5,
|
To: 5,
|
||||||
@ -108,11 +110,11 @@ func TestKeyVal(t *testing.T) {
|
|||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
From: 40,
|
From: 40,
|
||||||
To: 85,
|
To: 85,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
From: 40,
|
From: 40,
|
||||||
To: 51,
|
To: 51,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
From: 40,
|
From: 40,
|
||||||
To: 51,
|
To: 51,
|
||||||
@ -126,10 +128,10 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "value without a key",
|
title: "value without a key",
|
||||||
text: "= a value",
|
text: "= a value",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
To: 9,
|
To: 9,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
From: 2,
|
From: 2,
|
||||||
To: 9,
|
To: 9,
|
||||||
@ -141,11 +143,11 @@ func TestKeyVal(t *testing.T) {
|
|||||||
# a comment
|
# a comment
|
||||||
a key = a value
|
a key = a value
|
||||||
`,
|
`,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
From: 4,
|
From: 4,
|
||||||
To: 34,
|
To: 34,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
From: 4,
|
From: 4,
|
||||||
To: 15,
|
To: 15,
|
||||||
@ -153,7 +155,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
Name: "key",
|
Name: "key",
|
||||||
From: 19,
|
From: 19,
|
||||||
To: 24,
|
To: 24,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
From: 19,
|
From: 19,
|
||||||
To: 24,
|
To: 24,
|
||||||
@ -167,14 +169,14 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "a key with multiple symbols",
|
title: "a key with multiple symbols",
|
||||||
text: "a key . with.multiple.symbols=a value",
|
text: "a key . with.multiple.symbols=a value",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
To: 37,
|
To: 37,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 29,
|
To: 29,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
From: 0,
|
From: 0,
|
||||||
To: 5,
|
To: 5,
|
||||||
@ -203,11 +205,11 @@ func TestKeyVal(t *testing.T) {
|
|||||||
# a comment
|
# a comment
|
||||||
[a group key.empty]
|
[a group key.empty]
|
||||||
`,
|
`,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "group-key",
|
Name: "group-key",
|
||||||
From: 4,
|
From: 4,
|
||||||
To: 38,
|
To: 38,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
From: 4,
|
From: 4,
|
||||||
To: 15,
|
To: 15,
|
||||||
@ -229,9 +231,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
= two
|
= two
|
||||||
= three
|
= three
|
||||||
`,
|
`,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "group-key",
|
Name: "group-key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -240,17 +242,17 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -258,9 +260,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "a group key with multiple values, in a single line",
|
title: "a group key with multiple values, in a single line",
|
||||||
text: "[foo.bar.baz] = one = two = three",
|
text: "[foo.bar.baz] = one = two = three",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "group-key",
|
Name: "group-key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -269,17 +271,17 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "value",
|
Name: "value",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -301,11 +303,11 @@ func TestKeyVal(t *testing.T) {
|
|||||||
b = 2 # even
|
b = 2 # even
|
||||||
c = 3
|
c = 3
|
||||||
`,
|
`,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
@ -313,9 +315,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -325,9 +327,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -337,9 +339,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
@ -347,7 +349,7 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "group-key",
|
Name: "group-key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "comment",
|
Name: "comment",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -358,9 +360,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
@ -368,9 +370,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
@ -378,9 +380,9 @@ func TestKeyVal(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "key-val",
|
Name: "key-val",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
@ -14,9 +14,9 @@ func TestKeyword(t *testing.T) {
|
|||||||
title: "not keyword",
|
title: "not keyword",
|
||||||
text: "baz",
|
text: "baz",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "doc",
|
Name: "doc",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -24,9 +24,9 @@ func TestKeyword(t *testing.T) {
|
|||||||
title: "keyword",
|
title: "keyword",
|
||||||
text: "foo",
|
text: "foo",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "doc",
|
Name: "doc",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "keyword",
|
Name: "keyword",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -34,9 +34,9 @@ func TestKeyword(t *testing.T) {
|
|||||||
title: "mixed",
|
title: "mixed",
|
||||||
text: "foo bar baz bar foo baz bar",
|
text: "foo bar baz bar foo baz bar",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "doc",
|
Name: "doc",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "keyword",
|
Name: "keyword",
|
||||||
}, {
|
}, {
|
||||||
Name: "keyword",
|
Name: "keyword",
|
||||||
|
|||||||
638
mml_test.go
638
mml_test.go
File diff suppressed because it is too large
Load Diff
@ -16,18 +16,18 @@ func TestMMLExp2(t *testing.T) {
|
|||||||
title: "mixed indexer",
|
title: "mixed indexer",
|
||||||
text: "a.b[c]",
|
text: "a.b[c]",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol-index",
|
Name: "symbol-index",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "expression-index",
|
Name: "expression-index",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -38,18 +38,18 @@ func TestMMLExp2(t *testing.T) {
|
|||||||
title: "mixed indexer inverted",
|
title: "mixed indexer inverted",
|
||||||
text: "a[b].c",
|
text: "a[b].c",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "expression-index",
|
Name: "expression-index",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol-index",
|
Name: "symbol-index",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
|
|||||||
@ -16,21 +16,21 @@ func TestMMLExp3(t *testing.T) {
|
|||||||
title: "assignment",
|
title: "assignment",
|
||||||
text: "fn f() a.b = c",
|
text: "fn f() a.b = c",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "function-definition",
|
Name: "function-definition",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "function-capture",
|
Name: "function-capture",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "assignment",
|
Name: "assignment",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "indexer",
|
Name: "indexer",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol-index",
|
Name: "symbol-index",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
|
|||||||
840
mmlexp_test.go
840
mmlexp_test.go
File diff suppressed because it is too large
Load Diff
12
node.go
12
node.go
@ -2,8 +2,8 @@ package treerack
|
|||||||
|
|
||||||
import "code.squareroundforest.org/arpio/treerack/internal/self"
|
import "code.squareroundforest.org/arpio/treerack/internal/self"
|
||||||
|
|
||||||
func mapNodes(m func(n *Node) *Node, n []*Node) []*Node {
|
func mapNodes(m func(n Node) Node, n []Node) []Node {
|
||||||
var nn []*Node
|
var nn []Node
|
||||||
for i := range n {
|
for i := range n {
|
||||||
nn = append(nn, m(n[i]))
|
nn = append(nn, m(n[i]))
|
||||||
}
|
}
|
||||||
@ -11,8 +11,8 @@ func mapNodes(m func(n *Node) *Node, n []*Node) []*Node {
|
|||||||
return nn
|
return nn
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterNodes(f func(n *Node) bool, n []*Node) []*Node {
|
func filterNodes(f func(n Node) bool, n []Node) []Node {
|
||||||
var nn []*Node
|
var nn []Node
|
||||||
for i := range n {
|
for i := range n {
|
||||||
if f(n[i]) {
|
if f(n[i]) {
|
||||||
nn = append(nn, n[i])
|
nn = append(nn, n[i])
|
||||||
@ -22,7 +22,7 @@ func filterNodes(f func(n *Node) bool, n []*Node) []*Node {
|
|||||||
return nn
|
return nn
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapSelfNode(n *self.Node) *Node {
|
func mapSelfNode(n self.Node) Node {
|
||||||
nn := Node{
|
nn := Node{
|
||||||
Name: n.Name,
|
Name: n.Name,
|
||||||
From: n.From,
|
From: n.From,
|
||||||
@ -34,5 +34,5 @@ func mapSelfNode(n *self.Node) *Node {
|
|||||||
nn.Nodes = append(nn.Nodes, mapSelfNode(n.Nodes[i]))
|
nn.Nodes = append(nn.Nodes, mapSelfNode(n.Nodes[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &nn
|
return nn
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ type Node struct {
|
|||||||
Name string
|
Name string
|
||||||
|
|
||||||
// Nodes contains the child nodes representing the substructures of this node.
|
// 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 is the inclusive character offset of the starting position in the input stream.
|
||||||
From int
|
From int
|
||||||
@ -24,17 +24,17 @@ type Node struct {
|
|||||||
// Tokens returns the raw slice of runes from the input stream represented by this node.
|
// 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.
|
// 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
|
return n.tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string representation of the node, including its name, position range (From/To), and the
|
// String returns the string representation of the node, including its name, position range (From/To), and the
|
||||||
// captured text content.
|
// 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())
|
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.
|
// 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])
|
return string(n.Tokens()[n.From:n.To])
|
||||||
}
|
}
|
||||||
|
|||||||
127
parse_test.go
127
parse_test.go
@ -13,11 +13,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, right, left, commit",
|
title: "recursion in choice, right, left, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -32,11 +32,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, right, right, commit",
|
title: "recursion in choice, right, right, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -51,11 +51,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, left, right, commit",
|
title: "recursion in choice, left, right, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -70,11 +70,11 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, left, left, commit",
|
title: "recursion in choice, left, left, commit",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -89,7 +89,7 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, right, left, alias",
|
title: "recursion in choice, right, left, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -102,7 +102,7 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, right, right, alias",
|
title: "recursion in choice, right, right, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -115,7 +115,7 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, left, right, alias",
|
title: "recursion in choice, left, right, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -128,7 +128,7 @@ func TestRecursion(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursion in choice, left, left, alias",
|
title: "recursion in choice, left, left, alias",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -142,17 +142,17 @@ func TestRecursion(t *testing.T) {
|
|||||||
title: "recursive sequence in choice",
|
title: "recursive sequence in choice",
|
||||||
text: "aaaa",
|
text: "aaaa",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}, {
|
}, {
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}, {
|
}, {
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}, {
|
}, {
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -204,14 +204,14 @@ func TestSequence(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "sequence with optional items",
|
title: "sequence with optional items",
|
||||||
text: "abb",
|
text: "abb",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "AB",
|
Name: "AB",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "sequence with optional items, none",
|
title: "sequence with optional items, none",
|
||||||
text: "bb",
|
text: "bb",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "AB",
|
Name: "AB",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
@ -224,9 +224,9 @@ func TestSequence(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "recursive sequence in choice with redundant quantifier",
|
title: "recursive sequence in choice with redundant quantifier",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
}, {
|
}, {
|
||||||
Name: "A",
|
Name: "A",
|
||||||
@ -244,7 +244,7 @@ func TestSequence(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "sequence with redundant quantifier",
|
title: "sequence with redundant quantifier",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -258,9 +258,9 @@ func TestSequence(t *testing.T) {
|
|||||||
title: "single or zero-or-more optional in choice",
|
title: "single or zero-or-more optional in choice",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
}, {
|
}, {
|
||||||
Name: "a",
|
Name: "a",
|
||||||
@ -282,21 +282,21 @@ func TestSequence(t *testing.T) {
|
|||||||
title: "just min",
|
title: "just min",
|
||||||
text: "aaa",
|
text: "aaa",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "less than max",
|
title: "less than max",
|
||||||
text: "aaaa",
|
text: "aaaa",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "just max",
|
title: "just max",
|
||||||
text: "aaaaa",
|
text: "aaaaa",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -314,7 +314,7 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero, considered as one",
|
title: "zero, considered as one",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -335,7 +335,7 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "one",
|
title: "one",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -356,7 +356,7 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "three",
|
title: "three",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
@ -373,14 +373,14 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero or one explicit, missing",
|
title: "zero or one explicit, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or one explicit",
|
title: "zero or one explicit",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -397,14 +397,14 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero or one explicit, omit zero, missing",
|
title: "zero or one explicit, omit zero, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or one explicit, omit zero",
|
title: "zero or one explicit, omit zero",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -421,14 +421,14 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero or one explicit, shortcut, missing",
|
title: "zero or one explicit, shortcut, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or one explicit, shortcut",
|
title: "zero or one explicit, shortcut",
|
||||||
text: "aba",
|
text: "aba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 3,
|
To: 3,
|
||||||
},
|
},
|
||||||
@ -445,21 +445,21 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero or three, missing",
|
title: "zero or three, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or three",
|
title: "zero or three",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or three",
|
title: "zero or three",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
@ -476,21 +476,21 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero or three, omit zero, missing",
|
title: "zero or three, omit zero, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or three, omit zero",
|
title: "zero or three, omit zero",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or three, omit zero",
|
title: "zero or three, omit zero",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
@ -511,14 +511,14 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "one or three",
|
title: "one or three",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "one or three",
|
title: "one or three",
|
||||||
text: "abbba",
|
text: "abbba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 5,
|
To: 5,
|
||||||
},
|
},
|
||||||
@ -539,14 +539,14 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "three or five",
|
title: "three or five",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 6,
|
To: 6,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "three or five",
|
title: "three or five",
|
||||||
text: "abbbbba",
|
text: "abbbbba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 7,
|
To: 7,
|
||||||
},
|
},
|
||||||
@ -563,14 +563,14 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero or more, explicit, missing",
|
title: "zero or more, explicit, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or more, explicit",
|
title: "zero or more, explicit",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
@ -583,14 +583,14 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "zero or more, shortcut, missing",
|
title: "zero or more, shortcut, missing",
|
||||||
text: "aa",
|
text: "aa",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 2,
|
To: 2,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "zero or more, shortcut",
|
title: "zero or more, shortcut",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
@ -607,7 +607,7 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "one or more, explicit",
|
title: "one or more, explicit",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
@ -624,7 +624,7 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "one or more, shortcut",
|
title: "one or more, shortcut",
|
||||||
text: "abba",
|
text: "abba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 4,
|
To: 4,
|
||||||
},
|
},
|
||||||
@ -641,7 +641,7 @@ func TestQuantifiers(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "three or more, explicit",
|
title: "three or more, explicit",
|
||||||
text: "abbbba",
|
text: "abbbba",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
To: 6,
|
To: 6,
|
||||||
},
|
},
|
||||||
@ -664,6 +664,7 @@ func TestEmpty(t *testing.T) {
|
|||||||
`A = "1"?`,
|
`A = "1"?`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "empty primitive, succeed",
|
title: "empty primitive, succeed",
|
||||||
|
node: Node{Name: "A"},
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -672,9 +673,9 @@ func TestEmpty(t *testing.T) {
|
|||||||
`a = "1"?; A = a a`,
|
`a = "1"?; A = a a`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "empty document with quantifiers in the item",
|
title: "empty document with quantifiers in the item",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
}, {
|
}, {
|
||||||
Name: "a",
|
Name: "a",
|
||||||
@ -688,7 +689,7 @@ func TestEmpty(t *testing.T) {
|
|||||||
`a = "1"; A = a? a?`,
|
`a = "1"; A = a? a?`,
|
||||||
[]testItem{{
|
[]testItem{{
|
||||||
title: "empty document with quantifiers in the reference",
|
title: "empty document with quantifiers in the reference",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -701,9 +702,9 @@ func TestEmpty(t *testing.T) {
|
|||||||
title: "no a",
|
title: "no a",
|
||||||
text: "b",
|
text: "b",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "a''",
|
Name: "a''",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -719,7 +720,7 @@ func TestCharAsRoot(t *testing.T) {
|
|||||||
title: "char as root",
|
title: "char as root",
|
||||||
text: "a",
|
text: "a",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "A",
|
Name: "A",
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -766,7 +767,7 @@ func TestChoiceSequencePriority(t *testing.T) {
|
|||||||
title: "bc",
|
title: "bc",
|
||||||
text: "bc",
|
text: "bc",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{Name: "A"},
|
node: Node{Name: "A"},
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
10
run_test.go
10
run_test.go
@ -10,8 +10,8 @@ type testItem struct {
|
|||||||
title string
|
title string
|
||||||
text string
|
text string
|
||||||
fail bool
|
fail bool
|
||||||
node *Node
|
node Node
|
||||||
nodes []*Node
|
nodes []Node
|
||||||
ignorePosition bool
|
ignorePosition bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,10 +43,10 @@ func runTestsGetSyntax(t *testing.T, getSyntax func(t *testing.T) *Syntax, tests
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.node != nil {
|
if len(test.nodes) > 0 {
|
||||||
checkNode(t, test.ignorePosition, n, test.node)
|
|
||||||
} else {
|
|
||||||
checkNodes(t, test.ignorePosition, n.Nodes, test.nodes)
|
checkNodes(t, test.ignorePosition, n.Nodes, test.nodes)
|
||||||
|
} else {
|
||||||
|
checkNode(t, test.ignorePosition, n, test.node)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import "testing"
|
|||||||
func TestScheme(t *testing.T) {
|
func TestScheme(t *testing.T) {
|
||||||
runTestsFile(t, "doc/example/scheme.treerack", []testItem{{
|
runTestsFile(t, "doc/example/scheme.treerack", []testItem{{
|
||||||
title: "empty",
|
title: "empty",
|
||||||
|
node: Node{Name: "scheme"},
|
||||||
}, {
|
}, {
|
||||||
title: "a function",
|
title: "a function",
|
||||||
text: `
|
text: `
|
||||||
@ -13,13 +14,13 @@ func TestScheme(t *testing.T) {
|
|||||||
[baz (- a b c)])
|
[baz (- a b c)])
|
||||||
(* bar baz)))
|
(* bar baz)))
|
||||||
`,
|
`,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -30,17 +31,17 @@ func TestScheme(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -52,11 +53,11 @@ func TestScheme(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -69,7 +70,7 @@ func TestScheme(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
|
|||||||
@ -131,7 +131,7 @@ func (p *sequenceParser) parse(c *context) {
|
|||||||
func (b *sequenceBuilder) nodeName() string { return b.name }
|
func (b *sequenceBuilder) nodeName() string { return b.name }
|
||||||
func (b *sequenceBuilder) nodeID() int { return b.id }
|
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)
|
to, ok := c.results.longestMatch(c.offset, b.id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -146,7 +146,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return []*Node{{
|
return []Node{{
|
||||||
Name: b.name,
|
Name: b.name,
|
||||||
From: from,
|
From: from,
|
||||||
To: to,
|
To: to,
|
||||||
@ -172,7 +172,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
var (
|
var (
|
||||||
itemIndex int
|
itemIndex int
|
||||||
currentCount int
|
currentCount int
|
||||||
nodes []*Node
|
nodes []Node
|
||||||
)
|
)
|
||||||
|
|
||||||
for itemIndex < len(b.items) {
|
for itemIndex < len(b.items) {
|
||||||
@ -217,7 +217,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
return nodes, true
|
return nodes, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return []*Node{{
|
return []Node{{
|
||||||
Name: b.name,
|
Name: b.name,
|
||||||
From: from,
|
From: from,
|
||||||
To: to,
|
To: to,
|
||||||
|
|||||||
@ -6,37 +6,37 @@ func TestSExpr(t *testing.T) {
|
|||||||
runTestsFile(t, "doc/example/sexpr.treerack", []testItem{{
|
runTestsFile(t, "doc/example/sexpr.treerack", []testItem{{
|
||||||
title: "number",
|
title: "number",
|
||||||
text: "42",
|
text: "42",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "number",
|
Name: "number",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
title: "string",
|
title: "string",
|
||||||
text: "\"foo\"",
|
text: "\"foo\"",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "string",
|
Name: "string",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
title: "symbol",
|
title: "symbol",
|
||||||
text: "foo",
|
text: "foo",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
title: "nil",
|
title: "nil",
|
||||||
text: "()",
|
text: "()",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
}},
|
}},
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
}, {
|
}, {
|
||||||
title: "list",
|
title: "list",
|
||||||
text: "(foo bar baz)",
|
text: "(foo bar baz)",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -48,17 +48,17 @@ func TestSExpr(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "embedded list",
|
title: "embedded list",
|
||||||
text: "(foo (bar (baz)) qux)",
|
text: "(foo (bar (baz)) qux)",
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -72,9 +72,9 @@ func TestSExpr(t *testing.T) {
|
|||||||
text: `; some comment
|
text: `; some comment
|
||||||
(some expression)`,
|
(some expression)`,
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -85,9 +85,9 @@ func TestSExpr(t *testing.T) {
|
|||||||
text: `;
|
text: `;
|
||||||
(some expression)`,
|
(some expression)`,
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
nodes: []*Node{{
|
nodes: []Node{{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
|
|||||||
12
syntax.go
12
syntax.go
@ -381,7 +381,7 @@ func (s *Syntax) ReadSyntax(r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n := mapSelfNode(sn)
|
n := mapSelfNode(sn)
|
||||||
s.ast = n
|
s.ast = &n
|
||||||
return define(s, n)
|
return define(s, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,9 +498,9 @@ func (s *Syntax) Generate(o GeneratorOptions, w io.Writer) error {
|
|||||||
fprintln()
|
fprintln()
|
||||||
|
|
||||||
if o.Export {
|
if o.Export {
|
||||||
fprint(`func Parse(r io.Reader) (*Node, error) {`)
|
fprint(`func Parse(r io.Reader) (Node, error) {`)
|
||||||
} else {
|
} else {
|
||||||
fprint(`func parse(r io.Reader) (*node, error) {`)
|
fprint(`func parse(r io.Reader) (node, error) {`)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintln()
|
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.
|
// 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 {
|
if err := s.Init(); err != nil {
|
||||||
return nil, err
|
return Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseInput(r, s.root.parser(), s.root.builder(), s.keywordParsers())
|
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 formatDefinitions(out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return formatAST(out, s.ast)
|
return formatAST(out, *s.ast)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,7 +89,7 @@ type parser interface {
|
|||||||
type builder interface {
|
type builder interface {
|
||||||
nodeName() string
|
nodeName() string
|
||||||
nodeID() int
|
nodeID() int
|
||||||
build(*context) ([]*Node, bool)
|
build(*context) ([]Node, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrInvalidUnicodeCharacter indicates that the input content contains invalid UTF-8 sequences.
|
// 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)
|
c := newContext(bufio.NewReader(r), kw)
|
||||||
p.parse(c)
|
p.parse(c)
|
||||||
if c.readErr != nil {
|
if c.readErr != nil {
|
||||||
return nil, c.readErr
|
return Node{}, c.readErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.finalizeParse(p); err != nil {
|
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>"
|
perr.Input = "<input>"
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, err
|
return Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.offset = 0
|
c.offset = 0
|
||||||
|
|||||||
@ -25,18 +25,18 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
tests := []testItem{{
|
tests := []testItem{{
|
||||||
title: "empty",
|
title: "empty",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "only a cell",
|
title: "only a cell",
|
||||||
text: "abc",
|
text: "abc",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -45,11 +45,11 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
title: "single line",
|
title: "single line",
|
||||||
text: `a, b, c`,
|
text: `a, b, c`,
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}, {
|
}, {
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
@ -63,11 +63,11 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
text: `a, b, c
|
text: `a, b, c
|
||||||
d, e, f`,
|
d, e, f`,
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}, {
|
}, {
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
@ -76,7 +76,7 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}, {
|
}, {
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
@ -90,11 +90,11 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
text: `a,, b, c,
|
text: `a,, b, c,
|
||||||
d, ,,,,`,
|
d, ,,,,`,
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}, {
|
}, {
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
@ -107,7 +107,7 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}, {
|
}, {
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
@ -126,11 +126,11 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
title: "too many commas",
|
title: "too many commas",
|
||||||
text: `a,,`,
|
text: `a,,`,
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}, {
|
}, {
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
@ -143,11 +143,11 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
title: "csv with tabs",
|
title: "csv with tabs",
|
||||||
text: "a,\tb, c",
|
text: "a,\tb, c",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}, {
|
}, {
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
@ -159,14 +159,14 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
}, {
|
}, {
|
||||||
title: "whitespace between lines",
|
title: "whitespace between lines",
|
||||||
text: " a, b, c \n d, e, f ",
|
text: " a, b, c \n d, e, f ",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
To: 19,
|
To: 19,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
From: 1,
|
From: 1,
|
||||||
To: 8,
|
To: 8,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
From: 1,
|
From: 1,
|
||||||
To: 2,
|
To: 2,
|
||||||
@ -183,7 +183,7 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
Name: "line",
|
Name: "line",
|
||||||
From: 11,
|
From: 11,
|
||||||
To: 18,
|
To: 18,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
From: 11,
|
From: 11,
|
||||||
To: 12,
|
To: 12,
|
||||||
@ -202,19 +202,19 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
title: "just a space",
|
title: "just a space",
|
||||||
text: " ",
|
text: " ",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "cell with spaces in it",
|
title: "cell with spaces in it",
|
||||||
text: "cell content 1/1, cell content 1/2\ncell content 2/1, cell content 2/2",
|
text: "cell content 1/1, cell content 1/2\ncell content 2/1, cell content 2/2",
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
To: 69,
|
To: 69,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
To: 34,
|
To: 34,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
To: 16,
|
To: 16,
|
||||||
}, {
|
}, {
|
||||||
@ -226,7 +226,7 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
Name: "line",
|
Name: "line",
|
||||||
From: 35,
|
From: 35,
|
||||||
To: 69,
|
To: 69,
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
From: 35,
|
From: 35,
|
||||||
To: 51,
|
To: 51,
|
||||||
@ -241,21 +241,21 @@ func TestCSVWhitespace(t *testing.T) {
|
|||||||
title: "multiple empty lines",
|
title: "multiple empty lines",
|
||||||
text: "\n\n",
|
text: "\n\n",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "document",
|
Name: "document",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "line",
|
Name: "line",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "cell",
|
Name: "cell",
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -296,9 +296,9 @@ func TestWhitespace(t *testing.T) {
|
|||||||
title: "multiple symbols",
|
title: "multiple symbols",
|
||||||
text: "a b c",
|
text: "a b c",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "symbols",
|
Name: "symbols",
|
||||||
Nodes: []*Node{{
|
Nodes: []Node{{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
}, {
|
}, {
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
@ -322,21 +322,21 @@ func TestWhitespace(t *testing.T) {
|
|||||||
title: "just min",
|
title: "just min",
|
||||||
text: "a a a",
|
text: "a a a",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "less than max",
|
title: "less than max",
|
||||||
text: "a a a a",
|
text: "a a a a",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
title: "just max",
|
title: "just max",
|
||||||
text: "a a a a a",
|
text: "a a a a a",
|
||||||
ignorePosition: true,
|
ignorePosition: true,
|
||||||
node: &Node{
|
node: Node{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user