aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/jmespath/go-jmespath
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/jmespath/go-jmespath')
-rw-r--r--vendor/github.com/jmespath/go-jmespath/LICENSE13
-rw-r--r--vendor/github.com/jmespath/go-jmespath/Makefile44
-rw-r--r--vendor/github.com/jmespath/go-jmespath/README.md7
-rw-r--r--vendor/github.com/jmespath/go-jmespath/api.go49
-rw-r--r--vendor/github.com/jmespath/go-jmespath/astnodetype_string.go16
-rw-r--r--vendor/github.com/jmespath/go-jmespath/functions.go842
-rw-r--r--vendor/github.com/jmespath/go-jmespath/interpreter.go418
-rw-r--r--vendor/github.com/jmespath/go-jmespath/lexer.go420
-rw-r--r--vendor/github.com/jmespath/go-jmespath/parser.go603
-rw-r--r--vendor/github.com/jmespath/go-jmespath/toktype_string.go16
-rw-r--r--vendor/github.com/jmespath/go-jmespath/util.go185
11 files changed, 2613 insertions, 0 deletions
diff --git a/vendor/github.com/jmespath/go-jmespath/LICENSE b/vendor/github.com/jmespath/go-jmespath/LICENSE
new file mode 100644
index 0000000..b03310a
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/LICENSE
@@ -0,0 +1,13 @@
1Copyright 2015 James Saryerwinnie
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
diff --git a/vendor/github.com/jmespath/go-jmespath/Makefile b/vendor/github.com/jmespath/go-jmespath/Makefile
new file mode 100644
index 0000000..a828d28
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/Makefile
@@ -0,0 +1,44 @@
1
2CMD = jpgo
3
4help:
5 @echo "Please use \`make <target>' where <target> is one of"
6 @echo " test to run all the tests"
7 @echo " build to build the library and jp executable"
8 @echo " generate to run codegen"
9
10
11generate:
12 go generate ./...
13
14build:
15 rm -f $(CMD)
16 go build ./...
17 rm -f cmd/$(CMD)/$(CMD) && cd cmd/$(CMD)/ && go build ./...
18 mv cmd/$(CMD)/$(CMD) .
19
20test:
21 go test -v ./...
22
23check:
24 go vet ./...
25 @echo "golint ./..."
26 @lint=`golint ./...`; \
27 lint=`echo "$$lint" | grep -v "astnodetype_string.go" | grep -v "toktype_string.go"`; \
28 echo "$$lint"; \
29 if [ "$$lint" != "" ]; then exit 1; fi
30
31htmlc:
32 go test -coverprofile="/tmp/jpcov" && go tool cover -html="/tmp/jpcov" && unlink /tmp/jpcov
33
34buildfuzz:
35 go-fuzz-build github.com/jmespath/go-jmespath/fuzz
36
37fuzz: buildfuzz
38 go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/testdata
39
40bench:
41 go test -bench . -cpuprofile cpu.out
42
43pprof-cpu:
44 go tool pprof ./go-jmespath.test ./cpu.out
diff --git a/vendor/github.com/jmespath/go-jmespath/README.md b/vendor/github.com/jmespath/go-jmespath/README.md
new file mode 100644
index 0000000..187ef67
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/README.md
@@ -0,0 +1,7 @@
1# go-jmespath - A JMESPath implementation in Go
2
3[![Build Status](https://img.shields.io/travis/jmespath/go-jmespath.svg)](https://travis-ci.org/jmespath/go-jmespath)
4
5
6
7See http://jmespath.org for more info.
diff --git a/vendor/github.com/jmespath/go-jmespath/api.go b/vendor/github.com/jmespath/go-jmespath/api.go
new file mode 100644
index 0000000..9cfa988
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/api.go
@@ -0,0 +1,49 @@
1package jmespath
2
3import "strconv"
4
5// JmesPath is the epresentation of a compiled JMES path query. A JmesPath is
6// safe for concurrent use by multiple goroutines.
7type JMESPath struct {
8 ast ASTNode
9 intr *treeInterpreter
10}
11
12// Compile parses a JMESPath expression and returns, if successful, a JMESPath
13// object that can be used to match against data.
14func Compile(expression string) (*JMESPath, error) {
15 parser := NewParser()
16 ast, err := parser.Parse(expression)
17 if err != nil {
18 return nil, err
19 }
20 jmespath := &JMESPath{ast: ast, intr: newInterpreter()}
21 return jmespath, nil
22}
23
24// MustCompile is like Compile but panics if the expression cannot be parsed.
25// It simplifies safe initialization of global variables holding compiled
26// JMESPaths.
27func MustCompile(expression string) *JMESPath {
28 jmespath, err := Compile(expression)
29 if err != nil {
30 panic(`jmespath: Compile(` + strconv.Quote(expression) + `): ` + err.Error())
31 }
32 return jmespath
33}
34
35// Search evaluates a JMESPath expression against input data and returns the result.
36func (jp *JMESPath) Search(data interface{}) (interface{}, error) {
37 return jp.intr.Execute(jp.ast, data)
38}
39
40// Search evaluates a JMESPath expression against input data and returns the result.
41func Search(expression string, data interface{}) (interface{}, error) {
42 intr := newInterpreter()
43 parser := NewParser()
44 ast, err := parser.Parse(expression)
45 if err != nil {
46 return nil, err
47 }
48 return intr.Execute(ast, data)
49}
diff --git a/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go b/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go
new file mode 100644
index 0000000..1cd2d23
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/astnodetype_string.go
@@ -0,0 +1,16 @@
1// generated by stringer -type astNodeType; DO NOT EDIT
2
3package jmespath
4
5import "fmt"
6
7const _astNodeType_name = "ASTEmptyASTComparatorASTCurrentNodeASTExpRefASTFunctionExpressionASTFieldASTFilterProjectionASTFlattenASTIdentityASTIndexASTIndexExpressionASTKeyValPairASTLiteralASTMultiSelectHashASTMultiSelectListASTOrExpressionASTAndExpressionASTNotExpressionASTPipeASTProjectionASTSubexpressionASTSliceASTValueProjection"
8
9var _astNodeType_index = [...]uint16{0, 8, 21, 35, 44, 65, 73, 92, 102, 113, 121, 139, 152, 162, 180, 198, 213, 229, 245, 252, 265, 281, 289, 307}
10
11func (i astNodeType) String() string {
12 if i < 0 || i >= astNodeType(len(_astNodeType_index)-1) {
13 return fmt.Sprintf("astNodeType(%d)", i)
14 }
15 return _astNodeType_name[_astNodeType_index[i]:_astNodeType_index[i+1]]
16}
diff --git a/vendor/github.com/jmespath/go-jmespath/functions.go b/vendor/github.com/jmespath/go-jmespath/functions.go
new file mode 100644
index 0000000..9b7cd89
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/functions.go
@@ -0,0 +1,842 @@
1package jmespath
2
3import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "math"
8 "reflect"
9 "sort"
10 "strconv"
11 "strings"
12 "unicode/utf8"
13)
14
15type jpFunction func(arguments []interface{}) (interface{}, error)
16
17type jpType string
18
19const (
20 jpUnknown jpType = "unknown"
21 jpNumber jpType = "number"
22 jpString jpType = "string"
23 jpArray jpType = "array"
24 jpObject jpType = "object"
25 jpArrayNumber jpType = "array[number]"
26 jpArrayString jpType = "array[string]"
27 jpExpref jpType = "expref"
28 jpAny jpType = "any"
29)
30
31type functionEntry struct {
32 name string
33 arguments []argSpec
34 handler jpFunction
35 hasExpRef bool
36}
37
38type argSpec struct {
39 types []jpType
40 variadic bool
41}
42
43type byExprString struct {
44 intr *treeInterpreter
45 node ASTNode
46 items []interface{}
47 hasError bool
48}
49
50func (a *byExprString) Len() int {
51 return len(a.items)
52}
53func (a *byExprString) Swap(i, j int) {
54 a.items[i], a.items[j] = a.items[j], a.items[i]
55}
56func (a *byExprString) Less(i, j int) bool {
57 first, err := a.intr.Execute(a.node, a.items[i])
58 if err != nil {
59 a.hasError = true
60 // Return a dummy value.
61 return true
62 }
63 ith, ok := first.(string)
64 if !ok {
65 a.hasError = true
66 return true
67 }
68 second, err := a.intr.Execute(a.node, a.items[j])
69 if err != nil {
70 a.hasError = true
71 // Return a dummy value.
72 return true
73 }
74 jth, ok := second.(string)
75 if !ok {
76 a.hasError = true
77 return true
78 }
79 return ith < jth
80}
81
82type byExprFloat struct {
83 intr *treeInterpreter
84 node ASTNode
85 items []interface{}
86 hasError bool
87}
88
89func (a *byExprFloat) Len() int {
90 return len(a.items)
91}
92func (a *byExprFloat) Swap(i, j int) {
93 a.items[i], a.items[j] = a.items[j], a.items[i]
94}
95func (a *byExprFloat) Less(i, j int) bool {
96 first, err := a.intr.Execute(a.node, a.items[i])
97 if err != nil {
98 a.hasError = true
99 // Return a dummy value.
100 return true
101 }
102 ith, ok := first.(float64)
103 if !ok {
104 a.hasError = true
105 return true
106 }
107 second, err := a.intr.Execute(a.node, a.items[j])
108 if err != nil {
109 a.hasError = true
110 // Return a dummy value.
111 return true
112 }
113 jth, ok := second.(float64)
114 if !ok {
115 a.hasError = true
116 return true
117 }
118 return ith < jth
119}
120
121type functionCaller struct {
122 functionTable map[string]functionEntry
123}
124
125func newFunctionCaller() *functionCaller {
126 caller := &functionCaller{}
127 caller.functionTable = map[string]functionEntry{
128 "length": {
129 name: "length",
130 arguments: []argSpec{
131 {types: []jpType{jpString, jpArray, jpObject}},
132 },
133 handler: jpfLength,
134 },
135 "starts_with": {
136 name: "starts_with",
137 arguments: []argSpec{
138 {types: []jpType{jpString}},
139 {types: []jpType{jpString}},
140 },
141 handler: jpfStartsWith,
142 },
143 "abs": {
144 name: "abs",
145 arguments: []argSpec{
146 {types: []jpType{jpNumber}},
147 },
148 handler: jpfAbs,
149 },
150 "avg": {
151 name: "avg",
152 arguments: []argSpec{
153 {types: []jpType{jpArrayNumber}},
154 },
155 handler: jpfAvg,
156 },
157 "ceil": {
158 name: "ceil",
159 arguments: []argSpec{
160 {types: []jpType{jpNumber}},
161 },
162 handler: jpfCeil,
163 },
164 "contains": {
165 name: "contains",
166 arguments: []argSpec{
167 {types: []jpType{jpArray, jpString}},
168 {types: []jpType{jpAny}},
169 },
170 handler: jpfContains,
171 },
172 "ends_with": {
173 name: "ends_with",
174 arguments: []argSpec{
175 {types: []jpType{jpString}},
176 {types: []jpType{jpString}},
177 },
178 handler: jpfEndsWith,
179 },
180 "floor": {
181 name: "floor",
182 arguments: []argSpec{
183 {types: []jpType{jpNumber}},
184 },
185 handler: jpfFloor,
186 },
187 "map": {
188 name: "amp",
189 arguments: []argSpec{
190 {types: []jpType{jpExpref}},
191 {types: []jpType{jpArray}},
192 },
193 handler: jpfMap,
194 hasExpRef: true,
195 },
196 "max": {
197 name: "max",
198 arguments: []argSpec{
199 {types: []jpType{jpArrayNumber, jpArrayString}},
200 },
201 handler: jpfMax,
202 },
203 "merge": {
204 name: "merge",
205 arguments: []argSpec{
206 {types: []jpType{jpObject}, variadic: true},
207 },
208 handler: jpfMerge,
209 },
210 "max_by": {
211 name: "max_by",
212 arguments: []argSpec{
213 {types: []jpType{jpArray}},
214 {types: []jpType{jpExpref}},
215 },
216 handler: jpfMaxBy,
217 hasExpRef: true,
218 },
219 "sum": {
220 name: "sum",
221 arguments: []argSpec{
222 {types: []jpType{jpArrayNumber}},
223 },
224 handler: jpfSum,
225 },
226 "min": {
227 name: "min",
228 arguments: []argSpec{
229 {types: []jpType{jpArrayNumber, jpArrayString}},
230 },
231 handler: jpfMin,
232 },
233 "min_by": {
234 name: "min_by",
235 arguments: []argSpec{
236 {types: []jpType{jpArray}},
237 {types: []jpType{jpExpref}},
238 },
239 handler: jpfMinBy,
240 hasExpRef: true,
241 },
242 "type": {
243 name: "type",
244 arguments: []argSpec{
245 {types: []jpType{jpAny}},
246 },
247 handler: jpfType,
248 },
249 "keys": {
250 name: "keys",
251 arguments: []argSpec{
252 {types: []jpType{jpObject}},
253 },
254 handler: jpfKeys,
255 },
256 "values": {
257 name: "values",
258 arguments: []argSpec{
259 {types: []jpType{jpObject}},
260 },
261 handler: jpfValues,
262 },
263 "sort": {
264 name: "sort",
265 arguments: []argSpec{
266 {types: []jpType{jpArrayString, jpArrayNumber}},
267 },
268 handler: jpfSort,
269 },
270 "sort_by": {
271 name: "sort_by",
272 arguments: []argSpec{
273 {types: []jpType{jpArray}},
274 {types: []jpType{jpExpref}},
275 },
276 handler: jpfSortBy,
277 hasExpRef: true,
278 },
279 "join": {
280 name: "join",
281 arguments: []argSpec{
282 {types: []jpType{jpString}},
283 {types: []jpType{jpArrayString}},
284 },
285 handler: jpfJoin,
286 },
287 "reverse": {
288 name: "reverse",
289 arguments: []argSpec{
290 {types: []jpType{jpArray, jpString}},
291 },
292 handler: jpfReverse,
293 },
294 "to_array": {
295 name: "to_array",
296 arguments: []argSpec{
297 {types: []jpType{jpAny}},
298 },
299 handler: jpfToArray,
300 },
301 "to_string": {
302 name: "to_string",
303 arguments: []argSpec{
304 {types: []jpType{jpAny}},
305 },
306 handler: jpfToString,
307 },
308 "to_number": {
309 name: "to_number",
310 arguments: []argSpec{
311 {types: []jpType{jpAny}},
312 },
313 handler: jpfToNumber,
314 },
315 "not_null": {
316 name: "not_null",
317 arguments: []argSpec{
318 {types: []jpType{jpAny}, variadic: true},
319 },
320 handler: jpfNotNull,
321 },
322 }
323 return caller
324}
325
326func (e *functionEntry) resolveArgs(arguments []interface{}) ([]interface{}, error) {
327 if len(e.arguments) == 0 {
328 return arguments, nil
329 }
330 if !e.arguments[len(e.arguments)-1].variadic {
331 if len(e.arguments) != len(arguments) {
332 return nil, errors.New("incorrect number of args")
333 }
334 for i, spec := range e.arguments {
335 userArg := arguments[i]
336 err := spec.typeCheck(userArg)
337 if err != nil {
338 return nil, err
339 }
340 }
341 return arguments, nil
342 }
343 if len(arguments) < len(e.arguments) {
344 return nil, errors.New("Invalid arity.")
345 }
346 return arguments, nil
347}
348
349func (a *argSpec) typeCheck(arg interface{}) error {
350 for _, t := range a.types {
351 switch t {
352 case jpNumber:
353 if _, ok := arg.(float64); ok {
354 return nil
355 }
356 case jpString:
357 if _, ok := arg.(string); ok {
358 return nil
359 }
360 case jpArray:
361 if isSliceType(arg) {
362 return nil
363 }
364 case jpObject:
365 if _, ok := arg.(map[string]interface{}); ok {
366 return nil
367 }
368 case jpArrayNumber:
369 if _, ok := toArrayNum(arg); ok {
370 return nil
371 }
372 case jpArrayString:
373 if _, ok := toArrayStr(arg); ok {
374 return nil
375 }
376 case jpAny:
377 return nil
378 case jpExpref:
379 if _, ok := arg.(expRef); ok {
380 return nil
381 }
382 }
383 }
384 return fmt.Errorf("Invalid type for: %v, expected: %#v", arg, a.types)
385}
386
387func (f *functionCaller) CallFunction(name string, arguments []interface{}, intr *treeInterpreter) (interface{}, error) {
388 entry, ok := f.functionTable[name]
389 if !ok {
390 return nil, errors.New("unknown function: " + name)
391 }
392 resolvedArgs, err := entry.resolveArgs(arguments)
393 if err != nil {
394 return nil, err
395 }
396 if entry.hasExpRef {
397 var extra []interface{}
398 extra = append(extra, intr)
399 resolvedArgs = append(extra, resolvedArgs...)
400 }
401 return entry.handler(resolvedArgs)
402}
403
404func jpfAbs(arguments []interface{}) (interface{}, error) {
405 num := arguments[0].(float64)
406 return math.Abs(num), nil
407}
408
409func jpfLength(arguments []interface{}) (interface{}, error) {
410 arg := arguments[0]
411 if c, ok := arg.(string); ok {
412 return float64(utf8.RuneCountInString(c)), nil
413 } else if isSliceType(arg) {
414 v := reflect.ValueOf(arg)
415 return float64(v.Len()), nil
416 } else if c, ok := arg.(map[string]interface{}); ok {
417 return float64(len(c)), nil
418 }
419 return nil, errors.New("could not compute length()")
420}
421
422func jpfStartsWith(arguments []interface{}) (interface{}, error) {
423 search := arguments[0].(string)
424 prefix := arguments[1].(string)
425 return strings.HasPrefix(search, prefix), nil
426}
427
428func jpfAvg(arguments []interface{}) (interface{}, error) {
429 // We've already type checked the value so we can safely use
430 // type assertions.
431 args := arguments[0].([]interface{})
432 length := float64(len(args))
433 numerator := 0.0
434 for _, n := range args {
435 numerator += n.(float64)
436 }
437 return numerator / length, nil
438}
439func jpfCeil(arguments []interface{}) (interface{}, error) {
440 val := arguments[0].(float64)
441 return math.Ceil(val), nil
442}
443func jpfContains(arguments []interface{}) (interface{}, error) {
444 search := arguments[0]
445 el := arguments[1]
446 if searchStr, ok := search.(string); ok {
447 if elStr, ok := el.(string); ok {
448 return strings.Index(searchStr, elStr) != -1, nil
449 }
450 return false, nil
451 }
452 // Otherwise this is a generic contains for []interface{}
453 general := search.([]interface{})
454 for _, item := range general {
455 if item == el {
456 return true, nil
457 }
458 }
459 return false, nil
460}
461func jpfEndsWith(arguments []interface{}) (interface{}, error) {
462 search := arguments[0].(string)
463 suffix := arguments[1].(string)
464 return strings.HasSuffix(search, suffix), nil
465}
466func jpfFloor(arguments []interface{}) (interface{}, error) {
467 val := arguments[0].(float64)
468 return math.Floor(val), nil
469}
470func jpfMap(arguments []interface{}) (interface{}, error) {
471 intr := arguments[0].(*treeInterpreter)
472 exp := arguments[1].(expRef)
473 node := exp.ref
474 arr := arguments[2].([]interface{})
475 mapped := make([]interface{}, 0, len(arr))
476 for _, value := range arr {
477 current, err := intr.Execute(node, value)
478 if err != nil {
479 return nil, err
480 }
481 mapped = append(mapped, current)
482 }
483 return mapped, nil
484}
485func jpfMax(arguments []interface{}) (interface{}, error) {
486 if items, ok := toArrayNum(arguments[0]); ok {
487 if len(items) == 0 {
488 return nil, nil
489 }
490 if len(items) == 1 {
491 return items[0], nil
492 }
493 best := items[0]
494 for _, item := range items[1:] {
495 if item > best {
496 best = item
497 }
498 }
499 return best, nil
500 }
501 // Otherwise we're dealing with a max() of strings.
502 items, _ := toArrayStr(arguments[0])
503 if len(items) == 0 {
504 return nil, nil
505 }
506 if len(items) == 1 {
507 return items[0], nil
508 }
509 best := items[0]
510 for _, item := range items[1:] {
511 if item > best {
512 best = item
513 }
514 }
515 return best, nil
516}
517func jpfMerge(arguments []interface{}) (interface{}, error) {
518 final := make(map[string]interface{})
519 for _, m := range arguments {
520 mapped := m.(map[string]interface{})
521 for key, value := range mapped {
522 final[key] = value
523 }
524 }
525 return final, nil
526}
527func jpfMaxBy(arguments []interface{}) (interface{}, error) {
528 intr := arguments[0].(*treeInterpreter)
529 arr := arguments[1].([]interface{})
530 exp := arguments[2].(expRef)
531 node := exp.ref
532 if len(arr) == 0 {
533 return nil, nil
534 } else if len(arr) == 1 {
535 return arr[0], nil
536 }
537 start, err := intr.Execute(node, arr[0])
538 if err != nil {
539 return nil, err
540 }
541 switch t := start.(type) {
542 case float64:
543 bestVal := t
544 bestItem := arr[0]
545 for _, item := range arr[1:] {
546 result, err := intr.Execute(node, item)
547 if err != nil {
548 return nil, err
549 }
550 current, ok := result.(float64)
551 if !ok {
552 return nil, errors.New("invalid type, must be number")
553 }
554 if current > bestVal {
555 bestVal = current
556 bestItem = item
557 }
558 }
559 return bestItem, nil
560 case string:
561 bestVal := t
562 bestItem := arr[0]
563 for _, item := range arr[1:] {
564 result, err := intr.Execute(node, item)
565 if err != nil {
566 return nil, err
567 }
568 current, ok := result.(string)
569 if !ok {
570 return nil, errors.New("invalid type, must be string")
571 }
572 if current > bestVal {
573 bestVal = current
574 bestItem = item
575 }
576 }
577 return bestItem, nil
578 default:
579 return nil, errors.New("invalid type, must be number of string")
580 }
581}
582func jpfSum(arguments []interface{}) (interface{}, error) {
583 items, _ := toArrayNum(arguments[0])
584 sum := 0.0
585 for _, item := range items {
586 sum += item
587 }
588 return sum, nil
589}
590
591func jpfMin(arguments []interface{}) (interface{}, error) {
592 if items, ok := toArrayNum(arguments[0]); ok {
593 if len(items) == 0 {
594 return nil, nil
595 }
596 if len(items) == 1 {
597 return items[0], nil
598 }
599 best := items[0]
600 for _, item := range items[1:] {
601 if item < best {
602 best = item
603 }
604 }
605 return best, nil
606 }
607 items, _ := toArrayStr(arguments[0])
608 if len(items) == 0 {
609 return nil, nil
610 }
611 if len(items) == 1 {
612 return items[0], nil
613 }
614 best := items[0]
615 for _, item := range items[1:] {
616 if item < best {
617 best = item
618 }
619 }
620 return best, nil
621}
622
623func jpfMinBy(arguments []interface{}) (interface{}, error) {
624 intr := arguments[0].(*treeInterpreter)
625 arr := arguments[1].([]interface{})
626 exp := arguments[2].(expRef)
627 node := exp.ref
628 if len(arr) == 0 {
629 return nil, nil
630 } else if len(arr) == 1 {
631 return arr[0], nil
632 }
633 start, err := intr.Execute(node, arr[0])
634 if err != nil {
635 return nil, err
636 }
637 if t, ok := start.(float64); ok {
638 bestVal := t
639 bestItem := arr[0]
640 for _, item := range arr[1:] {
641 result, err := intr.Execute(node, item)
642 if err != nil {
643 return nil, err
644 }
645 current, ok := result.(float64)
646 if !ok {
647 return nil, errors.New("invalid type, must be number")
648 }
649 if current < bestVal {
650 bestVal = current
651 bestItem = item
652 }
653 }
654 return bestItem, nil
655 } else if t, ok := start.(string); ok {
656 bestVal := t
657 bestItem := arr[0]
658 for _, item := range arr[1:] {
659 result, err := intr.Execute(node, item)
660 if err != nil {
661 return nil, err
662 }
663 current, ok := result.(string)
664 if !ok {
665 return nil, errors.New("invalid type, must be string")
666 }
667 if current < bestVal {
668 bestVal = current
669 bestItem = item
670 }
671 }
672 return bestItem, nil
673 } else {
674 return nil, errors.New("invalid type, must be number of string")
675 }
676}
677func jpfType(arguments []interface{}) (interface{}, error) {
678 arg := arguments[0]
679 if _, ok := arg.(float64); ok {
680 return "number", nil
681 }
682 if _, ok := arg.(string); ok {
683 return "string", nil
684 }
685 if _, ok := arg.([]interface{}); ok {
686 return "array", nil
687 }
688 if _, ok := arg.(map[string]interface{}); ok {
689 return "object", nil
690 }
691 if arg == nil {
692 return "null", nil
693 }
694 if arg == true || arg == false {
695 return "boolean", nil
696 }
697 return nil, errors.New("unknown type")
698}
699func jpfKeys(arguments []interface{}) (interface{}, error) {
700 arg := arguments[0].(map[string]interface{})
701 collected := make([]interface{}, 0, len(arg))
702 for key := range arg {
703 collected = append(collected, key)
704 }
705 return collected, nil
706}
707func jpfValues(arguments []interface{}) (interface{}, error) {
708 arg := arguments[0].(map[string]interface{})
709 collected := make([]interface{}, 0, len(arg))
710 for _, value := range arg {
711 collected = append(collected, value)
712 }
713 return collected, nil
714}
715func jpfSort(arguments []interface{}) (interface{}, error) {
716 if items, ok := toArrayNum(arguments[0]); ok {
717 d := sort.Float64Slice(items)
718 sort.Stable(d)
719 final := make([]interface{}, len(d))
720 for i, val := range d {
721 final[i] = val
722 }
723 return final, nil
724 }
725 // Otherwise we're dealing with sort()'ing strings.
726 items, _ := toArrayStr(arguments[0])
727 d := sort.StringSlice(items)
728 sort.Stable(d)
729 final := make([]interface{}, len(d))
730 for i, val := range d {
731 final[i] = val
732 }
733 return final, nil
734}
735func jpfSortBy(arguments []interface{}) (interface{}, error) {
736 intr := arguments[0].(*treeInterpreter)
737 arr := arguments[1].([]interface{})
738 exp := arguments[2].(expRef)
739 node := exp.ref
740 if len(arr) == 0 {
741 return arr, nil
742 } else if len(arr) == 1 {
743 return arr, nil
744 }
745 start, err := intr.Execute(node, arr[0])
746 if err != nil {
747 return nil, err
748 }
749 if _, ok := start.(float64); ok {
750 sortable := &byExprFloat{intr, node, arr, false}
751 sort.Stable(sortable)
752 if sortable.hasError {
753 return nil, errors.New("error in sort_by comparison")
754 }
755 return arr, nil
756 } else if _, ok := start.(string); ok {
757 sortable := &byExprString{intr, node, arr, false}
758 sort.Stable(sortable)
759 if sortable.hasError {
760 return nil, errors.New("error in sort_by comparison")
761 }
762 return arr, nil
763 } else {
764 return nil, errors.New("invalid type, must be number of string")
765 }
766}
767func jpfJoin(arguments []interface{}) (interface{}, error) {
768 sep := arguments[0].(string)
769 // We can't just do arguments[1].([]string), we have to
770 // manually convert each item to a string.
771 arrayStr := []string{}
772 for _, item := range arguments[1].([]interface{}) {
773 arrayStr = append(arrayStr, item.(string))
774 }
775 return strings.Join(arrayStr, sep), nil
776}
777func jpfReverse(arguments []interface{}) (interface{}, error) {
778 if s, ok := arguments[0].(string); ok {
779 r := []rune(s)
780 for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
781 r[i], r[j] = r[j], r[i]
782 }
783 return string(r), nil
784 }
785 items := arguments[0].([]interface{})
786 length := len(items)
787 reversed := make([]interface{}, length)
788 for i, item := range items {
789 reversed[length-(i+1)] = item
790 }
791 return reversed, nil
792}
793func jpfToArray(arguments []interface{}) (interface{}, error) {
794 if _, ok := arguments[0].([]interface{}); ok {
795 return arguments[0], nil
796 }
797 return arguments[:1:1], nil
798}
799func jpfToString(arguments []interface{}) (interface{}, error) {
800 if v, ok := arguments[0].(string); ok {
801 return v, nil
802 }
803 result, err := json.Marshal(arguments[0])
804 if err != nil {
805 return nil, err
806 }
807 return string(result), nil
808}
809func jpfToNumber(arguments []interface{}) (interface{}, error) {
810 arg := arguments[0]
811 if v, ok := arg.(float64); ok {
812 return v, nil
813 }
814 if v, ok := arg.(string); ok {
815 conv, err := strconv.ParseFloat(v, 64)
816 if err != nil {
817 return nil, nil
818 }
819 return conv, nil
820 }
821 if _, ok := arg.([]interface{}); ok {
822 return nil, nil
823 }
824 if _, ok := arg.(map[string]interface{}); ok {
825 return nil, nil
826 }
827 if arg == nil {
828 return nil, nil
829 }
830 if arg == true || arg == false {
831 return nil, nil
832 }
833 return nil, errors.New("unknown type")
834}
835func jpfNotNull(arguments []interface{}) (interface{}, error) {
836 for _, arg := range arguments {
837 if arg != nil {
838 return arg, nil
839 }
840 }
841 return nil, nil
842}
diff --git a/vendor/github.com/jmespath/go-jmespath/interpreter.go b/vendor/github.com/jmespath/go-jmespath/interpreter.go
new file mode 100644
index 0000000..13c7460
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/interpreter.go
@@ -0,0 +1,418 @@
1package jmespath
2
3import (
4 "errors"
5 "reflect"
6 "unicode"
7 "unicode/utf8"
8)
9
10/* This is a tree based interpreter. It walks the AST and directly
11 interprets the AST to search through a JSON document.
12*/
13
14type treeInterpreter struct {
15 fCall *functionCaller
16}
17
18func newInterpreter() *treeInterpreter {
19 interpreter := treeInterpreter{}
20 interpreter.fCall = newFunctionCaller()
21 return &interpreter
22}
23
24type expRef struct {
25 ref ASTNode
26}
27
28// Execute takes an ASTNode and input data and interprets the AST directly.
29// It will produce the result of applying the JMESPath expression associated
30// with the ASTNode to the input data "value".
31func (intr *treeInterpreter) Execute(node ASTNode, value interface{}) (interface{}, error) {
32 switch node.nodeType {
33 case ASTComparator:
34 left, err := intr.Execute(node.children[0], value)
35 if err != nil {
36 return nil, err
37 }
38 right, err := intr.Execute(node.children[1], value)
39 if err != nil {
40 return nil, err
41 }
42 switch node.value {
43 case tEQ:
44 return objsEqual(left, right), nil
45 case tNE:
46 return !objsEqual(left, right), nil
47 }
48 leftNum, ok := left.(float64)
49 if !ok {
50 return nil, nil
51 }
52 rightNum, ok := right.(float64)
53 if !ok {
54 return nil, nil
55 }
56 switch node.value {
57 case tGT:
58 return leftNum > rightNum, nil
59 case tGTE:
60 return leftNum >= rightNum, nil
61 case tLT:
62 return leftNum < rightNum, nil
63 case tLTE:
64 return leftNum <= rightNum, nil
65 }
66 case ASTExpRef:
67 return expRef{ref: node.children[0]}, nil
68 case ASTFunctionExpression:
69 resolvedArgs := []interface{}{}
70 for _, arg := range node.children {
71 current, err := intr.Execute(arg, value)
72 if err != nil {
73 return nil, err
74 }
75 resolvedArgs = append(resolvedArgs, current)
76 }
77 return intr.fCall.CallFunction(node.value.(string), resolvedArgs, intr)
78 case ASTField:
79 if m, ok := value.(map[string]interface{}); ok {
80 key := node.value.(string)
81 return m[key], nil
82 }
83 return intr.fieldFromStruct(node.value.(string), value)
84 case ASTFilterProjection:
85 left, err := intr.Execute(node.children[0], value)
86 if err != nil {
87 return nil, nil
88 }
89 sliceType, ok := left.([]interface{})
90 if !ok {
91 if isSliceType(left) {
92 return intr.filterProjectionWithReflection(node, left)
93 }
94 return nil, nil
95 }
96 compareNode := node.children[2]
97 collected := []interface{}{}
98 for _, element := range sliceType {
99 result, err := intr.Execute(compareNode, element)
100 if err != nil {
101 return nil, err
102 }
103 if !isFalse(result) {
104 current, err := intr.Execute(node.children[1], element)
105 if err != nil {
106 return nil, err
107 }
108 if current != nil {
109 collected = append(collected, current)
110 }
111 }
112 }
113 return collected, nil
114 case ASTFlatten:
115 left, err := intr.Execute(node.children[0], value)
116 if err != nil {
117 return nil, nil
118 }
119 sliceType, ok := left.([]interface{})
120 if !ok {
121 // If we can't type convert to []interface{}, there's
122 // a chance this could still work via reflection if we're
123 // dealing with user provided types.
124 if isSliceType(left) {
125 return intr.flattenWithReflection(left)
126 }
127 return nil, nil
128 }
129 flattened := []interface{}{}
130 for _, element := range sliceType {
131 if elementSlice, ok := element.([]interface{}); ok {
132 flattened = append(flattened, elementSlice...)
133 } else if isSliceType(element) {
134 reflectFlat := []interface{}{}
135 v := reflect.ValueOf(element)
136 for i := 0; i < v.Len(); i++ {
137 reflectFlat = append(reflectFlat, v.Index(i).Interface())
138 }
139 flattened = append(flattened, reflectFlat...)
140 } else {
141 flattened = append(flattened, element)
142 }
143 }
144 return flattened, nil
145 case ASTIdentity, ASTCurrentNode:
146 return value, nil
147 case ASTIndex:
148 if sliceType, ok := value.([]interface{}); ok {
149 index := node.value.(int)
150 if index < 0 {
151 index += len(sliceType)
152 }
153 if index < len(sliceType) && index >= 0 {
154 return sliceType[index], nil
155 }
156 return nil, nil
157 }
158 // Otherwise try via reflection.
159 rv := reflect.ValueOf(value)
160 if rv.Kind() == reflect.Slice {
161 index := node.value.(int)
162 if index < 0 {
163 index += rv.Len()
164 }
165 if index < rv.Len() && index >= 0 {
166 v := rv.Index(index)
167 return v.Interface(), nil
168 }
169 }
170 return nil, nil
171 case ASTKeyValPair:
172 return intr.Execute(node.children[0], value)
173 case ASTLiteral:
174 return node.value, nil
175 case ASTMultiSelectHash:
176 if value == nil {
177 return nil, nil
178 }
179 collected := make(map[string]interface{})
180 for _, child := range node.children {
181 current, err := intr.Execute(child, value)
182 if err != nil {
183 return nil, err
184 }
185 key := child.value.(string)
186 collected[key] = current
187 }
188 return collected, nil
189 case ASTMultiSelectList:
190 if value == nil {
191 return nil, nil
192 }
193 collected := []interface{}{}
194 for _, child := range node.children {
195 current, err := intr.Execute(child, value)
196 if err != nil {
197 return nil, err
198 }
199 collected = append(collected, current)
200 }
201 return collected, nil
202 case ASTOrExpression:
203 matched, err := intr.Execute(node.children[0], value)
204 if err != nil {
205 return nil, err
206 }
207 if isFalse(matched) {
208 matched, err = intr.Execute(node.children[1], value)
209 if err != nil {
210 return nil, err
211 }
212 }
213 return matched, nil
214 case ASTAndExpression:
215 matched, err := intr.Execute(node.children[0], value)
216 if err != nil {
217 return nil, err
218 }
219 if isFalse(matched) {
220 return matched, nil
221 }
222 return intr.Execute(node.children[1], value)
223 case ASTNotExpression:
224 matched, err := intr.Execute(node.children[0], value)
225 if err != nil {
226 return nil, err
227 }
228 if isFalse(matched) {
229 return true, nil
230 }
231 return false, nil
232 case ASTPipe:
233 result := value
234 var err error
235 for _, child := range node.children {
236 result, err = intr.Execute(child, result)
237 if err != nil {
238 return nil, err
239 }
240 }
241 return result, nil
242 case ASTProjection:
243 left, err := intr.Execute(node.children[0], value)
244 if err != nil {
245 return nil, err
246 }
247 sliceType, ok := left.([]interface{})
248 if !ok {
249 if isSliceType(left) {
250 return intr.projectWithReflection(node, left)
251 }
252 return nil, nil
253 }
254 collected := []interface{}{}
255 var current interface{}
256 for _, element := range sliceType {
257 current, err = intr.Execute(node.children[1], element)
258 if err != nil {
259 return nil, err
260 }
261 if current != nil {
262 collected = append(collected, current)
263 }
264 }
265 return collected, nil
266 case ASTSubexpression, ASTIndexExpression:
267 left, err := intr.Execute(node.children[0], value)
268 if err != nil {
269 return nil, err
270 }
271 return intr.Execute(node.children[1], left)
272 case ASTSlice:
273 sliceType, ok := value.([]interface{})
274 if !ok {
275 if isSliceType(value) {
276 return intr.sliceWithReflection(node, value)
277 }
278 return nil, nil
279 }
280 parts := node.value.([]*int)
281 sliceParams := make([]sliceParam, 3)
282 for i, part := range parts {
283 if part != nil {
284 sliceParams[i].Specified = true
285 sliceParams[i].N = *part
286 }
287 }
288 return slice(sliceType, sliceParams)
289 case ASTValueProjection:
290 left, err := intr.Execute(node.children[0], value)
291 if err != nil {
292 return nil, nil
293 }
294 mapType, ok := left.(map[string]interface{})
295 if !ok {
296 return nil, nil
297 }
298 values := make([]interface{}, len(mapType))
299 for _, value := range mapType {
300 values = append(values, value)
301 }
302 collected := []interface{}{}
303 for _, element := range values {
304 current, err := intr.Execute(node.children[1], element)
305 if err != nil {
306 return nil, err
307 }
308 if current != nil {
309 collected = append(collected, current)
310 }
311 }
312 return collected, nil
313 }
314 return nil, errors.New("Unknown AST node: " + node.nodeType.String())
315}
316
317func (intr *treeInterpreter) fieldFromStruct(key string, value interface{}) (interface{}, error) {
318 rv := reflect.ValueOf(value)
319 first, n := utf8.DecodeRuneInString(key)
320 fieldName := string(unicode.ToUpper(first)) + key[n:]
321 if rv.Kind() == reflect.Struct {
322 v := rv.FieldByName(fieldName)
323 if !v.IsValid() {
324 return nil, nil
325 }
326 return v.Interface(), nil
327 } else if rv.Kind() == reflect.Ptr {
328 // Handle multiple levels of indirection?
329 if rv.IsNil() {
330 return nil, nil
331 }
332 rv = rv.Elem()
333 v := rv.FieldByName(fieldName)
334 if !v.IsValid() {
335 return nil, nil
336 }
337 return v.Interface(), nil
338 }
339 return nil, nil
340}
341
342func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface{}, error) {
343 v := reflect.ValueOf(value)
344 flattened := []interface{}{}
345 for i := 0; i < v.Len(); i++ {
346 element := v.Index(i).Interface()
347 if reflect.TypeOf(element).Kind() == reflect.Slice {
348 // Then insert the contents of the element
349 // slice into the flattened slice,
350 // i.e flattened = append(flattened, mySlice...)
351 elementV := reflect.ValueOf(element)
352 for j := 0; j < elementV.Len(); j++ {
353 flattened = append(
354 flattened, elementV.Index(j).Interface())
355 }
356 } else {
357 flattened = append(flattened, element)
358 }
359 }
360 return flattened, nil
361}
362
363func (intr *treeInterpreter) sliceWithReflection(node ASTNode, value interface{}) (interface{}, error) {
364 v := reflect.ValueOf(value)
365 parts := node.value.([]*int)
366 sliceParams := make([]sliceParam, 3)
367 for i, part := range parts {
368 if part != nil {
369 sliceParams[i].Specified = true
370 sliceParams[i].N = *part
371 }
372 }
373 final := []interface{}{}
374 for i := 0; i < v.Len(); i++ {
375 element := v.Index(i).Interface()
376 final = append(final, element)
377 }
378 return slice(final, sliceParams)
379}
380
381func (intr *treeInterpreter) filterProjectionWithReflection(node ASTNode, value interface{}) (interface{}, error) {
382 compareNode := node.children[2]
383 collected := []interface{}{}
384 v := reflect.ValueOf(value)
385 for i := 0; i < v.Len(); i++ {
386 element := v.Index(i).Interface()
387 result, err := intr.Execute(compareNode, element)
388 if err != nil {
389 return nil, err
390 }
391 if !isFalse(result) {
392 current, err := intr.Execute(node.children[1], element)
393 if err != nil {
394 return nil, err
395 }
396 if current != nil {
397 collected = append(collected, current)
398 }
399 }
400 }
401 return collected, nil
402}
403
404func (intr *treeInterpreter) projectWithReflection(node ASTNode, value interface{}) (interface{}, error) {
405 collected := []interface{}{}
406 v := reflect.ValueOf(value)
407 for i := 0; i < v.Len(); i++ {
408 element := v.Index(i).Interface()
409 result, err := intr.Execute(node.children[1], element)
410 if err != nil {
411 return nil, err
412 }
413 if result != nil {
414 collected = append(collected, result)
415 }
416 }
417 return collected, nil
418}
diff --git a/vendor/github.com/jmespath/go-jmespath/lexer.go b/vendor/github.com/jmespath/go-jmespath/lexer.go
new file mode 100644
index 0000000..817900c
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/lexer.go
@@ -0,0 +1,420 @@
1package jmespath
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "strconv"
8 "strings"
9 "unicode/utf8"
10)
11
12type token struct {
13 tokenType tokType
14 value string
15 position int
16 length int
17}
18
19type tokType int
20
21const eof = -1
22
23// Lexer contains information about the expression being tokenized.
24type Lexer struct {
25 expression string // The expression provided by the user.
26 currentPos int // The current position in the string.
27 lastWidth int // The width of the current rune. This
28 buf bytes.Buffer // Internal buffer used for building up values.
29}
30
31// SyntaxError is the main error used whenever a lexing or parsing error occurs.
32type SyntaxError struct {
33 msg string // Error message displayed to user
34 Expression string // Expression that generated a SyntaxError
35 Offset int // The location in the string where the error occurred
36}
37
38func (e SyntaxError) Error() string {
39 // In the future, it would be good to underline the specific
40 // location where the error occurred.
41 return "SyntaxError: " + e.msg
42}
43
44// HighlightLocation will show where the syntax error occurred.
45// It will place a "^" character on a line below the expression
46// at the point where the syntax error occurred.
47func (e SyntaxError) HighlightLocation() string {
48 return e.Expression + "\n" + strings.Repeat(" ", e.Offset) + "^"
49}
50
51//go:generate stringer -type=tokType
52const (
53 tUnknown tokType = iota
54 tStar
55 tDot
56 tFilter
57 tFlatten
58 tLparen
59 tRparen
60 tLbracket
61 tRbracket
62 tLbrace
63 tRbrace
64 tOr
65 tPipe
66 tNumber
67 tUnquotedIdentifier
68 tQuotedIdentifier
69 tComma
70 tColon
71 tLT
72 tLTE
73 tGT
74 tGTE
75 tEQ
76 tNE
77 tJSONLiteral
78 tStringLiteral
79 tCurrent
80 tExpref
81 tAnd
82 tNot
83 tEOF
84)
85
86var basicTokens = map[rune]tokType{
87 '.': tDot,
88 '*': tStar,
89 ',': tComma,
90 ':': tColon,
91 '{': tLbrace,
92 '}': tRbrace,
93 ']': tRbracket, // tLbracket not included because it could be "[]"
94 '(': tLparen,
95 ')': tRparen,
96 '@': tCurrent,
97}
98
99// Bit mask for [a-zA-Z_] shifted down 64 bits to fit in a single uint64.
100// When using this bitmask just be sure to shift the rune down 64 bits
101// before checking against identifierStartBits.
102const identifierStartBits uint64 = 576460745995190270
103
104// Bit mask for [a-zA-Z0-9], 128 bits -> 2 uint64s.
105var identifierTrailingBits = [2]uint64{287948901175001088, 576460745995190270}
106
107var whiteSpace = map[rune]bool{
108 ' ': true, '\t': true, '\n': true, '\r': true,
109}
110
111func (t token) String() string {
112 return fmt.Sprintf("Token{%+v, %s, %d, %d}",
113 t.tokenType, t.value, t.position, t.length)
114}
115
116// NewLexer creates a new JMESPath lexer.
117func NewLexer() *Lexer {
118 lexer := Lexer{}
119 return &lexer
120}
121
122func (lexer *Lexer) next() rune {
123 if lexer.currentPos >= len(lexer.expression) {
124 lexer.lastWidth = 0
125 return eof
126 }
127 r, w := utf8.DecodeRuneInString(lexer.expression[lexer.currentPos:])
128 lexer.lastWidth = w
129 lexer.currentPos += w
130 return r
131}
132
133func (lexer *Lexer) back() {
134 lexer.currentPos -= lexer.lastWidth
135}
136
137func (lexer *Lexer) peek() rune {
138 t := lexer.next()
139 lexer.back()
140 return t
141}
142
143// tokenize takes an expression and returns corresponding tokens.
144func (lexer *Lexer) tokenize(expression string) ([]token, error) {
145 var tokens []token
146 lexer.expression = expression
147 lexer.currentPos = 0
148 lexer.lastWidth = 0
149loop:
150 for {
151 r := lexer.next()
152 if identifierStartBits&(1<<(uint64(r)-64)) > 0 {
153 t := lexer.consumeUnquotedIdentifier()
154 tokens = append(tokens, t)
155 } else if val, ok := basicTokens[r]; ok {
156 // Basic single char token.
157 t := token{
158 tokenType: val,
159 value: string(r),
160 position: lexer.currentPos - lexer.lastWidth,
161 length: 1,
162 }
163 tokens = append(tokens, t)
164 } else if r == '-' || (r >= '0' && r <= '9') {
165 t := lexer.consumeNumber()
166 tokens = append(tokens, t)
167 } else if r == '[' {
168 t := lexer.consumeLBracket()
169 tokens = append(tokens, t)
170 } else if r == '"' {
171 t, err := lexer.consumeQuotedIdentifier()
172 if err != nil {
173 return tokens, err
174 }
175 tokens = append(tokens, t)
176 } else if r == '\'' {
177 t, err := lexer.consumeRawStringLiteral()
178 if err != nil {
179 return tokens, err
180 }
181 tokens = append(tokens, t)
182 } else if r == '`' {
183 t, err := lexer.consumeLiteral()
184 if err != nil {
185 return tokens, err
186 }
187 tokens = append(tokens, t)
188 } else if r == '|' {
189 t := lexer.matchOrElse(r, '|', tOr, tPipe)
190 tokens = append(tokens, t)
191 } else if r == '<' {
192 t := lexer.matchOrElse(r, '=', tLTE, tLT)
193 tokens = append(tokens, t)
194 } else if r == '>' {
195 t := lexer.matchOrElse(r, '=', tGTE, tGT)
196 tokens = append(tokens, t)
197 } else if r == '!' {
198 t := lexer.matchOrElse(r, '=', tNE, tNot)
199 tokens = append(tokens, t)
200 } else if r == '=' {
201 t := lexer.matchOrElse(r, '=', tEQ, tUnknown)
202 tokens = append(tokens, t)
203 } else if r == '&' {
204 t := lexer.matchOrElse(r, '&', tAnd, tExpref)
205 tokens = append(tokens, t)
206 } else if r == eof {
207 break loop
208 } else if _, ok := whiteSpace[r]; ok {
209 // Ignore whitespace
210 } else {
211 return tokens, lexer.syntaxError(fmt.Sprintf("Unknown char: %s", strconv.QuoteRuneToASCII(r)))
212 }
213 }
214 tokens = append(tokens, token{tEOF, "", len(lexer.expression), 0})
215 return tokens, nil
216}
217
218// Consume characters until the ending rune "r" is reached.
219// If the end of the expression is reached before seeing the
220// terminating rune "r", then an error is returned.
221// If no error occurs then the matching substring is returned.
222// The returned string will not include the ending rune.
223func (lexer *Lexer) consumeUntil(end rune) (string, error) {
224 start := lexer.currentPos
225 current := lexer.next()
226 for current != end && current != eof {
227 if current == '\\' && lexer.peek() != eof {
228 lexer.next()
229 }
230 current = lexer.next()
231 }
232 if lexer.lastWidth == 0 {
233 // Then we hit an EOF so we never reached the closing
234 // delimiter.
235 return "", SyntaxError{
236 msg: "Unclosed delimiter: " + string(end),
237 Expression: lexer.expression,
238 Offset: len(lexer.expression),
239 }
240 }
241 return lexer.expression[start : lexer.currentPos-lexer.lastWidth], nil
242}
243
244func (lexer *Lexer) consumeLiteral() (token, error) {
245 start := lexer.currentPos
246 value, err := lexer.consumeUntil('`')
247 if err != nil {
248 return token{}, err
249 }
250 value = strings.Replace(value, "\\`", "`", -1)
251 return token{
252 tokenType: tJSONLiteral,
253 value: value,
254 position: start,
255 length: len(value),
256 }, nil
257}
258
259func (lexer *Lexer) consumeRawStringLiteral() (token, error) {
260 start := lexer.currentPos
261 currentIndex := start
262 current := lexer.next()
263 for current != '\'' && lexer.peek() != eof {
264 if current == '\\' && lexer.peek() == '\'' {
265 chunk := lexer.expression[currentIndex : lexer.currentPos-1]
266 lexer.buf.WriteString(chunk)
267 lexer.buf.WriteString("'")
268 lexer.next()
269 currentIndex = lexer.currentPos
270 }
271 current = lexer.next()
272 }
273 if lexer.lastWidth == 0 {
274 // Then we hit an EOF so we never reached the closing
275 // delimiter.
276 return token{}, SyntaxError{
277 msg: "Unclosed delimiter: '",
278 Expression: lexer.expression,
279 Offset: len(lexer.expression),
280 }
281 }
282 if currentIndex < lexer.currentPos {
283 lexer.buf.WriteString(lexer.expression[currentIndex : lexer.currentPos-1])
284 }
285 value := lexer.buf.String()
286 // Reset the buffer so it can reused again.
287 lexer.buf.Reset()
288 return token{
289 tokenType: tStringLiteral,
290 value: value,
291 position: start,
292 length: len(value),
293 }, nil
294}
295
296func (lexer *Lexer) syntaxError(msg string) SyntaxError {
297 return SyntaxError{
298 msg: msg,
299 Expression: lexer.expression,
300 Offset: lexer.currentPos - 1,
301 }
302}
303
304// Checks for a two char token, otherwise matches a single character
305// token. This is used whenever a two char token overlaps a single
306// char token, e.g. "||" -> tPipe, "|" -> tOr.
307func (lexer *Lexer) matchOrElse(first rune, second rune, matchedType tokType, singleCharType tokType) token {
308 start := lexer.currentPos - lexer.lastWidth
309 nextRune := lexer.next()
310 var t token
311 if nextRune == second {
312 t = token{
313 tokenType: matchedType,
314 value: string(first) + string(second),
315 position: start,
316 length: 2,
317 }
318 } else {
319 lexer.back()
320 t = token{
321 tokenType: singleCharType,
322 value: string(first),
323 position: start,
324 length: 1,
325 }
326 }
327 return t
328}
329
330func (lexer *Lexer) consumeLBracket() token {
331 // There's three options here:
332 // 1. A filter expression "[?"
333 // 2. A flatten operator "[]"
334 // 3. A bare rbracket "["
335 start := lexer.currentPos - lexer.lastWidth
336 nextRune := lexer.next()
337 var t token
338 if nextRune == '?' {
339 t = token{
340 tokenType: tFilter,
341 value: "[?",
342 position: start,
343 length: 2,
344 }
345 } else if nextRune == ']' {
346 t = token{
347 tokenType: tFlatten,
348 value: "[]",
349 position: start,
350 length: 2,
351 }
352 } else {
353 t = token{
354 tokenType: tLbracket,
355 value: "[",
356 position: start,
357 length: 1,
358 }
359 lexer.back()
360 }
361 return t
362}
363
364func (lexer *Lexer) consumeQuotedIdentifier() (token, error) {
365 start := lexer.currentPos
366 value, err := lexer.consumeUntil('"')
367 if err != nil {
368 return token{}, err
369 }
370 var decoded string
371 asJSON := []byte("\"" + value + "\"")
372 if err := json.Unmarshal([]byte(asJSON), &decoded); err != nil {
373 return token{}, err
374 }
375 return token{
376 tokenType: tQuotedIdentifier,
377 value: decoded,
378 position: start - 1,
379 length: len(decoded),
380 }, nil
381}
382
383func (lexer *Lexer) consumeUnquotedIdentifier() token {
384 // Consume runes until we reach the end of an unquoted
385 // identifier.
386 start := lexer.currentPos - lexer.lastWidth
387 for {
388 r := lexer.next()
389 if r < 0 || r > 128 || identifierTrailingBits[uint64(r)/64]&(1<<(uint64(r)%64)) == 0 {
390 lexer.back()
391 break
392 }
393 }
394 value := lexer.expression[start:lexer.currentPos]
395 return token{
396 tokenType: tUnquotedIdentifier,
397 value: value,
398 position: start,
399 length: lexer.currentPos - start,
400 }
401}
402
403func (lexer *Lexer) consumeNumber() token {
404 // Consume runes until we reach something that's not a number.
405 start := lexer.currentPos - lexer.lastWidth
406 for {
407 r := lexer.next()
408 if r < '0' || r > '9' {
409 lexer.back()
410 break
411 }
412 }
413 value := lexer.expression[start:lexer.currentPos]
414 return token{
415 tokenType: tNumber,
416 value: value,
417 position: start,
418 length: lexer.currentPos - start,
419 }
420}
diff --git a/vendor/github.com/jmespath/go-jmespath/parser.go b/vendor/github.com/jmespath/go-jmespath/parser.go
new file mode 100644
index 0000000..1240a17
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/parser.go
@@ -0,0 +1,603 @@
1package jmespath
2
3import (
4 "encoding/json"
5 "fmt"
6 "strconv"
7 "strings"
8)
9
10type astNodeType int
11
12//go:generate stringer -type astNodeType
13const (
14 ASTEmpty astNodeType = iota
15 ASTComparator
16 ASTCurrentNode
17 ASTExpRef
18 ASTFunctionExpression
19 ASTField
20 ASTFilterProjection
21 ASTFlatten
22 ASTIdentity
23 ASTIndex
24 ASTIndexExpression
25 ASTKeyValPair
26 ASTLiteral
27 ASTMultiSelectHash
28 ASTMultiSelectList
29 ASTOrExpression
30 ASTAndExpression
31 ASTNotExpression
32 ASTPipe
33 ASTProjection
34 ASTSubexpression
35 ASTSlice
36 ASTValueProjection
37)
38
39// ASTNode represents the abstract syntax tree of a JMESPath expression.
40type ASTNode struct {
41 nodeType astNodeType
42 value interface{}
43 children []ASTNode
44}
45
46func (node ASTNode) String() string {
47 return node.PrettyPrint(0)
48}
49
50// PrettyPrint will pretty print the parsed AST.
51// The AST is an implementation detail and this pretty print
52// function is provided as a convenience method to help with
53// debugging. You should not rely on its output as the internal
54// structure of the AST may change at any time.
55func (node ASTNode) PrettyPrint(indent int) string {
56 spaces := strings.Repeat(" ", indent)
57 output := fmt.Sprintf("%s%s {\n", spaces, node.nodeType)
58 nextIndent := indent + 2
59 if node.value != nil {
60 if converted, ok := node.value.(fmt.Stringer); ok {
61 // Account for things like comparator nodes
62 // that are enums with a String() method.
63 output += fmt.Sprintf("%svalue: %s\n", strings.Repeat(" ", nextIndent), converted.String())
64 } else {
65 output += fmt.Sprintf("%svalue: %#v\n", strings.Repeat(" ", nextIndent), node.value)
66 }
67 }
68 lastIndex := len(node.children)
69 if lastIndex > 0 {
70 output += fmt.Sprintf("%schildren: {\n", strings.Repeat(" ", nextIndent))
71 childIndent := nextIndent + 2
72 for _, elem := range node.children {
73 output += elem.PrettyPrint(childIndent)
74 }
75 }
76 output += fmt.Sprintf("%s}\n", spaces)
77 return output
78}
79
80var bindingPowers = map[tokType]int{
81 tEOF: 0,
82 tUnquotedIdentifier: 0,
83 tQuotedIdentifier: 0,
84 tRbracket: 0,
85 tRparen: 0,
86 tComma: 0,
87 tRbrace: 0,
88 tNumber: 0,
89 tCurrent: 0,
90 tExpref: 0,
91 tColon: 0,
92 tPipe: 1,
93 tOr: 2,
94 tAnd: 3,
95 tEQ: 5,
96 tLT: 5,
97 tLTE: 5,
98 tGT: 5,
99 tGTE: 5,
100 tNE: 5,
101 tFlatten: 9,
102 tStar: 20,
103 tFilter: 21,
104 tDot: 40,
105 tNot: 45,
106 tLbrace: 50,
107 tLbracket: 55,
108 tLparen: 60,
109}
110
111// Parser holds state about the current expression being parsed.
112type Parser struct {
113 expression string
114 tokens []token
115 index int
116}
117
118// NewParser creates a new JMESPath parser.
119func NewParser() *Parser {
120 p := Parser{}
121 return &p
122}
123
124// Parse will compile a JMESPath expression.
125func (p *Parser) Parse(expression string) (ASTNode, error) {
126 lexer := NewLexer()
127 p.expression = expression
128 p.index = 0
129 tokens, err := lexer.tokenize(expression)
130 if err != nil {
131 return ASTNode{}, err
132 }
133 p.tokens = tokens
134 parsed, err := p.parseExpression(0)
135 if err != nil {
136 return ASTNode{}, err
137 }
138 if p.current() != tEOF {
139 return ASTNode{}, p.syntaxError(fmt.Sprintf(
140 "Unexpected token at the end of the expresssion: %s", p.current()))
141 }
142 return parsed, nil
143}
144
145func (p *Parser) parseExpression(bindingPower int) (ASTNode, error) {
146 var err error
147 leftToken := p.lookaheadToken(0)
148 p.advance()
149 leftNode, err := p.nud(leftToken)
150 if err != nil {
151 return ASTNode{}, err
152 }
153 currentToken := p.current()
154 for bindingPower < bindingPowers[currentToken] {
155 p.advance()
156 leftNode, err = p.led(currentToken, leftNode)
157 if err != nil {
158 return ASTNode{}, err
159 }
160 currentToken = p.current()
161 }
162 return leftNode, nil
163}
164
165func (p *Parser) parseIndexExpression() (ASTNode, error) {
166 if p.lookahead(0) == tColon || p.lookahead(1) == tColon {
167 return p.parseSliceExpression()
168 }
169 indexStr := p.lookaheadToken(0).value
170 parsedInt, err := strconv.Atoi(indexStr)
171 if err != nil {
172 return ASTNode{}, err
173 }
174 indexNode := ASTNode{nodeType: ASTIndex, value: parsedInt}
175 p.advance()
176 if err := p.match(tRbracket); err != nil {
177 return ASTNode{}, err
178 }
179 return indexNode, nil
180}
181
182func (p *Parser) parseSliceExpression() (ASTNode, error) {
183 parts := []*int{nil, nil, nil}
184 index := 0
185 current := p.current()
186 for current != tRbracket && index < 3 {
187 if current == tColon {
188 index++
189 p.advance()
190 } else if current == tNumber {
191 parsedInt, err := strconv.Atoi(p.lookaheadToken(0).value)
192 if err != nil {
193 return ASTNode{}, err
194 }
195 parts[index] = &parsedInt
196 p.advance()
197 } else {
198 return ASTNode{}, p.syntaxError(
199 "Expected tColon or tNumber" + ", received: " + p.current().String())
200 }
201 current = p.current()
202 }
203 if err := p.match(tRbracket); err != nil {
204 return ASTNode{}, err
205 }
206 return ASTNode{
207 nodeType: ASTSlice,
208 value: parts,
209 }, nil
210}
211
212func (p *Parser) match(tokenType tokType) error {
213 if p.current() == tokenType {
214 p.advance()
215 return nil
216 }
217 return p.syntaxError("Expected " + tokenType.String() + ", received: " + p.current().String())
218}
219
220func (p *Parser) led(tokenType tokType, node ASTNode) (ASTNode, error) {
221 switch tokenType {
222 case tDot:
223 if p.current() != tStar {
224 right, err := p.parseDotRHS(bindingPowers[tDot])
225 return ASTNode{
226 nodeType: ASTSubexpression,
227 children: []ASTNode{node, right},
228 }, err
229 }
230 p.advance()
231 right, err := p.parseProjectionRHS(bindingPowers[tDot])
232 return ASTNode{
233 nodeType: ASTValueProjection,
234 children: []ASTNode{node, right},
235 }, err
236 case tPipe:
237 right, err := p.parseExpression(bindingPowers[tPipe])
238 return ASTNode{nodeType: ASTPipe, children: []ASTNode{node, right}}, err
239 case tOr:
240 right, err := p.parseExpression(bindingPowers[tOr])
241 return ASTNode{nodeType: ASTOrExpression, children: []ASTNode{node, right}}, err
242 case tAnd:
243 right, err := p.parseExpression(bindingPowers[tAnd])
244 return ASTNode{nodeType: ASTAndExpression, children: []ASTNode{node, right}}, err
245 case tLparen:
246 name := node.value
247 var args []ASTNode
248 for p.current() != tRparen {
249 expression, err := p.parseExpression(0)
250 if err != nil {
251 return ASTNode{}, err
252 }
253 if p.current() == tComma {
254 if err := p.match(tComma); err != nil {
255 return ASTNode{}, err
256 }
257 }
258 args = append(args, expression)
259 }
260 if err := p.match(tRparen); err != nil {
261 return ASTNode{}, err
262 }
263 return ASTNode{
264 nodeType: ASTFunctionExpression,
265 value: name,
266 children: args,
267 }, nil
268 case tFilter:
269 return p.parseFilter(node)
270 case tFlatten:
271 left := ASTNode{nodeType: ASTFlatten, children: []ASTNode{node}}
272 right, err := p.parseProjectionRHS(bindingPowers[tFlatten])
273 return ASTNode{
274 nodeType: ASTProjection,
275 children: []ASTNode{left, right},
276 }, err
277 case tEQ, tNE, tGT, tGTE, tLT, tLTE:
278 right, err := p.parseExpression(bindingPowers[tokenType])
279 if err != nil {
280 return ASTNode{}, err
281 }
282 return ASTNode{
283 nodeType: ASTComparator,
284 value: tokenType,
285 children: []ASTNode{node, right},
286 }, nil
287 case tLbracket:
288 tokenType := p.current()
289 var right ASTNode
290 var err error
291 if tokenType == tNumber || tokenType == tColon {
292 right, err = p.parseIndexExpression()
293 if err != nil {
294 return ASTNode{}, err
295 }
296 return p.projectIfSlice(node, right)
297 }
298 // Otherwise this is a projection.
299 if err := p.match(tStar); err != nil {
300 return ASTNode{}, err
301 }
302 if err := p.match(tRbracket); err != nil {
303 return ASTNode{}, err
304 }
305 right, err = p.parseProjectionRHS(bindingPowers[tStar])
306 if err != nil {
307 return ASTNode{}, err
308 }
309 return ASTNode{
310 nodeType: ASTProjection,
311 children: []ASTNode{node, right},
312 }, nil
313 }
314 return ASTNode{}, p.syntaxError("Unexpected token: " + tokenType.String())
315}
316
317func (p *Parser) nud(token token) (ASTNode, error) {
318 switch token.tokenType {
319 case tJSONLiteral:
320 var parsed interface{}
321 err := json.Unmarshal([]byte(token.value), &parsed)
322 if err != nil {
323 return ASTNode{}, err
324 }
325 return ASTNode{nodeType: ASTLiteral, value: parsed}, nil
326 case tStringLiteral:
327 return ASTNode{nodeType: ASTLiteral, value: token.value}, nil
328 case tUnquotedIdentifier:
329 return ASTNode{
330 nodeType: ASTField,
331 value: token.value,
332 }, nil
333 case tQuotedIdentifier:
334 node := ASTNode{nodeType: ASTField, value: token.value}
335 if p.current() == tLparen {
336 return ASTNode{}, p.syntaxErrorToken("Can't have quoted identifier as function name.", token)
337 }
338 return node, nil
339 case tStar:
340 left := ASTNode{nodeType: ASTIdentity}
341 var right ASTNode
342 var err error
343 if p.current() == tRbracket {
344 right = ASTNode{nodeType: ASTIdentity}
345 } else {
346 right, err = p.parseProjectionRHS(bindingPowers[tStar])
347 }
348 return ASTNode{nodeType: ASTValueProjection, children: []ASTNode{left, right}}, err
349 case tFilter:
350 return p.parseFilter(ASTNode{nodeType: ASTIdentity})
351 case tLbrace:
352 return p.parseMultiSelectHash()
353 case tFlatten:
354 left := ASTNode{
355 nodeType: ASTFlatten,
356 children: []ASTNode{{nodeType: ASTIdentity}},
357 }
358 right, err := p.parseProjectionRHS(bindingPowers[tFlatten])
359 if err != nil {
360 return ASTNode{}, err
361 }
362 return ASTNode{nodeType: ASTProjection, children: []ASTNode{left, right}}, nil
363 case tLbracket:
364 tokenType := p.current()
365 //var right ASTNode
366 if tokenType == tNumber || tokenType == tColon {
367 right, err := p.parseIndexExpression()
368 if err != nil {
369 return ASTNode{}, nil
370 }
371 return p.projectIfSlice(ASTNode{nodeType: ASTIdentity}, right)
372 } else if tokenType == tStar && p.lookahead(1) == tRbracket {
373 p.advance()
374 p.advance()
375 right, err := p.parseProjectionRHS(bindingPowers[tStar])
376 if err != nil {
377 return ASTNode{}, err
378 }
379 return ASTNode{
380 nodeType: ASTProjection,
381 children: []ASTNode{{nodeType: ASTIdentity}, right},
382 }, nil
383 } else {
384 return p.parseMultiSelectList()
385 }
386 case tCurrent:
387 return ASTNode{nodeType: ASTCurrentNode}, nil
388 case tExpref:
389 expression, err := p.parseExpression(bindingPowers[tExpref])
390 if err != nil {
391 return ASTNode{}, err
392 }
393 return ASTNode{nodeType: ASTExpRef, children: []ASTNode{expression}}, nil
394 case tNot:
395 expression, err := p.parseExpression(bindingPowers[tNot])
396 if err != nil {
397 return ASTNode{}, err
398 }
399 return ASTNode{nodeType: ASTNotExpression, children: []ASTNode{expression}}, nil
400 case tLparen:
401 expression, err := p.parseExpression(0)
402 if err != nil {
403 return ASTNode{}, err
404 }
405 if err := p.match(tRparen); err != nil {
406 return ASTNode{}, err
407 }
408 return expression, nil
409 case tEOF:
410 return ASTNode{}, p.syntaxErrorToken("Incomplete expression", token)
411 }
412
413 return ASTNode{}, p.syntaxErrorToken("Invalid token: "+token.tokenType.String(), token)
414}
415
416func (p *Parser) parseMultiSelectList() (ASTNode, error) {
417 var expressions []ASTNode
418 for {
419 expression, err := p.parseExpression(0)
420 if err != nil {
421 return ASTNode{}, err
422 }
423 expressions = append(expressions, expression)
424 if p.current() == tRbracket {
425 break
426 }
427 err = p.match(tComma)
428 if err != nil {
429 return ASTNode{}, err
430 }
431 }
432 err := p.match(tRbracket)
433 if err != nil {
434 return ASTNode{}, err
435 }
436 return ASTNode{
437 nodeType: ASTMultiSelectList,
438 children: expressions,
439 }, nil
440}
441
442func (p *Parser) parseMultiSelectHash() (ASTNode, error) {
443 var children []ASTNode
444 for {
445 keyToken := p.lookaheadToken(0)
446 if err := p.match(tUnquotedIdentifier); err != nil {
447 if err := p.match(tQuotedIdentifier); err != nil {
448 return ASTNode{}, p.syntaxError("Expected tQuotedIdentifier or tUnquotedIdentifier")
449 }
450 }
451 keyName := keyToken.value
452 err := p.match(tColon)
453 if err != nil {
454 return ASTNode{}, err
455 }
456 value, err := p.parseExpression(0)
457 if err != nil {
458 return ASTNode{}, err
459 }
460 node := ASTNode{
461 nodeType: ASTKeyValPair,
462 value: keyName,
463 children: []ASTNode{value},
464 }
465 children = append(children, node)
466 if p.current() == tComma {
467 err := p.match(tComma)
468 if err != nil {
469 return ASTNode{}, nil
470 }
471 } else if p.current() == tRbrace {
472 err := p.match(tRbrace)
473 if err != nil {
474 return ASTNode{}, nil
475 }
476 break
477 }
478 }
479 return ASTNode{
480 nodeType: ASTMultiSelectHash,
481 children: children,
482 }, nil
483}
484
485func (p *Parser) projectIfSlice(left ASTNode, right ASTNode) (ASTNode, error) {
486 indexExpr := ASTNode{
487 nodeType: ASTIndexExpression,
488 children: []ASTNode{left, right},
489 }
490 if right.nodeType == ASTSlice {
491 right, err := p.parseProjectionRHS(bindingPowers[tStar])
492 return ASTNode{
493 nodeType: ASTProjection,
494 children: []ASTNode{indexExpr, right},
495 }, err
496 }
497 return indexExpr, nil
498}
499func (p *Parser) parseFilter(node ASTNode) (ASTNode, error) {
500 var right, condition ASTNode
501 var err error
502 condition, err = p.parseExpression(0)
503 if err != nil {
504 return ASTNode{}, err
505 }
506 if err := p.match(tRbracket); err != nil {
507 return ASTNode{}, err
508 }
509 if p.current() == tFlatten {
510 right = ASTNode{nodeType: ASTIdentity}
511 } else {
512 right, err = p.parseProjectionRHS(bindingPowers[tFilter])
513 if err != nil {
514 return ASTNode{}, err
515 }
516 }
517
518 return ASTNode{
519 nodeType: ASTFilterProjection,
520 children: []ASTNode{node, right, condition},
521 }, nil
522}
523
524func (p *Parser) parseDotRHS(bindingPower int) (ASTNode, error) {
525 lookahead := p.current()
526 if tokensOneOf([]tokType{tQuotedIdentifier, tUnquotedIdentifier, tStar}, lookahead) {
527 return p.parseExpression(bindingPower)
528 } else if lookahead == tLbracket {
529 if err := p.match(tLbracket); err != nil {
530 return ASTNode{}, err
531 }
532 return p.parseMultiSelectList()
533 } else if lookahead == tLbrace {
534 if err := p.match(tLbrace); err != nil {
535 return ASTNode{}, err
536 }
537 return p.parseMultiSelectHash()
538 }
539 return ASTNode{}, p.syntaxError("Expected identifier, lbracket, or lbrace")
540}
541
542func (p *Parser) parseProjectionRHS(bindingPower int) (ASTNode, error) {
543 current := p.current()
544 if bindingPowers[current] < 10 {
545 return ASTNode{nodeType: ASTIdentity}, nil
546 } else if current == tLbracket {
547 return p.parseExpression(bindingPower)
548 } else if current == tFilter {
549 return p.parseExpression(bindingPower)
550 } else if current == tDot {
551 err := p.match(tDot)
552 if err != nil {
553 return ASTNode{}, err
554 }
555 return p.parseDotRHS(bindingPower)
556 } else {
557 return ASTNode{}, p.syntaxError("Error")
558 }
559}
560
561func (p *Parser) lookahead(number int) tokType {
562 return p.lookaheadToken(number).tokenType
563}
564
565func (p *Parser) current() tokType {
566 return p.lookahead(0)
567}
568
569func (p *Parser) lookaheadToken(number int) token {
570 return p.tokens[p.index+number]
571}
572
573func (p *Parser) advance() {
574 p.index++
575}
576
577func tokensOneOf(elements []tokType, token tokType) bool {
578 for _, elem := range elements {
579 if elem == token {
580 return true
581 }
582 }
583 return false
584}
585
586func (p *Parser) syntaxError(msg string) SyntaxError {
587 return SyntaxError{
588 msg: msg,
589 Expression: p.expression,
590 Offset: p.lookaheadToken(0).position,
591 }
592}
593
594// Create a SyntaxError based on the provided token.
595// This differs from syntaxError() which creates a SyntaxError
596// based on the current lookahead token.
597func (p *Parser) syntaxErrorToken(msg string, t token) SyntaxError {
598 return SyntaxError{
599 msg: msg,
600 Expression: p.expression,
601 Offset: t.position,
602 }
603}
diff --git a/vendor/github.com/jmespath/go-jmespath/toktype_string.go b/vendor/github.com/jmespath/go-jmespath/toktype_string.go
new file mode 100644
index 0000000..dae79cb
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/toktype_string.go
@@ -0,0 +1,16 @@
1// generated by stringer -type=tokType; DO NOT EDIT
2
3package jmespath
4
5import "fmt"
6
7const _tokType_name = "tUnknowntStartDottFiltertFlattentLparentRparentLbrackettRbrackettLbracetRbracetOrtPipetNumbertUnquotedIdentifiertQuotedIdentifiertCommatColontLTtLTEtGTtGTEtEQtNEtJSONLiteraltStringLiteraltCurrenttExpreftAndtNottEOF"
8
9var _tokType_index = [...]uint8{0, 8, 13, 17, 24, 32, 39, 46, 55, 64, 71, 78, 81, 86, 93, 112, 129, 135, 141, 144, 148, 151, 155, 158, 161, 173, 187, 195, 202, 206, 210, 214}
10
11func (i tokType) String() string {
12 if i < 0 || i >= tokType(len(_tokType_index)-1) {
13 return fmt.Sprintf("tokType(%d)", i)
14 }
15 return _tokType_name[_tokType_index[i]:_tokType_index[i+1]]
16}
diff --git a/vendor/github.com/jmespath/go-jmespath/util.go b/vendor/github.com/jmespath/go-jmespath/util.go
new file mode 100644
index 0000000..ddc1b7d
--- /dev/null
+++ b/vendor/github.com/jmespath/go-jmespath/util.go
@@ -0,0 +1,185 @@
1package jmespath
2
3import (
4 "errors"
5 "reflect"
6)
7
8// IsFalse determines if an object is false based on the JMESPath spec.
9// JMESPath defines false values to be any of:
10// - An empty string array, or hash.
11// - The boolean value false.
12// - nil
13func isFalse(value interface{}) bool {
14 switch v := value.(type) {
15 case bool:
16 return !v
17 case []interface{}:
18 return len(v) == 0
19 case map[string]interface{}:
20 return len(v) == 0
21 case string:
22 return len(v) == 0
23 case nil:
24 return true
25 }
26 // Try the reflection cases before returning false.
27 rv := reflect.ValueOf(value)
28 switch rv.Kind() {
29 case reflect.Struct:
30 // A struct type will never be false, even if
31 // all of its values are the zero type.
32 return false
33 case reflect.Slice, reflect.Map:
34 return rv.Len() == 0
35 case reflect.Ptr:
36 if rv.IsNil() {
37 return true
38 }
39 // If it's a pointer type, we'll try to deref the pointer
40 // and evaluate the pointer value for isFalse.
41 element := rv.Elem()
42 return isFalse(element.Interface())
43 }
44 return false
45}
46
47// ObjsEqual is a generic object equality check.
48// It will take two arbitrary objects and recursively determine
49// if they are equal.
50func objsEqual(left interface{}, right interface{}) bool {
51 return reflect.DeepEqual(left, right)
52}
53
54// SliceParam refers to a single part of a slice.
55// A slice consists of a start, a stop, and a step, similar to
56// python slices.
57type sliceParam struct {
58 N int
59 Specified bool
60}
61
62// Slice supports [start:stop:step] style slicing that's supported in JMESPath.
63func slice(slice []interface{}, parts []sliceParam) ([]interface{}, error) {
64 computed, err := computeSliceParams(len(slice), parts)
65 if err != nil {
66 return nil, err
67 }
68 start, stop, step := computed[0], computed[1], computed[2]
69 result := []interface{}{}
70 if step > 0 {
71 for i := start; i < stop; i += step {
72 result = append(result, slice[i])
73 }
74 } else {
75 for i := start; i > stop; i += step {
76 result = append(result, slice[i])
77 }
78 }
79 return result, nil
80}
81
82func computeSliceParams(length int, parts []sliceParam) ([]int, error) {
83 var start, stop, step int
84 if !parts[2].Specified {
85 step = 1
86 } else if parts[2].N == 0 {
87 return nil, errors.New("Invalid slice, step cannot be 0")
88 } else {
89 step = parts[2].N
90 }
91 var stepValueNegative bool
92 if step < 0 {
93 stepValueNegative = true
94 } else {
95 stepValueNegative = false
96 }
97
98 if !parts[0].Specified {
99 if stepValueNegative {
100 start = length - 1
101 } else {
102 start = 0
103 }
104 } else {
105 start = capSlice(length, parts[0].N, step)
106 }
107
108 if !parts[1].Specified {
109 if stepValueNegative {
110 stop = -1
111 } else {
112 stop = length
113 }
114 } else {
115 stop = capSlice(length, parts[1].N, step)
116 }
117 return []int{start, stop, step}, nil
118}
119
120func capSlice(length int, actual int, step int) int {
121 if actual < 0 {
122 actual += length
123 if actual < 0 {
124 if step < 0 {
125 actual = -1
126 } else {
127 actual = 0
128 }
129 }
130 } else if actual >= length {
131 if step < 0 {
132 actual = length - 1
133 } else {
134 actual = length
135 }
136 }
137 return actual
138}
139
140// ToArrayNum converts an empty interface type to a slice of float64.
141// If any element in the array cannot be converted, then nil is returned
142// along with a second value of false.
143func toArrayNum(data interface{}) ([]float64, bool) {
144 // Is there a better way to do this with reflect?
145 if d, ok := data.([]interface{}); ok {
146 result := make([]float64, len(d))
147 for i, el := range d {
148 item, ok := el.(float64)
149 if !ok {
150 return nil, false
151 }
152 result[i] = item
153 }
154 return result, true
155 }
156 return nil, false
157}
158
159// ToArrayStr converts an empty interface type to a slice of strings.
160// If any element in the array cannot be converted, then nil is returned
161// along with a second value of false. If the input data could be entirely
162// converted, then the converted data, along with a second value of true,
163// will be returned.
164func toArrayStr(data interface{}) ([]string, bool) {
165 // Is there a better way to do this with reflect?
166 if d, ok := data.([]interface{}); ok {
167 result := make([]string, len(d))
168 for i, el := range d {
169 item, ok := el.(string)
170 if !ok {
171 return nil, false
172 }
173 result[i] = item
174 }
175 return result, true
176 }
177 return nil, false
178}
179
180func isSliceType(v interface{}) bool {
181 if v == nil {
182 return false
183 }
184 return reflect.TypeOf(v).Kind() == reflect.Slice
185}