1 package parse
2
3 import (
4 "errors"
5 )
6
7 var (
8
9 ErrBadSubstitution = errors.New("bad substitution")
10
11
12 ErrMissingClosingBrace = errors.New("missing closing brace")
13
14
15
16 ErrParseVariableName = errors.New("unable to parse variable name")
17
18
19
20 ErrParseFuncSubstitution = errors.New("unable to parse substitution within function")
21
22
23
24 ErrParseDefaultFunction = errors.New("unable to parse default function")
25 )
26
27
28 type Tree struct {
29 Root Node
30
31
32 scanner *scanner
33 }
34
35
36 func Parse(buf string) (*Tree, error) {
37 t := new(Tree)
38 t.scanner = new(scanner)
39 return t.Parse(buf)
40 }
41
42
43
44 func (t *Tree) Parse(buf string) (tree *Tree, err error) {
45 t.scanner.init(buf)
46 t.Root, err = t.parseAny()
47 return t, err
48 }
49
50 func (t *Tree) parseAny() (Node, error) {
51 t.scanner.accept = acceptRune
52 t.scanner.mode = scanIdent | scanLbrack | scanEscape
53 t.scanner.escapeChars = dollar
54
55 switch t.scanner.scan() {
56 case tokenIdent:
57 left := newTextNode(
58 t.scanner.string(),
59 )
60 right, err := t.parseAny()
61 switch {
62 case err != nil:
63 return nil, err
64 case right == empty:
65 return left, nil
66 }
67 return newListNode(left, right), nil
68 case tokenEOF:
69 return empty, nil
70 case tokenLbrack:
71 left, err := t.parseFunc()
72 if err != nil {
73 return nil, err
74 }
75
76 right, err := t.parseAny()
77 switch {
78 case err != nil:
79 return nil, err
80 case right == empty:
81 return left, nil
82 }
83 return newListNode(left, right), nil
84 }
85
86 return nil, ErrBadSubstitution
87 }
88
89 func (t *Tree) parseFunc() (Node, error) {
90
91 t.scanner.escapeChars = escapeAll
92 switch t.scanner.peek() {
93 case '#':
94 return t.parseLenFunc()
95 }
96
97 var name string
98 t.scanner.accept = acceptIdent
99 t.scanner.mode = scanIdent
100
101 switch t.scanner.scan() {
102 case tokenIdent:
103 name = t.scanner.string()
104 default:
105 return nil, ErrParseVariableName
106 }
107
108 switch t.scanner.peek() {
109 case ':':
110 return t.parseDefaultOrSubstr(name)
111 case '=':
112 return t.parseDefaultFunc(name)
113 case ',', '^':
114 return t.parseCasingFunc(name)
115 case '/':
116 return t.parseReplaceFunc(name)
117 case '#':
118 return t.parseRemoveFunc(name, acceptHashFunc)
119 case '%':
120 return t.parseRemoveFunc(name, acceptPercentFunc)
121 }
122
123 t.scanner.accept = acceptIdent
124 t.scanner.mode = scanRbrack
125 switch t.scanner.scan() {
126 case tokenRbrack:
127 return newFuncNode(name), nil
128 default:
129 return nil, ErrMissingClosingBrace
130 }
131 }
132
133
134 func (t *Tree) parseParam(accept acceptFunc, mode byte) (Node, error) {
135 t.scanner.accept = accept
136 t.scanner.mode = mode | scanLbrack
137 switch t.scanner.scan() {
138 case tokenLbrack:
139 return t.parseFunc()
140 case tokenIdent:
141 return newTextNode(
142 t.scanner.string(),
143 ), nil
144 case tokenRbrack:
145 return newTextNode(
146 t.scanner.string(),
147 ), nil
148 default:
149 return nil, ErrParseFuncSubstitution
150 }
151 }
152
153
154 func (t *Tree) parseDefaultOrSubstr(name string) (Node, error) {
155 t.scanner.read()
156 r := t.scanner.peek()
157 t.scanner.unread()
158 switch r {
159 case '=', '-', '?', '+':
160 return t.parseDefaultFunc(name)
161 default:
162 return t.parseSubstrFunc(name)
163 }
164 }
165
166
167
168 func (t *Tree) parseSubstrFunc(name string) (Node, error) {
169 node := new(FuncNode)
170 node.Param = name
171
172 t.scanner.accept = acceptOneColon
173 t.scanner.mode = scanIdent
174 switch t.scanner.scan() {
175 case tokenIdent:
176 node.Name = t.scanner.string()
177 default:
178 return nil, ErrBadSubstitution
179 }
180
181
182 {
183 param, err := t.parseParam(rejectColonClose, scanIdent)
184 if err != nil {
185 return nil, err
186 }
187
188
189 node.Args = append(node.Args, param)
190 }
191
192
193 t.scanner.accept = acceptColon
194 t.scanner.mode = scanIdent | scanRbrack
195 switch t.scanner.scan() {
196 case tokenRbrack:
197 return node, nil
198 case tokenIdent:
199
200 default:
201 return nil, ErrBadSubstitution
202 }
203
204
205 {
206 param, err := t.parseParam(acceptNotClosing, scanIdent)
207 if err != nil {
208 return nil, err
209 }
210 node.Args = append(node.Args, param)
211 }
212
213 return node, t.consumeRbrack()
214 }
215
216
217
218
219
220 func (t *Tree) parseRemoveFunc(name string, accept acceptFunc) (Node, error) {
221 node := new(FuncNode)
222 node.Param = name
223
224 t.scanner.accept = accept
225 t.scanner.mode = scanIdent
226 switch t.scanner.scan() {
227 case tokenIdent:
228 node.Name = t.scanner.string()
229 default:
230 return nil, ErrBadSubstitution
231 }
232
233
234 {
235 param, err := t.parseParam(acceptNotClosing, scanIdent)
236 if err != nil {
237 return nil, err
238 }
239
240
241 node.Args = append(node.Args, param)
242 }
243
244 return node, t.consumeRbrack()
245 }
246
247
248
249
250
251 func (t *Tree) parseReplaceFunc(name string) (Node, error) {
252 node := new(FuncNode)
253 node.Param = name
254
255 t.scanner.accept = acceptReplaceFunc
256 t.scanner.mode = scanIdent
257 switch t.scanner.scan() {
258 case tokenIdent:
259 node.Name = t.scanner.string()
260 default:
261 return nil, ErrBadSubstitution
262 }
263
264
265 {
266 param, err := t.parseParam(acceptNotSlash, scanIdent|scanEscape)
267 if err != nil {
268 return nil, err
269 }
270 node.Args = append(node.Args, param)
271 }
272
273
274 t.scanner.accept = acceptSlash
275 t.scanner.mode = scanIdent
276 switch t.scanner.scan() {
277 case tokenIdent:
278
279 default:
280 return nil, ErrBadSubstitution
281 }
282
283
284 switch t.scanner.peek() {
285 case '}':
286 return node, t.consumeRbrack()
287 }
288
289
290 {
291 param, err := t.parseParam(acceptNotClosing, scanIdent|scanEscape)
292 if err != nil {
293 return nil, err
294 }
295 node.Args = append(node.Args, param)
296 }
297
298 return node, t.consumeRbrack()
299 }
300
301
302
303
304
305
306 func (t *Tree) parseDefaultFunc(name string) (Node, error) {
307 node := new(FuncNode)
308 node.Param = name
309
310 t.scanner.accept = acceptDefaultFunc
311 if t.scanner.peek() == '=' {
312 t.scanner.accept = acceptOneEqual
313 }
314 t.scanner.mode = scanIdent
315 switch t.scanner.scan() {
316 case tokenIdent:
317 node.Name = t.scanner.string()
318 default:
319 return nil, ErrParseDefaultFunction
320 }
321
322
323 for {
324
325 switch t.scanner.peek() {
326 case '}':
327 return node, t.consumeRbrack()
328 }
329 param, err := t.parseParam(acceptNotClosing, scanIdent)
330 if err != nil {
331 return nil, err
332 }
333
334 node.Args = append(node.Args, param)
335 }
336 }
337
338
339
340
341
342 func (t *Tree) parseCasingFunc(name string) (Node, error) {
343 node := new(FuncNode)
344 node.Param = name
345
346 t.scanner.accept = acceptCasingFunc
347 t.scanner.mode = scanIdent
348 switch t.scanner.scan() {
349 case tokenIdent:
350 node.Name = t.scanner.string()
351 default:
352 return nil, ErrBadSubstitution
353 }
354
355 return node, t.consumeRbrack()
356 }
357
358
359 func (t *Tree) parseLenFunc() (Node, error) {
360 node := new(FuncNode)
361
362 t.scanner.accept = acceptOneHash
363 t.scanner.mode = scanIdent
364 switch t.scanner.scan() {
365 case tokenIdent:
366 node.Name = t.scanner.string()
367 default:
368 return nil, ErrBadSubstitution
369 }
370
371 t.scanner.accept = acceptIdent
372 t.scanner.mode = scanIdent
373 switch t.scanner.scan() {
374 case tokenIdent:
375 node.Param = t.scanner.string()
376 default:
377 return nil, ErrBadSubstitution
378 }
379
380 return node, t.consumeRbrack()
381 }
382
383
384
385 func (t *Tree) consumeRbrack() error {
386 t.scanner.mode = scanRbrack
387 if t.scanner.scan() != tokenRbrack {
388 return ErrBadSubstitution
389 }
390 return nil
391 }
392
393
394
395
396
397
398
399
400
401
402
403
View as plain text