glob/compiler/compiler.go

113 lines
2.3 KiB
Go
Raw Normal View History

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
2018-02-16 17:36:02 +03:00
func compile(tree *ast.Node, sep []rune) (m match.Matcher, err error) {
2018-10-02 22:52:57 +03:00
if debug.Enabled {
debug.Enter()
debug.Logf("compiler: compiling %s", tree)
defer func() {
debug.Logf("compiler: result %s", m)
debug.Leave()
}()
}
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)
if n := ast.Minimize(tree); n != nil {
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")
debug.Logf("compiler: \t%s", tree)
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
}
}
2016-05-30 19:35:53 +03:00
switch tree.Kind {
case ast.KindAnyOf:
2018-02-16 17:36:02 +03:00
matchers, err := compileNodes(tree.Children, sep)
2016-05-30 19:35:53 +03:00
if err != nil {
return nil, err
2016-01-08 20:14:31 +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:
if len(tree.Children) == 0 {
return match.NewNothing(), nil
2016-01-15 19:50:12 +03:00
}
2018-02-16 17:36:02 +03:00
matchers, err := compileNodes(tree.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:
l := tree.Value.(ast.List)
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:
r := tree.Value.(ast.Range)
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:
t := tree.Value.(ast.Text)
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
}