glob/parser.go

231 lines
3.7 KiB
Go
Raw Permalink Normal View History

2015-12-25 19:40:36 +03:00
package glob
import (
"errors"
"fmt"
2016-01-09 02:34:41 +03:00
"unicode/utf8"
2015-12-25 19:40:36 +03:00
)
2016-01-08 20:14:31 +03:00
type node interface {
children() []node
append(node)
}
2015-12-25 19:40:36 +03:00
2016-05-12 10:46:16 +03:00
// todo may be split it into another package
type lexerIface interface {
nextItem() item
}
2016-01-08 20:14:31 +03:00
type nodeImpl struct {
desc []node
}
func (n *nodeImpl) append(c node) {
n.desc = append(n.desc, c)
}
func (n *nodeImpl) children() []node {
return n.desc
}
type nodeList struct {
nodeImpl
not bool
chars string
}
type nodeRange struct {
nodeImpl
not bool
lo, hi rune
}
type nodeText struct {
nodeImpl
text string
}
type nodePattern struct{ nodeImpl }
type nodeAny struct{ nodeImpl }
type nodeSuper struct{ nodeImpl }
type nodeSingle struct{ nodeImpl }
type nodeAnyOf struct{ nodeImpl }
type tree struct {
root node
current node
path []node
}
func (t *tree) enter(c node) {
if t.root == nil {
t.root = c
t.current = c
return
2015-12-25 19:40:36 +03:00
}
2016-01-08 20:14:31 +03:00
t.current.append(c)
t.path = append(t.path, c)
t.current = c
2015-12-25 19:40:36 +03:00
}
2016-01-08 20:14:31 +03:00
func (t *tree) leave() {
if len(t.path)-1 <= 0 {
t.current = t.root
t.path = nil
return
}
2015-12-25 19:40:36 +03:00
2016-01-08 20:14:31 +03:00
t.path = t.path[:len(t.path)-1]
t.current = t.path[len(t.path)-1]
}
2016-05-12 10:46:16 +03:00
type parseFn func(*tree, lexerIface) (parseFn, error)
2015-12-25 19:40:36 +03:00
2016-05-12 10:46:16 +03:00
func parse(lexer lexerIface) (*nodePattern, error) {
2016-01-08 20:14:31 +03:00
var parser parseFn
2015-12-25 19:40:36 +03:00
2016-01-08 20:14:31 +03:00
root := &nodePattern{}
tree := &tree{}
tree.enter(root)
for parser = parserMain; ; {
next, err := parser(tree, lexer)
if err != nil {
return nil, err
}
if next == nil {
2015-12-25 19:40:36 +03:00
break
}
2016-01-08 20:14:31 +03:00
parser = next
}
return root, nil
}
2016-05-12 10:46:16 +03:00
func parserMain(tree *tree, lexer lexerIface) (parseFn, error) {
2016-01-08 20:14:31 +03:00
for stop := false; !stop; {
item := lexer.nextItem()
2015-12-25 19:40:36 +03:00
switch item.t {
case item_eof:
2016-01-08 20:14:31 +03:00
stop = true
continue
2015-12-25 19:40:36 +03:00
case item_error:
2016-01-08 20:14:31 +03:00
return nil, errors.New(item.s)
2015-12-25 19:40:36 +03:00
case item_text:
2016-01-08 20:14:31 +03:00
tree.current.append(&nodeText{text: item.s})
return parserMain, nil
2015-12-25 19:40:36 +03:00
case item_any:
2016-01-08 20:14:31 +03:00
tree.current.append(&nodeAny{})
return parserMain, nil
case item_super:
tree.current.append(&nodeSuper{})
return parserMain, nil
2015-12-25 19:40:36 +03:00
case item_single:
2016-01-08 20:14:31 +03:00
tree.current.append(&nodeSingle{})
return parserMain, nil
2015-12-25 19:40:36 +03:00
case item_range_open:
2016-01-08 20:14:31 +03:00
return parserRange, nil
case item_terms_open:
tree.enter(&nodeAnyOf{})
tree.enter(&nodePattern{})
return parserMain, nil
2015-12-25 19:40:36 +03:00
2016-01-08 20:14:31 +03:00
case item_separator:
tree.leave()
tree.enter(&nodePattern{})
return parserMain, nil
case item_terms_close:
tree.leave()
tree.leave()
return parserMain, nil
default:
return nil, fmt.Errorf("unexpected token: %s", item)
}
2015-12-25 19:40:36 +03:00
}
2016-01-08 20:14:31 +03:00
return nil, nil
2015-12-25 19:40:36 +03:00
}
2016-05-12 10:46:16 +03:00
func parserRange(tree *tree, lexer lexerIface) (parseFn, error) {
2015-12-25 19:40:36 +03:00
var (
not bool
lo rune
hi rune
chars string
)
2016-01-08 20:14:31 +03:00
for {
item := lexer.nextItem()
2015-12-25 19:40:36 +03:00
switch item.t {
case item_eof:
2016-01-08 20:14:31 +03:00
return nil, errors.New("unexpected end")
2015-12-25 19:40:36 +03:00
case item_error:
2016-01-08 20:14:31 +03:00
return nil, errors.New(item.s)
2015-12-25 19:40:36 +03:00
2016-01-08 20:14:31 +03:00
case item_not:
2015-12-25 19:40:36 +03:00
not = true
case item_range_lo:
2016-01-09 02:34:41 +03:00
r, w := utf8.DecodeRuneInString(item.s)
if len(item.s) > w {
2016-01-08 20:14:31 +03:00
return nil, fmt.Errorf("unexpected length of lo character")
2015-12-25 19:40:36 +03:00
}
2016-01-09 02:34:41 +03:00
lo = r
2015-12-25 19:40:36 +03:00
2016-01-08 20:14:31 +03:00
case item_range_between:
2015-12-25 19:40:36 +03:00
//
case item_range_hi:
2016-01-09 02:34:41 +03:00
r, w := utf8.DecodeRuneInString(item.s)
if len(item.s) > w {
return nil, fmt.Errorf("unexpected length of lo character")
2015-12-25 19:40:36 +03:00
}
2016-01-09 02:34:41 +03:00
hi = r
2016-01-08 20:14:31 +03:00
2015-12-25 21:08:54 +03:00
if hi < lo {
2016-01-08 20:14:31 +03:00
return nil, fmt.Errorf("hi character '%s' should be greater than lo '%s'", string(hi), string(lo))
2015-12-25 21:08:54 +03:00
}
2016-01-08 20:14:31 +03:00
case item_text:
2015-12-25 19:40:36 +03:00
chars = item.s
case item_range_close:
isRange := lo != 0 && hi != 0
2016-01-08 20:14:31 +03:00
isChars := chars != ""
2015-12-25 19:40:36 +03:00
2016-01-08 20:14:31 +03:00
if isChars == isRange {
return nil, fmt.Errorf("could not parse range")
2015-12-25 19:40:36 +03:00
}
if isRange {
2016-01-08 20:14:31 +03:00
tree.current.append(&nodeRange{
lo: lo,
hi: hi,
not: not,
})
2015-12-25 19:40:36 +03:00
} else {
2016-01-08 20:14:31 +03:00
tree.current.append(&nodeList{
chars: chars,
not: not,
})
2015-12-25 19:40:36 +03:00
}
2016-01-08 20:14:31 +03:00
return parserMain, nil
2015-12-25 19:40:36 +03:00
}
}
}