123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- package ast
- import (
- "errors"
- "fmt"
- "github.com/gobwas/glob/syntax/lexer"
- "unicode/utf8"
- )
- type Lexer interface {
- Next() lexer.Token
- }
- type parseFn func(*Node, Lexer) (parseFn, *Node, error)
- func Parse(lexer Lexer) (*Node, error) {
- var parser parseFn
- root := NewNode(KindPattern, nil)
- var (
- tree *Node
- err error
- )
- for parser, tree = parserMain, root; parser != nil; {
- parser, tree, err = parser(tree, lexer)
- if err != nil {
- return nil, err
- }
- }
- return root, nil
- }
- func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) {
- 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:
- Insert(tree, NewNode(KindText, Text{token.Raw}))
- return parserMain, tree, nil
- case lexer.Any:
- Insert(tree, NewNode(KindAny, nil))
- return parserMain, tree, nil
- case lexer.Super:
- Insert(tree, NewNode(KindSuper, nil))
- return parserMain, tree, nil
- case lexer.Single:
- Insert(tree, NewNode(KindSingle, nil))
- return parserMain, tree, nil
- case lexer.RangeOpen:
- return parserRange, tree, nil
- case lexer.TermsOpen:
- a := NewNode(KindAnyOf, nil)
- Insert(tree, a)
- p := NewNode(KindPattern, nil)
- Insert(a, p)
- return parserMain, p, nil
- case lexer.Separator:
- p := NewNode(KindPattern, nil)
- Insert(tree.Parent, p)
- return parserMain, p, nil
- case lexer.TermsClose:
- return parserMain, tree.Parent.Parent, nil
- default:
- return nil, tree, fmt.Errorf("unexpected token: %s", token)
- }
- }
- return nil, tree, fmt.Errorf("unknown error")
- }
- func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) {
- 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 {
- Insert(tree, NewNode(KindRange, Range{
- Lo: lo,
- Hi: hi,
- Not: not,
- }))
- } else {
- Insert(tree, NewNode(KindList, List{
- Chars: chars,
- Not: not,
- }))
- }
- return parserMain, tree, nil
- }
- }
- }
|