glob/syntax/ast/parser.go

158 lines
2.9 KiB
Go
Raw Normal View History

2016-05-30 19:35:53 +03:00
package ast
2016-05-27 20:47:19 +03:00
import (
"errors"
"fmt"
2016-05-30 19:35:53 +03:00
"github.com/gobwas/glob/syntax/lexer"
2016-05-27 20:47:19 +03:00
"unicode/utf8"
)
type Lexer interface {
Next() lexer.Token
}
2016-05-30 19:35:53 +03:00
type parseFn func(*Node, Lexer) (parseFn, *Node, error)
2016-05-27 20:47:19 +03:00
2016-05-30 19:35:53 +03:00
func Parse(lexer Lexer) (*Node, error) {
2016-05-27 20:47:19 +03:00
var parser parseFn
2016-05-30 19:35:53 +03:00
root := NewNode(KindPattern, nil)
2016-05-27 20:47:19 +03:00
var (
2016-05-30 19:35:53 +03:00
tree *Node
2016-05-27 20:47:19 +03:00
err error
)
for parser, tree = parserMain, root; parser != nil; {
parser, tree, err = parser(tree, lexer)
if err != nil {
return nil, err
}
}
return root, nil
}
2016-05-30 19:35:53 +03:00
func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) {
2016-05-27 20:47:19 +03:00
for {
token := lex.Next()
switch token.Type {
case lexer.EOF:
return nil, tree, nil
case lexer.Error:
return nil, tree, errors.New(token.Raw)
case lexer.Text:
2016-05-30 19:35:53 +03:00
Insert(tree, NewNode(KindText, &Text{token.Raw}))
return parserMain, tree, nil
2016-05-27 20:47:19 +03:00
case lexer.Any:
2016-05-30 19:35:53 +03:00
Insert(tree, NewNode(KindAny, nil))
return parserMain, tree, nil
2016-05-27 20:47:19 +03:00
case lexer.Super:
2016-05-30 19:35:53 +03:00
Insert(tree, NewNode(KindSuper, nil))
return parserMain, tree, nil
2016-05-27 20:47:19 +03:00
case lexer.Single:
2016-05-30 19:35:53 +03:00
Insert(tree, NewNode(KindSingle, nil))
return parserMain, tree, nil
2016-05-27 20:47:19 +03:00
case lexer.RangeOpen:
return parserRange, tree, nil
case lexer.TermsOpen:
2016-05-30 19:35:53 +03:00
a := NewNode(KindAnyOf, nil)
Insert(tree, a)
p := NewNode(KindPattern, nil)
Insert(a, p)
return parserMain, p, nil
2016-05-27 20:47:19 +03:00
case lexer.Separator:
2016-05-30 19:35:53 +03:00
p := NewNode(KindPattern, nil)
Insert(tree.Parent, p)
return parserMain, p, nil
2016-05-27 20:47:19 +03:00
case lexer.TermsClose:
2016-05-30 19:35:53 +03:00
return parserMain, tree.Parent.Parent, nil
2016-05-27 20:47:19 +03:00
default:
return nil, tree, fmt.Errorf("unexpected token: %s", token)
}
}
return nil, tree, fmt.Errorf("unknown error")
}
2016-05-30 19:35:53 +03:00
func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) {
2016-05-27 20:47:19 +03:00
var (
not bool
lo rune
hi rune
chars string
)
for {
token := lex.Next()
switch token.Type {
case lexer.EOF:
return nil, tree, errors.New("unexpected end")
case lexer.Error:
return nil, tree, errors.New(token.Raw)
case lexer.Not:
not = true
case lexer.RangeLo:
r, w := utf8.DecodeRuneInString(token.Raw)
if len(token.Raw) > w {
return nil, tree, fmt.Errorf("unexpected length of lo character")
}
lo = r
case lexer.RangeBetween:
//
case lexer.RangeHi:
r, w := utf8.DecodeRuneInString(token.Raw)
if len(token.Raw) > w {
return nil, tree, fmt.Errorf("unexpected length of lo character")
}
hi = r
if hi < lo {
return nil, tree, fmt.Errorf("hi character '%s' should be greater than lo '%s'", string(hi), string(lo))
}
case lexer.Text:
chars = token.Raw
case lexer.RangeClose:
isRange := lo != 0 && hi != 0
isChars := chars != ""
if isChars == isRange {
return nil, tree, fmt.Errorf("could not parse range")
}
if isRange {
2016-05-30 19:35:53 +03:00
Insert(tree, NewNode(KindRange, &Range{
2016-05-27 20:47:19 +03:00
Lo: lo,
Hi: hi,
Not: not,
2016-05-30 19:35:53 +03:00
}))
2016-05-27 20:47:19 +03:00
} else {
2016-05-30 19:35:53 +03:00
Insert(tree, NewNode(KindList, &List{
2016-05-27 20:47:19 +03:00
Chars: chars,
Not: not,
2016-05-30 19:35:53 +03:00
}))
2016-05-27 20:47:19 +03:00
}
return parserMain, tree, nil
}
}
}