1 package filtering
2
3 import (
4 "errors"
5 "fmt"
6 "io"
7 "strconv"
8 "strings"
9
10 expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
11 )
12
13
14 type Parser struct {
15 filter string
16 lexer Lexer
17 id int64
18 positions []int32
19 }
20
21
22 func (p *Parser) Init(filter string) {
23 filter = strings.TrimSpace(filter)
24 *p = Parser{
25 filter: filter,
26 positions: p.positions[:0],
27 id: -1,
28 }
29 p.lexer.Init(filter)
30 }
31
32
33 func (p *Parser) Parse() (*expr.ParsedExpr, error) {
34 e, err := p.ParseExpression()
35 if err != nil {
36 return nil, err
37 }
38 end := p.lexer.Position()
39 if token, err := p.lexer.Lex(); err != nil {
40 if !errors.Is(err, io.EOF) {
41 return nil, err
42 }
43 } else {
44 return nil, p.errorf(end, "unexpected trailing token %s", token.Type)
45 }
46 return &expr.ParsedExpr{
47 Expr: e,
48 SourceInfo: p.SourceInfo(),
49 }, nil
50 }
51
52 func (p *Parser) SourceInfo() *expr.SourceInfo {
53 positions := make(map[int64]int32, len(p.positions))
54 for id, position := range p.positions {
55 positions[int64(id)] = position
56 }
57 return &expr.SourceInfo{
58 LineOffsets: p.lexer.LineOffsets(),
59 Positions: positions,
60 }
61 }
62
63
64
65
66
67
68
69
70 func (p *Parser) ParseExpression() (_ *expr.Expr, err error) {
71 start := p.lexer.Position()
72 defer func() {
73 if err != nil {
74 err = p.wrapf(err, start, "expression")
75 }
76 }()
77 sequences := make([]*expr.Expr, 0, 1)
78 for {
79 _ = p.eatTokens(TokenTypeWhitespace)
80 sequence, err := p.ParseSequence()
81 if err != nil {
82 return nil, err
83 }
84 sequences = append(sequences, sequence)
85 if err := p.eatTokens(TokenTypeWhitespace, TokenTypeAnd, TokenTypeWhitespace); err != nil {
86 break
87 }
88 }
89 exp := sequences[0]
90 for _, seq := range sequences[1:] {
91 exp = parsedExpression(p.nextID(start), exp, seq)
92 }
93 return exp, nil
94 }
95
96
97
98
99
100
101
102
103 func (p *Parser) ParseSequence() (_ *expr.Expr, err error) {
104 start := p.lexer.Position()
105 defer func() {
106 if err != nil {
107 err = p.wrapf(err, start, "sequence")
108 }
109 }()
110 factors := make([]*expr.Expr, 0, 2)
111 for {
112 factor, err := p.ParseFactor()
113 if err != nil {
114 return nil, err
115 }
116 factors = append(factors, factor)
117 if p.sniffTokens(TokenTypeWhitespace, TokenTypeAnd) {
118 break
119 }
120 if err := p.eatTokens(TokenTypeWhitespace); err != nil {
121 break
122 }
123 }
124 if len(factors) == 1 {
125 return factors[0], nil
126 }
127 result := parsedSequence(p.nextID(start), factors[0], factors[1])
128 for _, factor := range factors[2:] {
129 result = parsedSequence(p.nextID(start), result, factor)
130 }
131 return result, nil
132 }
133
134
135
136
137
138
139
140
141 func (p *Parser) ParseFactor() (_ *expr.Expr, err error) {
142 start := p.lexer.Position()
143 defer func() {
144 if err != nil {
145 err = p.wrapf(err, start, "factor")
146 }
147 }()
148 terms := make([]*expr.Expr, 0, 2)
149 for {
150 term, err := p.ParseTerm()
151 if err != nil {
152 return nil, err
153 }
154 terms = append(terms, term)
155 if err := p.eatTokens(TokenTypeWhitespace, TokenTypeOr, TokenTypeWhitespace); err != nil {
156 break
157 }
158 }
159 if len(terms) == 1 {
160 return terms[0], nil
161 }
162 result := parsedFactor(p.nextID(start), terms[0], terms[1])
163 for _, factor := range terms[2:] {
164 result = parsedFactor(p.nextID(start), result, factor)
165 }
166 return result, nil
167 }
168
169
170
171
172
173
174
175
176 func (p *Parser) ParseTerm() (_ *expr.Expr, err error) {
177 start := p.lexer.Position()
178 defer func() {
179 if err != nil {
180 err = p.wrapf(err, start, "term")
181 }
182 }()
183 var not, minus bool
184 if err := p.eatTokens(TokenTypeNot, TokenTypeWhitespace); err == nil {
185 not = true
186 } else if err := p.eatTokens(TokenTypeMinus); err == nil {
187 minus = true
188 }
189 simple, err := p.ParseSimple()
190 if err != nil {
191 return nil, err
192 }
193 switch {
194 case not, minus:
195 if minus {
196
197 if constExpr, ok := simple.GetExprKind().(*expr.Expr_ConstExpr); ok {
198 switch constantKind := constExpr.ConstExpr.GetConstantKind().(type) {
199 case *expr.Constant_Int64Value:
200 constantKind.Int64Value *= -1
201 return simple, nil
202 case *expr.Constant_DoubleValue:
203 constantKind.DoubleValue *= -1
204 return simple, nil
205 }
206 }
207 }
208 return parsedFunction(p.nextID(start), FunctionNot, simple), nil
209 default:
210 return simple, nil
211 }
212 }
213
214
215
216
217
218
219
220
221
222 func (p *Parser) ParseSimple() (_ *expr.Expr, err error) {
223 start := p.lexer.Position()
224 defer func() {
225 if err != nil {
226 err = p.wrapf(err, start, "simple")
227 }
228 }()
229 if p.sniffTokens(TokenTypeLeftParen) {
230 return p.ParseComposite()
231 }
232 return p.ParseRestriction()
233 }
234
235
236
237
238
239
240
241
242 func (p *Parser) ParseRestriction() (_ *expr.Expr, err error) {
243 start := p.lexer.Position()
244 defer func() {
245 if err != nil {
246 err = p.wrapf(err, start, "restriction")
247 }
248 }()
249 comp, err := p.ParseComparable()
250 if err != nil {
251 return nil, err
252 }
253 if !(p.sniff(TokenType.IsComparator) || p.sniff(TokenTypeWhitespace.Test, TokenType.IsComparator)) {
254 return comp, nil
255 }
256 _ = p.eatTokens(TokenTypeWhitespace)
257 comparatorToken, err := p.parseToken(TokenType.IsComparator)
258 if err != nil {
259 return nil, err
260 }
261 _ = p.eatTokens(TokenTypeWhitespace)
262 arg, err := p.ParseArg()
263 if err != nil {
264 return nil, err
265 }
266
267 if comparatorToken.Type == TokenTypeHas && arg.GetIdentExpr() != nil {
268
269 arg = parsedString(arg.GetId(), arg.GetIdentExpr().GetName())
270 }
271 return parsedFunction(p.nextID(start), comparatorToken.Type.Function(), comp, arg), nil
272 }
273
274
275
276
277
278
279
280
281
282
283 func (p *Parser) ParseComparable() (_ *expr.Expr, err error) {
284 start := p.lexer.Position()
285 defer func() {
286 if err != nil {
287 err = p.wrapf(err, start, "comparable")
288 }
289 }()
290 if function, ok := p.TryParseFunction(); ok {
291 return function, nil
292 }
293 if number, ok := p.TryParseNumber(); ok {
294 return number, nil
295 }
296 return p.ParseMember()
297 }
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 func (p *Parser) ParseMember() (_ *expr.Expr, err error) {
318 start := p.lexer.Position()
319 defer func() {
320 if err != nil {
321 err = p.wrapf(err, start, "member")
322 }
323 }()
324 valueToken, err := p.parseToken(TokenType.IsValue)
325 if err != nil {
326 return nil, err
327 }
328 if !p.sniffTokens(TokenTypeDot) {
329 if valueToken.Type == TokenTypeString {
330 return parsedString(p.nextID(valueToken.Position), valueToken.Unquote()), nil
331 }
332 return parsedText(p.nextID(valueToken.Position), valueToken.Value), nil
333 }
334 value := parsedText(p.nextID(valueToken.Position), valueToken.Unquote())
335 _ = p.eatTokens(TokenTypeDot)
336 firstFieldToken, err := p.parseToken(TokenType.IsField)
337 if err != nil {
338 return nil, err
339 }
340 member := parsedMember(p.nextID(start), value, firstFieldToken.Unquote())
341 for {
342 if err := p.eatTokens(TokenTypeDot); err != nil {
343 break
344 }
345 fieldToken, err := p.parseToken(TokenType.IsField)
346 if err != nil {
347 return nil, err
348 }
349 member = parsedMember(p.nextID(start), member, fieldToken.Unquote())
350 }
351 return member, nil
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366 func (p *Parser) ParseFunction() (_ *expr.Expr, err error) {
367 start := p.lexer.Position()
368 defer func() {
369 if err != nil {
370 err = p.wrapf(err, start, "function")
371 }
372 }()
373 var name strings.Builder
374 for {
375 nameToken, err := p.parseToken(TokenType.IsName)
376 if err != nil {
377 return nil, err
378 }
379 _, _ = name.WriteString(nameToken.Unquote())
380 if err := p.eatTokens(TokenTypeDot); err != nil {
381 break
382 }
383 _ = name.WriteByte('.')
384 }
385 if err := p.eatTokens(TokenTypeLeftParen); err != nil {
386 return nil, err
387 }
388 _ = p.eatTokens(TokenTypeWhitespace)
389 args := make([]*expr.Expr, 0)
390 for !p.sniffTokens(TokenTypeRightParen) {
391 arg, err := p.ParseArg()
392 if err != nil {
393 return nil, err
394 }
395 args = append(args, arg)
396 _ = p.eatTokens(TokenTypeWhitespace)
397 if err := p.eatTokens(TokenTypeComma); err != nil {
398 break
399 }
400 _ = p.eatTokens(TokenTypeWhitespace)
401 }
402 _ = p.eatTokens(TokenTypeWhitespace)
403 if err := p.eatTokens(TokenTypeRightParen); err != nil {
404 return nil, err
405 }
406 return parsedFunction(p.nextID(start), name.String(), args...), nil
407 }
408
409 func (p *Parser) TryParseFunction() (*expr.Expr, bool) {
410 start := *p
411 function, err := p.ParseFunction()
412 if err != nil {
413 *p = start
414 return nil, false
415 }
416 return function, true
417 }
418
419
420
421
422
423
424
425
426 func (p *Parser) ParseComposite() (_ *expr.Expr, err error) {
427 start := p.lexer.Position()
428 defer func() {
429 if err != nil {
430 err = p.wrapf(err, start, "composite")
431 }
432 }()
433 if err := p.eatTokens(TokenTypeLeftParen); err != nil {
434 return nil, err
435 }
436 _ = p.eatTokens(TokenTypeWhitespace)
437 expression, err := p.ParseExpression()
438 if err != nil {
439 return nil, err
440 }
441 _ = p.eatTokens(TokenTypeWhitespace)
442 if err := p.eatTokens(TokenTypeRightParen); err != nil {
443 return nil, err
444 }
445 return expression, nil
446 }
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465 func (p *Parser) ParseNumber() (_ *expr.Expr, err error) {
466 start := p.lexer.Position()
467 defer func() {
468 if err != nil {
469 err = p.wrapf(err, start, "number")
470 }
471 }()
472 if float, ok := p.TryParseFloat(); ok {
473 return float, nil
474 }
475 return p.ParseInt()
476 }
477
478 func (p *Parser) TryParseNumber() (*expr.Expr, bool) {
479 start := *p
480 result, err := p.ParseNumber()
481 if err != nil {
482 *p = start
483 return nil, false
484 }
485 return result, true
486 }
487
488
489
490
491
492
493
494
495 func (p *Parser) ParseFloat() (_ *expr.Expr, err error) {
496 start := p.lexer.Position()
497 defer func() {
498 if err != nil {
499 err = p.wrapf(err, start, "float")
500 }
501 }()
502 var minusToken Token
503 if p.sniffTokens(TokenTypeMinus) {
504 minusToken, _ = p.lexer.Lex()
505 }
506 var intToken Token
507 var hasIntToken bool
508 if p.sniffTokens(TokenTypeNumber) {
509 intToken, err = p.lexer.Lex()
510 if err != nil {
511 return nil, err
512 }
513 hasIntToken = true
514 }
515 dotToken, err := p.parseToken(TokenTypeDot.Test)
516 if err != nil {
517 return nil, err
518 }
519 var fractionToken Token
520 var hasFractionToken bool
521 if p.sniffTokens(TokenTypeNumber) {
522 fractionToken, err = p.lexer.Lex()
523 if err != nil {
524 return nil, err
525 }
526 hasFractionToken = true
527 }
528
529 if !hasFractionToken && !hasIntToken {
530 return nil, p.errorf(start, "expected int or fraction")
531 }
532 var stringValue strings.Builder
533 stringValue.Grow(
534 len(minusToken.Value) + len(intToken.Value) + len(dotToken.Value) + len(fractionToken.Value),
535 )
536 _, _ = stringValue.WriteString(minusToken.Value)
537 _, _ = stringValue.WriteString(intToken.Value)
538 _, _ = stringValue.WriteString(dotToken.Value)
539 _, _ = stringValue.WriteString(fractionToken.Value)
540 floatValue, err := strconv.ParseFloat(stringValue.String(), 64)
541 if err != nil {
542 return nil, err
543 }
544 return parsedFloat(p.nextID(start), floatValue), nil
545 }
546
547 func (p *Parser) TryParseFloat() (*expr.Expr, bool) {
548 start := *p
549 result, err := p.ParseFloat()
550 if err != nil {
551 *p = start
552 return nil, false
553 }
554 return result, true
555 }
556
557
558
559
560
561
562
563
564
565 func (p *Parser) ParseInt() (_ *expr.Expr, err error) {
566 start := p.lexer.Position()
567 defer func() {
568 if err != nil {
569 err = p.wrapf(err, start, "int")
570 }
571 }()
572 minus := p.eatTokens(TokenTypeMinus) == nil
573 token, err := p.parseToken(TokenTypeNumber.Test, TokenTypeHexNumber.Test)
574 if err != nil {
575 return nil, err
576 }
577 intValue, err := strconv.ParseInt(token.Value, 0, 64)
578 if err != nil {
579 return nil, err
580 }
581 if minus {
582 intValue *= -1
583 }
584 return parsedInt(p.nextID(start), intValue), nil
585 }
586
587
588
589
590
591
592
593
594
595 func (p *Parser) ParseArg() (_ *expr.Expr, err error) {
596 start := p.lexer.Position()
597 defer func() {
598 if err != nil {
599 err = p.wrapf(err, start, "arg")
600 }
601 }()
602 if p.sniffTokens(TokenTypeLeftParen) {
603 return p.ParseComposite()
604 }
605 return p.ParseComparable()
606 }
607
608 func (p *Parser) parseToken(fns ...func(TokenType) bool) (Token, error) {
609 start := p.lexer.Position()
610 token, err := p.lexer.Lex()
611 if err != nil {
612 return Token{}, p.wrapf(err, start, "parse token")
613 }
614 for _, fn := range fns {
615 if fn(token.Type) {
616 return token, nil
617 }
618 }
619 return Token{}, p.errorf(token.Position, "unexpected token %s", token.Type)
620 }
621
622 func (p *Parser) sniff(fns ...func(TokenType) bool) bool {
623 start := *p
624 defer func() {
625 *p = start
626 }()
627 for _, fn := range fns {
628 if token, err := p.lexer.Lex(); err != nil || !fn(token.Type) {
629 return false
630 }
631 }
632 return true
633 }
634
635 func (p *Parser) sniffTokens(wantTokenTypes ...TokenType) bool {
636 start := *p
637 defer func() {
638 *p = start
639 }()
640 for _, wantTokenType := range wantTokenTypes {
641 if token, err := p.lexer.Lex(); err != nil || token.Type != wantTokenType {
642 return false
643 }
644 }
645 return true
646 }
647
648 func (p *Parser) eatTokens(wantTokenTypes ...TokenType) error {
649 start := *p
650 for _, wantTokenType := range wantTokenTypes {
651 if token, err := p.lexer.Lex(); err != nil || token.Type != wantTokenType {
652 *p = start
653 return p.errorf(start.lexer.Position(), "expected %s", wantTokenType)
654 }
655 }
656 return nil
657 }
658
659 func (p *Parser) errorf(position Position, format string, args ...interface{}) error {
660 return &parseError{
661 filter: p.filter,
662 position: position,
663 message: fmt.Sprintf(format, args...),
664 }
665 }
666
667 func (p *Parser) wrapf(err error, position Position, format string, args ...interface{}) error {
668 return &parseError{
669 filter: p.filter,
670 position: position,
671 message: fmt.Sprintf(format, args...),
672 err: err,
673 }
674 }
675
676 func (p *Parser) nextID(position Position) int64 {
677 p.id++
678 p.positions = append(p.positions, position.Offset)
679 return p.id
680 }
681
View as plain text