refactoring done

This commit is contained in:
gobwas 2016-05-31 11:28:02 +03:00
parent 510a1756cf
commit 36eb5476d5
7 changed files with 468 additions and 460 deletions

View File

@ -350,23 +350,33 @@ func minimizeTreeAnyOf(tree *ast.Node) *ast.Node {
} }
func commonChildren(nodes []*ast.Node) (commonLeft, commonRight []*ast.Node) { func commonChildren(nodes []*ast.Node) (commonLeft, commonRight []*ast.Node) {
if len(nodes) <= 1 {
return
}
// find node that has least number of children // find node that has least number of children
idx := leastChildren(nodes) idx := leastChildren(nodes)
if idx == -1 { if idx == -1 {
return nil, nil return
} }
tree := nodes[idx] tree := nodes[idx]
treeLength := len(tree.Children)
// allocate max able size for rightCommon slice
// to get ability insert elements in reverse order (from end to start)
// without sorting
commonRight = make([]*ast.Node, treeLength)
lastRight := treeLength // will use this to get results as commonRight[lastRight:]
var ( var (
breakLeft bool breakLeft bool
breakRight bool breakRight bool
commonTotal int
) )
for i, j := 0, len(tree.Children)-1; j >= 0 && !(breakLeft && breakLeft); i, j = i+1, j-1 { for i, j := 0, treeLength-1; commonTotal < treeLength && j >= 0 && !(breakLeft && breakLeft); i, j = i+1, j-1 {
treeLeft := tree.Children[i] treeLeft := tree.Children[i]
treeRight := tree.Children[j] treeRight := tree.Children[j]
fmt.Println(i, j)
for k := 0; k < len(nodes) && !(breakLeft && breakLeft); k++ { for k := 0; k < len(nodes) && !(breakLeft && breakLeft); k++ {
// skip least children node // skip least children node
if k == idx { if k == idx {
@ -374,7 +384,7 @@ func commonChildren(nodes []*ast.Node) (commonLeft, commonRight []*ast.Node) {
} }
restLeft := nodes[k].Children[i] restLeft := nodes[k].Children[i]
restRight := nodes[k].Children[j+len(nodes[k].Children)-len(tree.Children)] restRight := nodes[k].Children[j+len(nodes[k].Children)-treeLength]
breakLeft = breakLeft || !treeLeft.Equal(restLeft) breakLeft = breakLeft || !treeLeft.Equal(restLeft)
@ -382,15 +392,20 @@ func commonChildren(nodes []*ast.Node) (commonLeft, commonRight []*ast.Node) {
breakRight = breakRight || (!breakLeft && j <= i) breakRight = breakRight || (!breakLeft && j <= i)
breakRight = breakRight || !treeRight.Equal(restRight) breakRight = breakRight || !treeRight.Equal(restRight)
} }
if !breakLeft { if !breakLeft {
fmt.Println("left app") commonTotal++
commonLeft = append(commonLeft, treeLeft) commonLeft = append(commonLeft, treeLeft)
} }
if !breakRight { if !breakRight {
fmt.Println("right app") commonTotal++
commonRight = append(commonRight, treeRight) lastRight = j
commonRight[j] = treeRight
} }
} }
commonRight = commonRight[lastRight:]
return return
} }

View File

@ -16,26 +16,35 @@ func TestCommonChildren(t *testing.T) {
left []*ast.Node left []*ast.Node
right []*ast.Node right []*ast.Node
}{ }{
// { {
// nodes: []*ast.Node{ nodes: []*ast.Node{
// ast.NewNode(ast.KindNothing, nil, ast.NewNode(ast.KindNothing, nil,
// ast.NewNode(ast.KindText, ast.Text{"a"}), ast.NewNode(ast.KindText, ast.Text{"a"}),
// ast.NewNode(ast.KindText, ast.Text{"z"}), ast.NewNode(ast.KindText, ast.Text{"z"}),
// ast.NewNode(ast.KindText, ast.Text{"c"}), ast.NewNode(ast.KindText, ast.Text{"c"}),
// ), ),
// ast.NewNode(ast.KindNothing, nil, },
// ast.NewNode(ast.KindText, ast.Text{"a"}), },
// ast.NewNode(ast.KindText, ast.Text{"b"}), {
// ast.NewNode(ast.KindText, ast.Text{"c"}), nodes: []*ast.Node{
// ), ast.NewNode(ast.KindNothing, nil,
// }, ast.NewNode(ast.KindText, ast.Text{"a"}),
// left: []*ast.Node{ ast.NewNode(ast.KindText, ast.Text{"z"}),
// ast.NewNode(ast.KindText, ast.Text{"a"}), ast.NewNode(ast.KindText, ast.Text{"c"}),
// }, ),
// right: []*ast.Node{ ast.NewNode(ast.KindNothing, nil,
// ast.NewNode(ast.KindText, ast.Text{"c"}), ast.NewNode(ast.KindText, ast.Text{"a"}),
// }, ast.NewNode(ast.KindText, ast.Text{"b"}),
// }, ast.NewNode(ast.KindText, ast.Text{"c"}),
),
},
left: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"a"}),
},
right: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"c"}),
},
},
{ {
nodes: []*ast.Node{ nodes: []*ast.Node{
ast.NewNode(ast.KindNothing, nil, ast.NewNode(ast.KindNothing, nil,
@ -55,12 +64,54 @@ func TestCommonChildren(t *testing.T) {
left: []*ast.Node{ left: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"a"}), ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"b"}), ast.NewNode(ast.KindText, ast.Text{"b"}),
ast.NewNode(ast.KindText, ast.Text{"c"}),
}, },
right: []*ast.Node{ right: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"c"}),
ast.NewNode(ast.KindText, ast.Text{"d"}), ast.NewNode(ast.KindText, ast.Text{"d"}),
}, },
}, },
{
nodes: []*ast.Node{
ast.NewNode(ast.KindNothing, nil,
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"b"}),
ast.NewNode(ast.KindText, ast.Text{"c"}),
),
ast.NewNode(ast.KindNothing, nil,
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"b"}),
ast.NewNode(ast.KindText, ast.Text{"b"}),
ast.NewNode(ast.KindText, ast.Text{"c"}),
),
},
left: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"b"}),
},
right: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"c"}),
},
},
{
nodes: []*ast.Node{
ast.NewNode(ast.KindNothing, nil,
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"d"}),
),
ast.NewNode(ast.KindNothing, nil,
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"d"}),
),
ast.NewNode(ast.KindNothing, nil,
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"e"}),
),
},
left: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"a"}),
},
right: []*ast.Node{},
},
} { } {
left, right := commonChildren(test.nodes) left, right := commonChildren(test.nodes)
if !nodesEqual(left, test.left) { if !nodesEqual(left, test.left) {
@ -268,238 +319,238 @@ func TestCompiler(t *testing.T) {
result match.Matcher result match.Matcher
sep []rune sep []rune
}{ }{
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ), ),
// result: match.NewText("abc"), result: match.NewText("abc"),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ), ),
// sep: separators, sep: separators,
// result: match.NewAny(separators), result: match.NewAny(separators),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ), ),
// result: match.NewSuper(), result: match.NewSuper(),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSuper, nil), ast.NewNode(ast.KindSuper, nil),
// ), ),
// result: match.NewSuper(), result: match.NewSuper(),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ), ),
// sep: separators, sep: separators,
// result: match.NewSingle(separators), result: match.NewSingle(separators),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindRange, &ast.Range{ ast.NewNode(ast.KindRange, ast.Range{
// Lo: 'a', Lo: 'a',
// Hi: 'z', Hi: 'z',
// Not: true, Not: true,
// }), }),
// ), ),
// result: match.NewRange('a', 'z', true), result: match.NewRange('a', 'z', true),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindList, &ast.List{ ast.NewNode(ast.KindList, ast.List{
// Chars: "abc", Chars: "abc",
// Not: true, Not: true,
// }), }),
// ), ),
// result: match.NewList([]rune{'a', 'b', 'c'}, true), result: match.NewList([]rune{'a', 'b', 'c'}, true),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ), ),
// sep: separators, sep: separators,
// result: match.EveryOf{Matchers: match.Matchers{ result: match.EveryOf{Matchers: match.Matchers{
// match.NewMin(3), match.NewMin(3),
// match.NewContains(string(separators), true), match.NewContains(string(separators), true),
// }}, }},
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ), ),
// result: match.NewMin(3), result: match.NewMin(3),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ), ),
// sep: separators, sep: separators,
// result: match.NewBTree( result: match.NewBTree(
// match.NewRow( match.NewRow(
// 4, 4,
// match.Matchers{ match.Matchers{
// match.NewText("abc"), match.NewText("abc"),
// match.NewSingle(separators), match.NewSingle(separators),
// }..., }...,
// ), ),
// match.NewAny(separators), match.NewAny(separators),
// nil, nil,
// ), ),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"/"}), ast.NewNode(ast.KindText, ast.Text{"/"}),
// ast.NewNode(ast.KindAnyOf, nil, ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindText, &ast.Text{"z"}), ast.NewNode(ast.KindText, ast.Text{"z"}),
// ast.NewNode(ast.KindText, &ast.Text{"ab"}), ast.NewNode(ast.KindText, ast.Text{"ab"}),
// ), ),
// ast.NewNode(ast.KindSuper, nil), ast.NewNode(ast.KindSuper, nil),
// ), ),
// sep: separators, sep: separators,
// result: match.NewBTree( result: match.NewBTree(
// match.NewText("/"), match.NewText("/"),
// nil, nil,
// match.NewBTree( match.NewBTree(
// match.NewAnyOf(match.NewText("z"), match.NewText("ab")), match.NewAnyOf(match.NewText("z"), match.NewText("ab")),
// nil, nil,
// match.NewSuper(), match.NewSuper(),
// ), ),
// ), ),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSuper, nil), ast.NewNode(ast.KindSuper, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ), ),
// sep: separators, sep: separators,
// result: match.NewBTree( result: match.NewBTree(
// match.NewRow( match.NewRow(
// 5, 5,
// match.Matchers{ match.Matchers{
// match.NewSingle(separators), match.NewSingle(separators),
// match.NewText("abc"), match.NewText("abc"),
// match.NewSingle(separators), match.NewSingle(separators),
// }..., }...,
// ), ),
// match.NewSuper(), match.NewSuper(),
// nil, nil,
// ), ),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ), ),
// result: match.NewSuffix("abc"), result: match.NewSuffix("abc"),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ), ),
// result: match.NewPrefix("abc"), result: match.NewPrefix("abc"),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"def"}), ast.NewNode(ast.KindText, ast.Text{"def"}),
// ), ),
// result: match.NewPrefixSuffix("abc", "def"), result: match.NewPrefixSuffix("abc", "def"),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ), ),
// result: match.NewContains("abc", false), result: match.NewContains("abc", false),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ), ),
// sep: separators, sep: separators,
// result: match.NewBTree( result: match.NewBTree(
// match.NewText("abc"), match.NewText("abc"),
// match.NewAny(separators), match.NewAny(separators),
// match.NewAny(separators), match.NewAny(separators),
// ), ),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSuper, nil), ast.NewNode(ast.KindSuper, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindSuper, nil), ast.NewNode(ast.KindSuper, nil),
// ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
// ), ),
// result: match.NewBTree( result: match.NewBTree(
// match.NewText("abc"), match.NewText("abc"),
// match.NewMin(1), match.NewMin(1),
// match.NewMin(1), match.NewMin(1),
// ), ),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ), ),
// result: match.NewText("abc"), result: match.NewText("abc"),
// }, },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ),
// ),
// ),
// ),
// ),
// result: match.NewText("abc"),
// },
{ {
ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindAnyOf, nil, ast.NewNode(ast.KindAnyOf, nil,
ast.NewNode(ast.KindPattern, nil, ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindAnyOf, nil,
ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, ast.Text{"abc"}),
),
),
),
),
),
result: match.NewText("abc"),
},
{
ast: ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindAnyOf, nil,
ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, ast.Text{"abc"}),
ast.NewNode(ast.KindSingle, nil), ast.NewNode(ast.KindSingle, nil),
), ),
ast.NewNode(ast.KindPattern, nil, ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
ast.NewNode(ast.KindList, &ast.List{Chars: "def"}), ast.NewNode(ast.KindList, ast.List{Chars: "def"}),
), ),
ast.NewNode(ast.KindPattern, nil, ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
), ),
ast.NewNode(ast.KindPattern, nil, ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
), ),
), ),
), ),
@ -513,51 +564,51 @@ func TestCompiler(t *testing.T) {
}}, }},
), ),
}, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindRange, &ast.Range{Lo: 'a', Hi: 'z'}), ast.NewNode(ast.KindRange, ast.Range{Lo: 'a', Hi: 'z'}),
// ast.NewNode(ast.KindRange, &ast.Range{Lo: 'a', Hi: 'x', Not: true}), ast.NewNode(ast.KindRange, ast.Range{Lo: 'a', Hi: 'x', Not: true}),
// ast.NewNode(ast.KindAny, nil), ast.NewNode(ast.KindAny, nil),
// ), ),
// result: match.NewBTree( result: match.NewBTree(
// match.NewRow( match.NewRow(
// 2, 2,
// match.Matchers{ match.Matchers{
// match.NewRange('a', 'z', false), match.NewRange('a', 'z', false),
// match.NewRange('a', 'x', true), match.NewRange('a', 'x', true),
// }..., }...,
// ), ),
// nil, nil,
// match.NewSuper(), match.NewSuper(),
// ), ),
// }, },
// { {
// ast: ast.NewNode(ast.KindPattern, nil, ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAnyOf, nil, ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindPattern, nil, ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindList, &ast.List{Chars: "abc"}), ast.NewNode(ast.KindList, ast.List{Chars: "abc"}),
// ast.NewNode(ast.KindText, &ast.Text{"ghi"}), ast.NewNode(ast.KindText, ast.Text{"ghi"}),
// ), ),
// ast.NewNode(ast.KindPattern, nil, ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}), ast.NewNode(ast.KindText, ast.Text{"abc"}),
// ast.NewNode(ast.KindList, &ast.List{Chars: "def"}), ast.NewNode(ast.KindList, ast.List{Chars: "def"}),
// ast.NewNode(ast.KindText, &ast.Text{"ghi"}), ast.NewNode(ast.KindText, ast.Text{"ghi"}),
// ), ),
// ), ),
// ), ),
// result: match.NewRow( result: match.NewRow(
// 7, 7,
// match.Matchers{ match.Matchers{
// match.NewText("abc"), match.NewText("abc"),
// match.AnyOf{Matchers: match.Matchers{ match.AnyOf{Matchers: match.Matchers{
// match.NewList([]rune{'a', 'b', 'c'}, false), match.NewList([]rune{'a', 'b', 'c'}, false),
// match.NewList([]rune{'d', 'e', 'f'}, false), match.NewList([]rune{'d', 'e', 'f'}, false),
// }}, }},
// match.NewText("ghi"), match.NewText("ghi"),
// }..., }...,
// ), ),
// }, },
} { } {
m, err := Compile(test.ast, test.sep) m, err := Compile(test.ast, test.sep)
if err != nil { if err != nil {

View File

@ -1,7 +1,7 @@
package glob package glob
import ( import (
"github.com/gobwas/glob/parser" "github.com/gobwas/glob/compiler"
"github.com/gobwas/glob/syntax" "github.com/gobwas/glob/syntax"
) )
@ -42,7 +42,7 @@ func Compile(pattern string, separators ...rune) (Glob, error) {
return nil, err return nil, err
} }
matcher, err := compile(ast, separators) matcher, err := compiler.Compile(ast, separators)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -159,12 +159,6 @@ func TestGlob(t *testing.T) {
} }
func TestQuoteMeta(t *testing.T) { func TestQuoteMeta(t *testing.T) {
specialsQuoted := make([]byte, len(specials)*2)
for i, j := 0, 0; i < len(specials); i, j = i+1, j+2 {
specialsQuoted[j] = '\\'
specialsQuoted[j+1] = specials[i]
}
for id, test := range []struct { for id, test := range []struct {
in, out string in, out string
}{ }{
@ -177,12 +171,12 @@ func TestQuoteMeta(t *testing.T) {
out: `\{foo\*\}`, out: `\{foo\*\}`,
}, },
{ {
in: string(specials), in: `*?\[]{}`,
out: string(specialsQuoted), out: `\*\?\\\[\]\{\}`,
}, },
{ {
in: string(append([]byte("some text and"), specials...)), in: `some text and *?\[]{}`,
out: string(append([]byte("some text and"), specialsQuoted...)), out: `some text and \*\?\\\[\]\{\}`,
}, },
} { } {
act := QuoteMeta(test.in) act := QuoteMeta(test.in)

View File

@ -1,18 +1,5 @@
package ast package ast
type Visitor interface {
Visit(*Node) Visitor
}
func Walk(v Visitor, n *Node) {
if v = v.Visit(n); v == nil {
return
}
for _, c := range n.Children {
Walk(v, c)
}
}
type Node struct { type Node struct {
Parent *Node Parent *Node
Children []*Node Children []*Node

View File

@ -43,7 +43,7 @@ func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) {
return nil, tree, errors.New(token.Raw) return nil, tree, errors.New(token.Raw)
case lexer.Text: case lexer.Text:
Insert(tree, NewNode(KindText, &Text{token.Raw})) Insert(tree, NewNode(KindText, Text{token.Raw}))
return parserMain, tree, nil return parserMain, tree, nil
case lexer.Any: case lexer.Any:
@ -139,13 +139,13 @@ func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) {
} }
if isRange { if isRange {
Insert(tree, NewNode(KindRange, &Range{ Insert(tree, NewNode(KindRange, Range{
Lo: lo, Lo: lo,
Hi: hi, Hi: hi,
Not: not, Not: not,
})) }))
} else { } else {
Insert(tree, NewNode(KindList, &List{ Insert(tree, NewNode(KindList, List{
Chars: chars, Chars: chars,
Not: not, Not: not,
})) }))

View File

@ -1,19 +1,19 @@
package ast package ast
import ( import (
"github.com/gobwas/glob/syntax" "github.com/gobwas/glob/syntax/lexer"
"reflect" "reflect"
"testing" "testing"
) )
type stubLexer struct { type stubLexer struct {
tokens []syntax.Token tokens []lexer.Token
pos int pos int
} }
func (s *stubLexer) Next() (ret syntax.Token) { func (s *stubLexer) Next() (ret lexer.Token) {
if s.pos == len(s.tokens) { if s.pos == len(s.tokens) {
return syntax.Token{syntax.EOF, ""} return lexer.Token{lexer.EOF, ""}
} }
ret = s.tokens[s.pos] ret = s.tokens[s.pos]
s.pos++ s.pos++
@ -22,129 +22,129 @@ func (s *stubLexer) Next() (ret syntax.Token) {
func TestParseString(t *testing.T) { func TestParseString(t *testing.T) {
for id, test := range []struct { for id, test := range []struct {
tokens []syntax.Token tokens []lexer.Token
tree Node tree *Node
}{ }{
{ {
//pattern: "abc", //pattern: "abc",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.Text, "abc"}, lexer.Token{lexer.Text, "abc"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "abc"}), NewNode(KindText, Text{Text: "abc"}),
), ),
}, },
{ {
//pattern: "a*c", //pattern: "a*c",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.Text, "a"}, lexer.Token{lexer.Text, "a"},
syntax.Token{syntax.Any, "*"}, lexer.Token{lexer.Any, "*"},
syntax.Token{syntax.Text, "c"}, lexer.Token{lexer.Text, "c"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "a"}), NewNode(KindText, Text{Text: "a"}),
NewNode(KindAny, nil), NewNode(KindAny, nil),
NewNode(KindText, &Text{Text: "c"}), NewNode(KindText, Text{Text: "c"}),
), ),
}, },
{ {
//pattern: "a**c", //pattern: "a**c",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.Text, "a"}, lexer.Token{lexer.Text, "a"},
syntax.Token{syntax.Super, "**"}, lexer.Token{lexer.Super, "**"},
syntax.Token{syntax.Text, "c"}, lexer.Token{lexer.Text, "c"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "a"}), NewNode(KindText, Text{Text: "a"}),
NewNode(KindSuper, nil), NewNode(KindSuper, nil),
NewNode(KindText, &Text{Text: "c"}), NewNode(KindText, Text{Text: "c"}),
), ),
}, },
{ {
//pattern: "a?c", //pattern: "a?c",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.Text, "a"}, lexer.Token{lexer.Text, "a"},
syntax.Token{syntax.Single, "?"}, lexer.Token{lexer.Single, "?"},
syntax.Token{syntax.Text, "c"}, lexer.Token{lexer.Text, "c"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "a"}), NewNode(KindText, Text{Text: "a"}),
NewNode(KindSingle, nil), NewNode(KindSingle, nil),
NewNode(KindText, &Text{Text: "c"}), NewNode(KindText, Text{Text: "c"}),
), ),
}, },
{ {
//pattern: "[!a-z]", //pattern: "[!a-z]",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.RangeOpen, "["}, lexer.Token{lexer.RangeOpen, "["},
syntax.Token{syntax.Not, "!"}, lexer.Token{lexer.Not, "!"},
syntax.Token{syntax.RangeLo, "a"}, lexer.Token{lexer.RangeLo, "a"},
syntax.Token{syntax.RangeBetween, "-"}, lexer.Token{lexer.RangeBetween, "-"},
syntax.Token{syntax.RangeHi, "z"}, lexer.Token{lexer.RangeHi, "z"},
syntax.Token{syntax.RangeClose, "]"}, lexer.Token{lexer.RangeClose, "]"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindRange, &Range{Lo: 'a', Hi: 'z', Not: true}), NewNode(KindRange, Range{Lo: 'a', Hi: 'z', Not: true}),
), ),
}, },
{ {
//pattern: "[az]", //pattern: "[az]",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.RangeOpen, "["}, lexer.Token{lexer.RangeOpen, "["},
syntax.Token{syntax.Text, "az"}, lexer.Token{lexer.Text, "az"},
syntax.Token{syntax.RangeClose, "]"}, lexer.Token{lexer.RangeClose, "]"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindList, &List{Chars: "az"}), NewNode(KindList, List{Chars: "az"}),
), ),
}, },
{ {
//pattern: "{a,z}", //pattern: "{a,z}",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.TermsOpen, "{"}, lexer.Token{lexer.TermsOpen, "{"},
syntax.Token{syntax.Text, "a"}, lexer.Token{lexer.Text, "a"},
syntax.Token{syntax.Separator, ","}, lexer.Token{lexer.Separator, ","},
syntax.Token{syntax.Text, "z"}, lexer.Token{lexer.Text, "z"},
syntax.Token{syntax.TermsClose, "}"}, lexer.Token{lexer.TermsClose, "}"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindAnyOf, nil, NewNode(KindAnyOf, nil,
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "a"}), NewNode(KindText, Text{Text: "a"}),
), ),
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "z"}), NewNode(KindText, Text{Text: "z"}),
), ),
), ),
), ),
}, },
{ {
//pattern: "/{z,ab}*", //pattern: "/{z,ab}*",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.Text, "/"}, lexer.Token{lexer.Text, "/"},
syntax.Token{syntax.TermsOpen, "{"}, lexer.Token{lexer.TermsOpen, "{"},
syntax.Token{syntax.Text, "z"}, lexer.Token{lexer.Text, "z"},
syntax.Token{syntax.Separator, ","}, lexer.Token{lexer.Separator, ","},
syntax.Token{syntax.Text, "ab"}, lexer.Token{lexer.Text, "ab"},
syntax.Token{syntax.TermsClose, "}"}, lexer.Token{lexer.TermsClose, "}"},
syntax.Token{syntax.Any, "*"}, lexer.Token{lexer.Any, "*"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "/"}), NewNode(KindText, Text{Text: "/"}),
NewNode(KindAnyOf, nil, NewNode(KindAnyOf, nil,
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "z"}), NewNode(KindText, Text{Text: "z"}),
), ),
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "ab"}), NewNode(KindText, Text{Text: "ab"}),
), ),
), ),
NewNode(KindAny, nil), NewNode(KindAny, nil),
@ -152,43 +152,43 @@ func TestParseString(t *testing.T) {
}, },
{ {
//pattern: "{a,{x,y},?,[a-z],[!qwe]}", //pattern: "{a,{x,y},?,[a-z],[!qwe]}",
tokens: []syntax.Token{ tokens: []lexer.Token{
syntax.Token{syntax.TermsOpen, "{"}, lexer.Token{lexer.TermsOpen, "{"},
syntax.Token{syntax.Text, "a"}, lexer.Token{lexer.Text, "a"},
syntax.Token{syntax.Separator, ","}, lexer.Token{lexer.Separator, ","},
syntax.Token{syntax.TermsOpen, "{"}, lexer.Token{lexer.TermsOpen, "{"},
syntax.Token{syntax.Text, "x"}, lexer.Token{lexer.Text, "x"},
syntax.Token{syntax.Separator, ","}, lexer.Token{lexer.Separator, ","},
syntax.Token{syntax.Text, "y"}, lexer.Token{lexer.Text, "y"},
syntax.Token{syntax.TermsClose, "}"}, lexer.Token{lexer.TermsClose, "}"},
syntax.Token{syntax.Separator, ","}, lexer.Token{lexer.Separator, ","},
syntax.Token{syntax.Single, "?"}, lexer.Token{lexer.Single, "?"},
syntax.Token{syntax.Separator, ","}, lexer.Token{lexer.Separator, ","},
syntax.Token{syntax.RangeOpen, "["}, lexer.Token{lexer.RangeOpen, "["},
syntax.Token{syntax.RangeLo, "a"}, lexer.Token{lexer.RangeLo, "a"},
syntax.Token{syntax.RangeBetween, "-"}, lexer.Token{lexer.RangeBetween, "-"},
syntax.Token{syntax.RangeHi, "z"}, lexer.Token{lexer.RangeHi, "z"},
syntax.Token{syntax.RangeClose, "]"}, lexer.Token{lexer.RangeClose, "]"},
syntax.Token{syntax.Separator, ","}, lexer.Token{lexer.Separator, ","},
syntax.Token{syntax.RangeOpen, "["}, lexer.Token{lexer.RangeOpen, "["},
syntax.Token{syntax.Not, "!"}, lexer.Token{lexer.Not, "!"},
syntax.Token{syntax.Text, "qwe"}, lexer.Token{lexer.Text, "qwe"},
syntax.Token{syntax.RangeClose, "]"}, lexer.Token{lexer.RangeClose, "]"},
syntax.Token{syntax.TermsClose, "}"}, lexer.Token{lexer.TermsClose, "}"},
syntax.Token{syntax.EOF, ""}, lexer.Token{lexer.EOF, ""},
}, },
tree: NewNode(KindPattern, nil, tree: NewNode(KindPattern, nil,
NewNode(KindAnyOf, nil, NewNode(KindAnyOf, nil,
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "a"}), NewNode(KindText, Text{Text: "a"}),
), ),
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindAnyOf, nil, NewNode(KindAnyOf, nil,
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "x"}), NewNode(KindText, Text{Text: "x"}),
), ),
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindText, &Text{Text: "y"}), NewNode(KindText, Text{Text: "y"}),
), ),
), ),
), ),
@ -196,10 +196,10 @@ func TestParseString(t *testing.T) {
NewNode(KindSingle, nil), NewNode(KindSingle, nil),
), ),
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindRange, &Range{Lo: 'a', Hi: 'z', Not: false}), NewNode(KindRange, Range{Lo: 'a', Hi: 'z', Not: false}),
), ),
NewNode(KindPattern, nil, NewNode(KindPattern, nil,
NewNode(KindList, &List{Chars: "qwe", Not: true}), NewNode(KindList, List{Chars: "qwe", Not: true}),
), ),
), ),
), ),
@ -215,42 +215,3 @@ func TestParseString(t *testing.T) {
} }
} }
} }
type kv struct {
kind Kind
value interface{}
}
type visitor struct {
visited []kv
}
func (v *visitor) Visit(n Node) Visitor {
v.visited = append(v.visited, kv{n.Kind(), n.Value()})
return v
}
func TestWalkTree(t *testing.T) {
for i, test := range []struct {
tree *Node
visited []kv
}{
{
tree: NewNode(KindPattern, nil,
NewNode(KindSingle, nil),
),
visited: []kv{
kv{KindPattern, nil},
kv{KindSingle, nil},
},
},
} {
v := &visitor{}
Walk(v, test.tree)
if !reflect.DeepEqual(test.visited, v.visited) {
t.Errorf("[%d] unexpected result of Walk():\nvisited:\t%v\nwant:\t\t%v", i, v.visited, test.visited)
}
}
}