1 package ast
2
3 import (
4 "errors"
5 "fmt"
6 "github.com/gobwas/glob/syntax/lexer"
7 "unicode/utf8"
8 )
9
10 type Lexer interface {
11 Next() lexer.Token
12 }
13
14 type parseFn func(*Node, Lexer) (parseFn, *Node, error)
15
16 func Parse(lexer Lexer) (*Node, error) {
17 var parser parseFn
18
19 root := NewNode(KindPattern, nil)
20
21 var (
22 tree *Node
23 err error
24 )
25 for parser, tree = parserMain, root; parser != nil; {
26 parser, tree, err = parser(tree, lexer)
27 if err != nil {
28 return nil, err
29 }
30 }
31
32 return root, nil
33 }
34
35 func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) {
36 for {
37 token := lex.Next()
38 switch token.Type {
39 case lexer.EOF:
40 return nil, tree, nil
41
42 case lexer.Error:
43 return nil, tree, errors.New(token.Raw)
44
45 case lexer.Text:
46 Insert(tree, NewNode(KindText, Text{token.Raw}))
47 return parserMain, tree, nil
48
49 case lexer.Any:
50 Insert(tree, NewNode(KindAny, nil))
51 return parserMain, tree, nil
52
53 case lexer.Super:
54 Insert(tree, NewNode(KindSuper, nil))
55 return parserMain, tree, nil
56
57 case lexer.Single:
58 Insert(tree, NewNode(KindSingle, nil))
59 return parserMain, tree, nil
60
61 case lexer.RangeOpen:
62 return parserRange, tree, nil
63
64 case lexer.TermsOpen:
65 a := NewNode(KindAnyOf, nil)
66 Insert(tree, a)
67
68 p := NewNode(KindPattern, nil)
69 Insert(a, p)
70
71 return parserMain, p, nil
72
73 case lexer.Separator:
74 p := NewNode(KindPattern, nil)
75 Insert(tree.Parent, p)
76
77 return parserMain, p, nil
78
79 case lexer.TermsClose:
80 return parserMain, tree.Parent.Parent, nil
81
82 default:
83 return nil, tree, fmt.Errorf("unexpected token: %s", token)
84 }
85 }
86 return nil, tree, fmt.Errorf("unknown error")
87 }
88
89 func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) {
90 var (
91 not bool
92 lo rune
93 hi rune
94 chars string
95 )
96 for {
97 token := lex.Next()
98 switch token.Type {
99 case lexer.EOF:
100 return nil, tree, errors.New("unexpected end")
101
102 case lexer.Error:
103 return nil, tree, errors.New(token.Raw)
104
105 case lexer.Not:
106 not = true
107
108 case lexer.RangeLo:
109 r, w := utf8.DecodeRuneInString(token.Raw)
110 if len(token.Raw) > w {
111 return nil, tree, fmt.Errorf("unexpected length of lo character")
112 }
113 lo = r
114
115 case lexer.RangeBetween:
116
117
118 case lexer.RangeHi:
119 r, w := utf8.DecodeRuneInString(token.Raw)
120 if len(token.Raw) > w {
121 return nil, tree, fmt.Errorf("unexpected length of lo character")
122 }
123
124 hi = r
125
126 if hi < lo {
127 return nil, tree, fmt.Errorf("hi character '%s' should be greater than lo '%s'", string(hi), string(lo))
128 }
129
130 case lexer.Text:
131 chars = token.Raw
132
133 case lexer.RangeClose:
134 isRange := lo != 0 && hi != 0
135 isChars := chars != ""
136
137 if isChars == isRange {
138 return nil, tree, fmt.Errorf("could not parse range")
139 }
140
141 if isRange {
142 Insert(tree, NewNode(KindRange, Range{
143 Lo: lo,
144 Hi: hi,
145 Not: not,
146 }))
147 } else {
148 Insert(tree, NewNode(KindList, List{
149 Chars: chars,
150 Not: not,
151 }))
152 }
153
154 return parserMain, tree, nil
155 }
156 }
157 }
158
View as plain text