2016-05-30 19:35:53 +03:00
|
|
|
package compiler
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2016-02-23 14:46:32 +03:00
|
|
|
// TODO use constructor with all matchers, and to their structs private
|
2016-02-25 00:41:52 +03:00
|
|
|
// TODO glue multiple Text nodes (like after QuoteMeta)
|
2016-02-23 14:46:32 +03:00
|
|
|
|
2016-01-08 20:14:31 +03:00
|
|
|
import (
|
|
|
|
"fmt"
|
2016-12-07 10:55:55 +03:00
|
|
|
|
2018-10-02 22:52:57 +03:00
|
|
|
"github.com/gobwas/glob/internal/debug"
|
2016-01-08 20:14:31 +03:00
|
|
|
"github.com/gobwas/glob/match"
|
2016-05-30 19:35:53 +03:00
|
|
|
"github.com/gobwas/glob/syntax/ast"
|
2016-01-08 20:14:31 +03:00
|
|
|
)
|
|
|
|
|
2018-02-16 17:36:02 +03:00
|
|
|
func Compile(tree *ast.Node, sep []rune) (match.Matcher, error) {
|
|
|
|
m, err := compile(tree, sep)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2016-01-08 20:14:31 +03:00
|
|
|
}
|
2018-02-16 17:36:02 +03:00
|
|
|
return m, nil
|
2016-01-08 20:14:31 +03:00
|
|
|
}
|
|
|
|
|
2018-02-16 17:36:02 +03:00
|
|
|
func compileNodes(ns []*ast.Node, sep []rune) ([]match.Matcher, error) {
|
|
|
|
var matchers []match.Matcher
|
|
|
|
for _, n := range ns {
|
|
|
|
m, err := compile(n, sep)
|
2016-05-30 19:35:53 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2016-01-09 02:34:41 +03:00
|
|
|
}
|
2018-02-16 17:36:02 +03:00
|
|
|
matchers = append(matchers, m)
|
2016-01-09 02:34:41 +03:00
|
|
|
}
|
2018-02-16 17:36:02 +03:00
|
|
|
return matchers, nil
|
2016-05-30 19:35:53 +03:00
|
|
|
}
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2019-02-06 23:43:38 +03:00
|
|
|
func compile(node *ast.Node, sep []rune) (m match.Matcher, err error) {
|
2018-10-02 22:52:57 +03:00
|
|
|
if debug.Enabled {
|
2019-02-06 23:43:38 +03:00
|
|
|
debug.EnterPrefix("compiler: compiling %s", node)
|
2018-10-02 22:52:57 +03:00
|
|
|
defer func() {
|
2019-02-06 23:43:38 +03:00
|
|
|
if err != nil {
|
|
|
|
debug.Logf("->! %v", err)
|
|
|
|
} else {
|
|
|
|
debug.Logf("-> %s", m)
|
|
|
|
}
|
|
|
|
debug.LeavePrefix()
|
2018-10-02 22:52:57 +03:00
|
|
|
}()
|
|
|
|
}
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2018-02-16 17:36:02 +03:00
|
|
|
// todo this could be faster on pattern_alternatives_combine_lite (see glob_test.go)
|
2019-02-06 23:43:38 +03:00
|
|
|
if n := ast.Minimize(node); n != nil {
|
|
|
|
debug.Logf("minimized tree -> %s", node, n)
|
2018-02-16 17:36:02 +03:00
|
|
|
r, err := compile(n, sep)
|
2018-10-02 22:52:57 +03:00
|
|
|
if debug.Enabled {
|
|
|
|
if err != nil {
|
|
|
|
debug.Logf("compiler: compile minimized tree failed: %v", err)
|
|
|
|
} else {
|
|
|
|
debug.Logf("compiler: minimized tree")
|
2019-02-06 23:43:38 +03:00
|
|
|
debug.Logf("compiler: \t%s", node)
|
2018-10-02 22:52:57 +03:00
|
|
|
debug.Logf("compiler: \t%s", n)
|
|
|
|
}
|
|
|
|
}
|
2018-02-16 17:36:02 +03:00
|
|
|
if err == nil {
|
|
|
|
return r, nil
|
2016-01-08 20:14:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-06 23:43:38 +03:00
|
|
|
switch node.Kind {
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindAnyOf:
|
2019-02-06 23:43:38 +03:00
|
|
|
matchers, err := compileNodes(node.Children, sep)
|
2016-05-30 19:35:53 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2016-01-08 20:14:31 +03:00
|
|
|
}
|
2016-02-24 12:36:15 +03:00
|
|
|
return match.NewAnyOf(matchers...), nil
|
2016-01-15 19:50:12 +03:00
|
|
|
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindPattern:
|
2019-02-06 23:43:38 +03:00
|
|
|
if len(node.Children) == 0 {
|
2016-02-24 12:36:15 +03:00
|
|
|
return match.NewNothing(), nil
|
2016-01-15 19:50:12 +03:00
|
|
|
}
|
2019-02-06 23:43:38 +03:00
|
|
|
matchers, err := compileNodes(node.Children, sep)
|
2016-05-30 19:35:53 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2016-01-15 19:50:12 +03:00
|
|
|
}
|
2018-02-16 17:36:02 +03:00
|
|
|
m, err = match.Compile(match.Minimize(matchers))
|
2016-01-15 19:50:12 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2016-01-08 20:14:31 +03:00
|
|
|
}
|
|
|
|
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindAny:
|
|
|
|
m = match.NewAny(sep)
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindSuper:
|
|
|
|
m = match.NewSuper()
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindSingle:
|
|
|
|
m = match.NewSingle(sep)
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindNothing:
|
|
|
|
m = match.NewNothing()
|
|
|
|
|
|
|
|
case ast.KindList:
|
2019-02-06 23:43:38 +03:00
|
|
|
l := node.Value.(ast.List)
|
2016-05-30 19:35:53 +03:00
|
|
|
m = match.NewList([]rune(l.Chars), l.Not)
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindRange:
|
2019-02-06 23:43:38 +03:00
|
|
|
r := node.Value.(ast.Range)
|
2016-05-30 19:35:53 +03:00
|
|
|
m = match.NewRange(r.Lo, r.Hi, r.Not)
|
2016-01-08 20:14:31 +03:00
|
|
|
|
2016-05-30 19:35:53 +03:00
|
|
|
case ast.KindText:
|
2019-02-06 23:43:38 +03:00
|
|
|
t := node.Value.(ast.Text)
|
2016-05-30 19:35:53 +03:00
|
|
|
m = match.NewText(t.Text)
|
2016-01-08 20:14:31 +03:00
|
|
|
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("could not compile tree: unknown node type")
|
|
|
|
}
|
|
|
|
|
2018-02-16 17:36:02 +03:00
|
|
|
return match.Optimize(m), nil
|
2016-01-08 20:14:31 +03:00
|
|
|
}
|