1 package gval
2
3 import (
4 "context"
5 "fmt"
6 "reflect"
7 "strconv"
8 "text/scanner"
9
10 "github.com/shopspring/decimal"
11 )
12
13
14 func (p *Parser) ParseExpression(c context.Context) (eval Evaluable, err error) {
15 stack := stageStack{}
16 for {
17 eval, err = p.ParseNextExpression(c)
18 if err != nil {
19 return nil, err
20 }
21
22 if stage, err := p.parseOperator(c, &stack, eval); err != nil {
23 return nil, err
24 } else if err = stack.push(stage); err != nil {
25 return nil, err
26 }
27
28 if stack.peek().infixBuilder == nil {
29 return stack.pop().Evaluable, nil
30 }
31 }
32 }
33
34
35 func (p *Parser) ParseNextExpression(c context.Context) (eval Evaluable, err error) {
36 scan := p.Scan()
37 ex, ok := p.prefixes[scan]
38 if !ok {
39 if scan != scanner.EOF && p.def != nil {
40 return p.def(c, p)
41 }
42 return nil, p.Expected("extensions")
43 }
44 return ex(c, p)
45 }
46
47
48
49 func (p *Parser) ParseSublanguage(c context.Context, l Language) (Evaluable, error) {
50 if p.isCamouflaged() {
51 panic("can not ParseSublanguage() on camouflaged Parser")
52 }
53 curLang := p.Language
54 curWhitespace := p.scanner.Whitespace
55 curMode := p.scanner.Mode
56 curIsIdentRune := p.scanner.IsIdentRune
57
58 p.Language = l
59 p.resetScannerProperties()
60
61 defer func() {
62 p.Language = curLang
63 p.scanner.Whitespace = curWhitespace
64 p.scanner.Mode = curMode
65 p.scanner.IsIdentRune = curIsIdentRune
66 }()
67
68 return p.parse(c)
69 }
70
71 func (p *Parser) parse(c context.Context) (Evaluable, error) {
72 if p.init != nil {
73 return p.init(c, p)
74 }
75
76 return p.ParseExpression(c)
77 }
78
79 func parseString(c context.Context, p *Parser) (Evaluable, error) {
80 s, err := strconv.Unquote(p.TokenText())
81 if err != nil {
82 return nil, fmt.Errorf("could not parse string: %w", err)
83 }
84 return p.Const(s), nil
85 }
86
87 func parseNumber(c context.Context, p *Parser) (Evaluable, error) {
88 n, err := strconv.ParseFloat(p.TokenText(), 64)
89 if err != nil {
90 return nil, err
91 }
92 return p.Const(n), nil
93 }
94
95 func parseDecimal(c context.Context, p *Parser) (Evaluable, error) {
96 n, err := strconv.ParseFloat(p.TokenText(), 64)
97 if err != nil {
98 return nil, err
99 }
100 return p.Const(decimal.NewFromFloat(n)), nil
101 }
102
103 func parseParentheses(c context.Context, p *Parser) (Evaluable, error) {
104 eval, err := p.ParseExpression(c)
105 if err != nil {
106 return nil, err
107 }
108 switch p.Scan() {
109 case ')':
110 return eval, nil
111 default:
112 return nil, p.Expected("parentheses", ')')
113 }
114 }
115
116 func (p *Parser) parseOperator(c context.Context, stack *stageStack, eval Evaluable) (st stage, err error) {
117 for {
118 scan := p.Scan()
119 op := p.TokenText()
120 mustOp := false
121 if p.isSymbolOperation(scan) {
122 scan = p.Peek()
123 for p.isSymbolOperation(scan) && p.isOperatorPrefix(op+string(scan)) {
124 mustOp = true
125 op += string(scan)
126 p.Next()
127 scan = p.Peek()
128 }
129 } else if scan != scanner.Ident {
130 p.Camouflage("operator")
131 return stage{Evaluable: eval}, nil
132 }
133 switch operator := p.operators[op].(type) {
134 case *infix:
135 return stage{
136 Evaluable: eval,
137 infixBuilder: operator.builder,
138 operatorPrecedence: operator.operatorPrecedence,
139 }, nil
140 case directInfix:
141 return stage{
142 Evaluable: eval,
143 infixBuilder: operator.infixBuilder,
144 operatorPrecedence: operator.operatorPrecedence,
145 }, nil
146 case postfix:
147 if err = stack.push(stage{
148 operatorPrecedence: operator.operatorPrecedence,
149 Evaluable: eval,
150 }); err != nil {
151 return stage{}, err
152 }
153 eval, err = operator.f(c, p, stack.pop().Evaluable, operator.operatorPrecedence)
154 if err != nil {
155 return
156 }
157 continue
158 }
159
160 if !mustOp {
161 p.Camouflage("operator")
162 return stage{Evaluable: eval}, nil
163 }
164 return stage{}, fmt.Errorf("unknown operator %s", op)
165 }
166 }
167
168 func parseIdent(c context.Context, p *Parser) (call string, alternative func() (Evaluable, error), err error) {
169 token := p.TokenText()
170 return token,
171 func() (Evaluable, error) {
172 fullname := token
173
174 keys := []Evaluable{p.Const(token)}
175 for {
176 scan := p.Scan()
177 switch scan {
178 case '.':
179 scan = p.Scan()
180 switch scan {
181 case scanner.Ident:
182 token = p.TokenText()
183 keys = append(keys, p.Const(token))
184 default:
185 return nil, p.Expected("field", scanner.Ident)
186 }
187 case '(':
188 args, err := p.parseArguments(c)
189 if err != nil {
190 return nil, err
191 }
192 return p.callEvaluable(fullname, p.Var(keys...), args...), nil
193 case '[':
194 key, err := p.ParseExpression(c)
195 if err != nil {
196 return nil, err
197 }
198 switch p.Scan() {
199 case ']':
200 keys = append(keys, key)
201 default:
202 return nil, p.Expected("array key", ']')
203 }
204 default:
205 p.Camouflage("variable", '.', '(', '[')
206 return p.Var(keys...), nil
207 }
208 }
209 }, nil
210
211 }
212
213 func (p *Parser) parseArguments(c context.Context) (args []Evaluable, err error) {
214 if p.Scan() == ')' {
215 return
216 }
217 p.Camouflage("scan arguments", ')')
218 for {
219 arg, err := p.ParseExpression(c)
220 args = append(args, arg)
221 if err != nil {
222 return nil, err
223 }
224 switch p.Scan() {
225 case ')':
226 return args, nil
227 case ',':
228 default:
229 return nil, p.Expected("arguments", ')', ',')
230 }
231 }
232 }
233
234 func inArray(a, b interface{}) (interface{}, error) {
235 col, ok := b.([]interface{})
236 if !ok {
237 return nil, fmt.Errorf("expected type []interface{} for in operator but got %T", b)
238 }
239 for _, value := range col {
240 if reflect.DeepEqual(a, value) {
241 return true, nil
242 }
243 }
244 return false, nil
245 }
246
247 func parseIf(c context.Context, p *Parser, e Evaluable) (Evaluable, error) {
248 a, err := p.ParseExpression(c)
249 if err != nil {
250 return nil, err
251 }
252 b := p.Const(nil)
253 switch p.Scan() {
254 case ':':
255 b, err = p.ParseExpression(c)
256 if err != nil {
257 return nil, err
258 }
259 case scanner.EOF:
260 default:
261 return nil, p.Expected("<> ? <> : <>", ':', scanner.EOF)
262 }
263 return func(c context.Context, v interface{}) (interface{}, error) {
264 x, err := e(c, v)
265 if err != nil {
266 return nil, err
267 }
268 if valX := reflect.ValueOf(x); x == nil || valX.IsZero() {
269 return b(c, v)
270 }
271 return a(c, v)
272 }, nil
273 }
274
275 func parseJSONArray(c context.Context, p *Parser) (Evaluable, error) {
276 evals := []Evaluable{}
277 for {
278 switch p.Scan() {
279 default:
280 p.Camouflage("array", ',', ']')
281 eval, err := p.ParseExpression(c)
282 if err != nil {
283 return nil, err
284 }
285 evals = append(evals, eval)
286 case ',':
287 case ']':
288 return func(c context.Context, v interface{}) (interface{}, error) {
289 vs := make([]interface{}, len(evals))
290 for i, e := range evals {
291 eval, err := e(c, v)
292 if err != nil {
293 return nil, err
294 }
295 vs[i] = eval
296 }
297
298 return vs, nil
299 }, nil
300 }
301 }
302 }
303
304 func parseJSONObject(c context.Context, p *Parser) (Evaluable, error) {
305 type kv struct {
306 key Evaluable
307 value Evaluable
308 }
309 evals := []kv{}
310 for {
311 switch p.Scan() {
312 default:
313 p.Camouflage("object", ',', '}')
314 key, err := p.ParseExpression(c)
315 if err != nil {
316 return nil, err
317 }
318 if p.Scan() != ':' {
319 if err != nil {
320 return nil, p.Expected("object", ':')
321 }
322 }
323 value, err := p.ParseExpression(c)
324 if err != nil {
325 return nil, err
326 }
327 evals = append(evals, kv{key, value})
328 case ',':
329 case '}':
330 return func(c context.Context, v interface{}) (interface{}, error) {
331 vs := map[string]interface{}{}
332 for _, e := range evals {
333 value, err := e.value(c, v)
334 if err != nil {
335 return nil, err
336 }
337 key, err := e.key.EvalString(c, v)
338 if err != nil {
339 return nil, err
340 }
341 vs[key] = value
342 }
343 return vs, nil
344 }, nil
345 }
346 }
347 }
348
View as plain text