forked from sgarciac/fuego
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.go
99 lines (87 loc) · 2.5 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package main
import (
"github.com/alecthomas/participle"
"github.com/alecthomas/participle/lexer"
"strings"
"time"
)
// Queries grammar (It is probably overkill to use a parser generator)
// Boolean is an alias for bool.
type Boolean bool
// DateTime is an alias for time.Time
type DateTime time.Time
// Capture a bool
func (b *Boolean) Capture(values []string) error {
*b = strings.ToUpper(values[0]) == "TRUE"
return nil
}
// Capture a timestamp.Timestamp
func (t *DateTime) Capture(values []string) error {
ttime, _ := time.Parse(time.RFC3339, values[0])
*t = DateTime(ttime)
return nil
}
type Firestorefieldpath struct {
Key []string `@(SimpleFieldPath | String)(Dot @(SimpleFieldPath | String))*`
}
type Firestorequery struct {
// Must take care of the "in" operator.
Key []string `@(SimpleFieldPath | String | "in")(Dot @(SimpleFieldPath | String | "in"))*`
Operator string `@Operator`
Value *Firestorevalue `@@`
}
type Firestorevalue struct {
String *string ` @String`
Number *float64 `| @Number`
DateTime *DateTime `| @DateTime`
Boolean *Boolean `| @("true" | "false" | "TRUE" | "FALSE")`
List []*Firestorevalue `| "[" {@@} "]"`
}
func (value *Firestorevalue) get() interface{} {
if value.String != nil {
return *value.String
} else if value.Number != nil {
return *value.Number
} else if value.DateTime != nil {
return time.Time(*value.DateTime)
} else if value.Boolean != nil {
return !!*value.Boolean
} else {
list := []interface{}{}
for _, item := range value.List {
list = append(list, item.get())
}
return list
}
}
func getQueryParser() *participle.Parser {
queryLexer := lexer.Must(lexer.Regexp(`(\s+)` +
`|(?P<DateTime>` + rfc3339pattern + `)` +
`|(?P<Operator><=|>=|<|>|==|in|array-contains-any|array-contains)` +
`|(?P<SimpleFieldPath>[a-zA-Z_][a-zA-Z0-9_]*)` +
`|(?P<Number>[-+]?\d*\.?\d+)` +
`|(?P<OpenList>\[)` +
`|(?P<CloseList>\])` +
`|(?P<String>('[^']*')|("((\\")|[^"])*"))` +
`|(?P<Dot>\.)`,
))
parser := participle.MustBuild(
&Firestorequery{},
participle.Lexer(queryLexer),
participle.Unquote("String"),
)
return parser
}
func getFieldPathParser() *participle.Parser {
queryLexer := lexer.Must(lexer.Regexp(`(\s+)` +
`|(?P<SimpleFieldPath>[a-zA-Z_][a-zA-Z0-9_]*)` +
`|(?P<String>('[^']*')|("((\\")|[^"])*"))` +
`|(?P<Dot>\.)`,
))
parser := participle.MustBuild(
&Firestorefieldpath{},
participle.Lexer(queryLexer),
participle.Unquote("String"),
)
return parser
}