mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-23 14:16:10 +00:00
wip - reduce!
This commit is contained in:
parent
4d6d07ec43
commit
c4faa70143
0
pkg/yqlib/doc/Reduce.md
Normal file
0
pkg/yqlib/doc/Reduce.md
Normal file
@ -13,185 +13,190 @@ var pathTests = []struct {
|
|||||||
expectedPostFix []interface{}
|
expectedPostFix []interface{}
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
`.a | .b | .c`,
|
`.[] as $item reduce (0; . + $item)`, // note - add code to shuffle reduce to this position for postfix
|
||||||
append(make([]interface{}, 0), "a", "PIPE", "b", "PIPE", "c"),
|
append(make([]interface{}, 0), "a", "ASSIGN_VARIABLE", "GET_VARIABLE", "REDUCE", "(", "b", ")"),
|
||||||
append(make([]interface{}, 0), "a", "b", "c", "PIPE", "PIPE"),
|
append(make([]interface{}, 0), "a", "GET_VARIABLE", "ASSIGN_VARIABLE", "b", "REDUCE"),
|
||||||
},
|
|
||||||
{
|
|
||||||
`[]`,
|
|
||||||
append(make([]interface{}, 0), "[", "EMPTY", "]"),
|
|
||||||
append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`{}`,
|
|
||||||
append(make([]interface{}, 0), "{", "EMPTY", "}"),
|
|
||||||
append(make([]interface{}, 0), "EMPTY", "COLLECT_OBJECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[{}]`,
|
|
||||||
append(make([]interface{}, 0), "[", "{", "EMPTY", "}", "]"),
|
|
||||||
append(make([]interface{}, 0), "EMPTY", "COLLECT_OBJECT", "SHORT_PIPE", "COLLECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.realnames as $names | $names["anon"]`,
|
|
||||||
append(make([]interface{}, 0), "realnames", "ASSIGN_VARIABLE", "GET_VARIABLE", "PIPE", "GET_VARIABLE", "TRAVERSE_ARRAY", "[", "anon (string)", "]"),
|
|
||||||
append(make([]interface{}, 0), "realnames", "GET_VARIABLE", "ASSIGN_VARIABLE", "GET_VARIABLE", "anon (string)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.b[.a]`,
|
|
||||||
append(make([]interface{}, 0), "b", "TRAVERSE_ARRAY", "[", "a", "]"),
|
|
||||||
append(make([]interface{}, 0), "b", "a", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.[]`,
|
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
|
||||||
append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a[]`,
|
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
|
||||||
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a.[]`,
|
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
|
||||||
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a[0]`,
|
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
|
||||||
append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a.[0]`,
|
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
|
||||||
append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a[].c`,
|
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "c"),
|
|
||||||
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "c", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[3]`,
|
|
||||||
append(make([]interface{}, 0), "[", "3 (int64)", "]"),
|
|
||||||
append(make([]interface{}, 0), "3 (int64)", "COLLECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.key.array + .key.array2`,
|
|
||||||
append(make([]interface{}, 0), "key", "SHORT_PIPE", "array", "ADD", "key", "SHORT_PIPE", "array2"),
|
|
||||||
append(make([]interface{}, 0), "key", "array", "SHORT_PIPE", "key", "array2", "SHORT_PIPE", "ADD"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.key.array * .key.array2`,
|
|
||||||
append(make([]interface{}, 0), "key", "SHORT_PIPE", "array", "MULTIPLY", "key", "SHORT_PIPE", "array2"),
|
|
||||||
append(make([]interface{}, 0), "key", "array", "SHORT_PIPE", "key", "array2", "SHORT_PIPE", "MULTIPLY"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.key.array // .key.array2`,
|
|
||||||
append(make([]interface{}, 0), "key", "SHORT_PIPE", "array", "ALTERNATIVE", "key", "SHORT_PIPE", "array2"),
|
|
||||||
append(make([]interface{}, 0), "key", "array", "SHORT_PIPE", "key", "array2", "SHORT_PIPE", "ALTERNATIVE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a | .[].b == "apple"`,
|
|
||||||
append(make([]interface{}, 0), "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", "EQUALS", "apple (string)"),
|
|
||||||
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "apple (string)", "EQUALS", "PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`(.a | .[].b) == "apple"`,
|
|
||||||
append(make([]interface{}, 0), "(", "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", ")", "EQUALS", "apple (string)"),
|
|
||||||
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "PIPE", "apple (string)", "EQUALS"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.[] | select(. == "*at")`,
|
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "PIPE", "SELECT", "(", "SELF", "EQUALS", "*at (string)", ")"),
|
|
||||||
append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SELF", "*at (string)", "EQUALS", "SELECT", "PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[true]`,
|
|
||||||
append(make([]interface{}, 0), "[", "true (bool)", "]"),
|
|
||||||
append(make([]interface{}, 0), "true (bool)", "COLLECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[true, false]`,
|
|
||||||
append(make([]interface{}, 0), "[", "true (bool)", "UNION", "false (bool)", "]"),
|
|
||||||
append(make([]interface{}, 0), "true (bool)", "false (bool)", "UNION", "COLLECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`"mike": .a`,
|
|
||||||
append(make([]interface{}, 0), "mike (string)", "CREATE_MAP", "a"),
|
|
||||||
append(make([]interface{}, 0), "mike (string)", "a", "CREATE_MAP"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a: "mike"`,
|
|
||||||
append(make([]interface{}, 0), "a", "CREATE_MAP", "mike (string)"),
|
|
||||||
append(make([]interface{}, 0), "a", "mike (string)", "CREATE_MAP"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`{"mike": .a}`,
|
|
||||||
append(make([]interface{}, 0), "{", "mike (string)", "CREATE_MAP", "a", "}"),
|
|
||||||
append(make([]interface{}, 0), "mike (string)", "a", "CREATE_MAP", "COLLECT_OBJECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`{.a: "mike"}`,
|
|
||||||
append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "mike (string)", "}"),
|
|
||||||
append(make([]interface{}, 0), "a", "mike (string)", "CREATE_MAP", "COLLECT_OBJECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`{.a: .c, .b.[]: .f.g[]}`,
|
|
||||||
append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "c", "UNION", "b", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "CREATE_MAP", "f", "SHORT_PIPE", "g", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "}"),
|
|
||||||
append(make([]interface{}, 0), "a", "c", "CREATE_MAP", "b", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "f", "g", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SHORT_PIPE", "CREATE_MAP", "UNION", "COLLECT_OBJECT", "SHORT_PIPE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`explode(.a.b)`,
|
|
||||||
append(make([]interface{}, 0), "EXPLODE", "(", "a", "SHORT_PIPE", "b", ")"),
|
|
||||||
append(make([]interface{}, 0), "a", "b", "SHORT_PIPE", "EXPLODE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a.b style="folded"`,
|
|
||||||
append(make([]interface{}, 0), "a", "SHORT_PIPE", "b", "ASSIGN_STYLE", "folded (string)"),
|
|
||||||
append(make([]interface{}, 0), "a", "b", "SHORT_PIPE", "folded (string)", "ASSIGN_STYLE"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`tag == "str"`,
|
|
||||||
append(make([]interface{}, 0), "GET_TAG", "EQUALS", "str (string)"),
|
|
||||||
append(make([]interface{}, 0), "GET_TAG", "str (string)", "EQUALS"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`. tag= "str"`,
|
|
||||||
append(make([]interface{}, 0), "SELF", "ASSIGN_TAG", "str (string)"),
|
|
||||||
append(make([]interface{}, 0), "SELF", "str (string)", "ASSIGN_TAG"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`lineComment == "str"`,
|
|
||||||
append(make([]interface{}, 0), "GET_COMMENT", "EQUALS", "str (string)"),
|
|
||||||
append(make([]interface{}, 0), "GET_COMMENT", "str (string)", "EQUALS"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`. lineComment= "str"`,
|
|
||||||
append(make([]interface{}, 0), "SELF", "ASSIGN_COMMENT", "str (string)"),
|
|
||||||
append(make([]interface{}, 0), "SELF", "str (string)", "ASSIGN_COMMENT"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`. lineComment |= "str"`,
|
|
||||||
append(make([]interface{}, 0), "SELF", "ASSIGN_COMMENT", "str (string)"),
|
|
||||||
append(make([]interface{}, 0), "SELF", "str (string)", "ASSIGN_COMMENT"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.a.b tag="!!str"`,
|
|
||||||
append(make([]interface{}, 0), "a", "SHORT_PIPE", "b", "ASSIGN_TAG", "!!str (string)"),
|
|
||||||
append(make([]interface{}, 0), "a", "b", "SHORT_PIPE", "!!str (string)", "ASSIGN_TAG"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`""`,
|
|
||||||
append(make([]interface{}, 0), " (string)"),
|
|
||||||
append(make([]interface{}, 0), " (string)"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`.foo* | (. style="flow")`,
|
|
||||||
append(make([]interface{}, 0), "foo*", "PIPE", "(", "SELF", "ASSIGN_STYLE", "flow (string)", ")"),
|
|
||||||
append(make([]interface{}, 0), "foo*", "SELF", "flow (string)", "ASSIGN_STYLE", "PIPE"),
|
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// `.a | .b | .c`,
|
||||||
|
// append(make([]interface{}, 0), "a", "PIPE", "b", "PIPE", "c"),
|
||||||
|
// append(make([]interface{}, 0), "a", "b", "c", "PIPE", "PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `[]`,
|
||||||
|
// append(make([]interface{}, 0), "[", "EMPTY", "]"),
|
||||||
|
// append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `{}`,
|
||||||
|
// append(make([]interface{}, 0), "{", "EMPTY", "}"),
|
||||||
|
// append(make([]interface{}, 0), "EMPTY", "COLLECT_OBJECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `[{}]`,
|
||||||
|
// append(make([]interface{}, 0), "[", "{", "EMPTY", "}", "]"),
|
||||||
|
// append(make([]interface{}, 0), "EMPTY", "COLLECT_OBJECT", "SHORT_PIPE", "COLLECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.realnames as $names | $names["anon"]`,
|
||||||
|
// append(make([]interface{}, 0), "realnames", "ASSIGN_VARIABLE", "GET_VARIABLE", "PIPE", "GET_VARIABLE", "TRAVERSE_ARRAY", "[", "anon (string)", "]"),
|
||||||
|
// append(make([]interface{}, 0), "realnames", "GET_VARIABLE", "ASSIGN_VARIABLE", "GET_VARIABLE", "anon (string)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.b[.a]`,
|
||||||
|
// append(make([]interface{}, 0), "b", "TRAVERSE_ARRAY", "[", "a", "]"),
|
||||||
|
// append(make([]interface{}, 0), "b", "a", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.[]`,
|
||||||
|
// append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
||||||
|
// append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a[]`,
|
||||||
|
// append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
||||||
|
// append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a.[]`,
|
||||||
|
// append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
||||||
|
// append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a[0]`,
|
||||||
|
// append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
||||||
|
// append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a.[0]`,
|
||||||
|
// append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
||||||
|
// append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a[].c`,
|
||||||
|
// append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "c"),
|
||||||
|
// append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "c", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `[3]`,
|
||||||
|
// append(make([]interface{}, 0), "[", "3 (int64)", "]"),
|
||||||
|
// append(make([]interface{}, 0), "3 (int64)", "COLLECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.key.array + .key.array2`,
|
||||||
|
// append(make([]interface{}, 0), "key", "SHORT_PIPE", "array", "ADD", "key", "SHORT_PIPE", "array2"),
|
||||||
|
// append(make([]interface{}, 0), "key", "array", "SHORT_PIPE", "key", "array2", "SHORT_PIPE", "ADD"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.key.array * .key.array2`,
|
||||||
|
// append(make([]interface{}, 0), "key", "SHORT_PIPE", "array", "MULTIPLY", "key", "SHORT_PIPE", "array2"),
|
||||||
|
// append(make([]interface{}, 0), "key", "array", "SHORT_PIPE", "key", "array2", "SHORT_PIPE", "MULTIPLY"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.key.array // .key.array2`,
|
||||||
|
// append(make([]interface{}, 0), "key", "SHORT_PIPE", "array", "ALTERNATIVE", "key", "SHORT_PIPE", "array2"),
|
||||||
|
// append(make([]interface{}, 0), "key", "array", "SHORT_PIPE", "key", "array2", "SHORT_PIPE", "ALTERNATIVE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a | .[].b == "apple"`,
|
||||||
|
// append(make([]interface{}, 0), "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", "EQUALS", "apple (string)"),
|
||||||
|
// append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "apple (string)", "EQUALS", "PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `(.a | .[].b) == "apple"`,
|
||||||
|
// append(make([]interface{}, 0), "(", "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", ")", "EQUALS", "apple (string)"),
|
||||||
|
// append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "PIPE", "apple (string)", "EQUALS"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.[] | select(. == "*at")`,
|
||||||
|
// append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "PIPE", "SELECT", "(", "SELF", "EQUALS", "*at (string)", ")"),
|
||||||
|
// append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SELF", "*at (string)", "EQUALS", "SELECT", "PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `[true]`,
|
||||||
|
// append(make([]interface{}, 0), "[", "true (bool)", "]"),
|
||||||
|
// append(make([]interface{}, 0), "true (bool)", "COLLECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `[true, false]`,
|
||||||
|
// append(make([]interface{}, 0), "[", "true (bool)", "UNION", "false (bool)", "]"),
|
||||||
|
// append(make([]interface{}, 0), "true (bool)", "false (bool)", "UNION", "COLLECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `"mike": .a`,
|
||||||
|
// append(make([]interface{}, 0), "mike (string)", "CREATE_MAP", "a"),
|
||||||
|
// append(make([]interface{}, 0), "mike (string)", "a", "CREATE_MAP"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a: "mike"`,
|
||||||
|
// append(make([]interface{}, 0), "a", "CREATE_MAP", "mike (string)"),
|
||||||
|
// append(make([]interface{}, 0), "a", "mike (string)", "CREATE_MAP"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `{"mike": .a}`,
|
||||||
|
// append(make([]interface{}, 0), "{", "mike (string)", "CREATE_MAP", "a", "}"),
|
||||||
|
// append(make([]interface{}, 0), "mike (string)", "a", "CREATE_MAP", "COLLECT_OBJECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `{.a: "mike"}`,
|
||||||
|
// append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "mike (string)", "}"),
|
||||||
|
// append(make([]interface{}, 0), "a", "mike (string)", "CREATE_MAP", "COLLECT_OBJECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `{.a: .c, .b.[]: .f.g[]}`,
|
||||||
|
// append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "c", "UNION", "b", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "CREATE_MAP", "f", "SHORT_PIPE", "g", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "}"),
|
||||||
|
// append(make([]interface{}, 0), "a", "c", "CREATE_MAP", "b", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "f", "g", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SHORT_PIPE", "CREATE_MAP", "UNION", "COLLECT_OBJECT", "SHORT_PIPE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `explode(.a.b)`,
|
||||||
|
// append(make([]interface{}, 0), "EXPLODE", "(", "a", "SHORT_PIPE", "b", ")"),
|
||||||
|
// append(make([]interface{}, 0), "a", "b", "SHORT_PIPE", "EXPLODE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a.b style="folded"`,
|
||||||
|
// append(make([]interface{}, 0), "a", "SHORT_PIPE", "b", "ASSIGN_STYLE", "folded (string)"),
|
||||||
|
// append(make([]interface{}, 0), "a", "b", "SHORT_PIPE", "folded (string)", "ASSIGN_STYLE"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `tag == "str"`,
|
||||||
|
// append(make([]interface{}, 0), "GET_TAG", "EQUALS", "str (string)"),
|
||||||
|
// append(make([]interface{}, 0), "GET_TAG", "str (string)", "EQUALS"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `. tag= "str"`,
|
||||||
|
// append(make([]interface{}, 0), "SELF", "ASSIGN_TAG", "str (string)"),
|
||||||
|
// append(make([]interface{}, 0), "SELF", "str (string)", "ASSIGN_TAG"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `lineComment == "str"`,
|
||||||
|
// append(make([]interface{}, 0), "GET_COMMENT", "EQUALS", "str (string)"),
|
||||||
|
// append(make([]interface{}, 0), "GET_COMMENT", "str (string)", "EQUALS"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `. lineComment= "str"`,
|
||||||
|
// append(make([]interface{}, 0), "SELF", "ASSIGN_COMMENT", "str (string)"),
|
||||||
|
// append(make([]interface{}, 0), "SELF", "str (string)", "ASSIGN_COMMENT"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `. lineComment |= "str"`,
|
||||||
|
// append(make([]interface{}, 0), "SELF", "ASSIGN_COMMENT", "str (string)"),
|
||||||
|
// append(make([]interface{}, 0), "SELF", "str (string)", "ASSIGN_COMMENT"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.a.b tag="!!str"`,
|
||||||
|
// append(make([]interface{}, 0), "a", "SHORT_PIPE", "b", "ASSIGN_TAG", "!!str (string)"),
|
||||||
|
// append(make([]interface{}, 0), "a", "b", "SHORT_PIPE", "!!str (string)", "ASSIGN_TAG"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `""`,
|
||||||
|
// append(make([]interface{}, 0), " (string)"),
|
||||||
|
// append(make([]interface{}, 0), " (string)"),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// `.foo* | (. style="flow")`,
|
||||||
|
// append(make([]interface{}, 0), "foo*", "PIPE", "(", "SELF", "ASSIGN_STYLE", "flow (string)", ")"),
|
||||||
|
// append(make([]interface{}, 0), "foo*", "SELF", "flow (string)", "ASSIGN_STYLE", "PIPE"),
|
||||||
|
// },
|
||||||
}
|
}
|
||||||
|
|
||||||
var tokeniser = newExpressionTokeniser()
|
var tokeniser = newExpressionTokeniser()
|
||||||
|
@ -252,6 +252,8 @@ func initLexer() (*lex.Lexer, error) {
|
|||||||
lexer.Add([]byte(`or`), opToken(orOpType))
|
lexer.Add([]byte(`or`), opToken(orOpType))
|
||||||
lexer.Add([]byte(`and`), opToken(andOpType))
|
lexer.Add([]byte(`and`), opToken(andOpType))
|
||||||
lexer.Add([]byte(`not`), opToken(notOpType))
|
lexer.Add([]byte(`not`), opToken(notOpType))
|
||||||
|
lexer.Add([]byte(`reduce`), opToken(reduceOpType))
|
||||||
|
lexer.Add([]byte(`;`), opToken(blockOpType))
|
||||||
lexer.Add([]byte(`\/\/`), opToken(alternativeOpType))
|
lexer.Add([]byte(`\/\/`), opToken(alternativeOpType))
|
||||||
|
|
||||||
lexer.Add([]byte(`documentIndex`), opToken(getDocumentIndexOpType))
|
lexer.Add([]byte(`documentIndex`), opToken(getDocumentIndexOpType))
|
||||||
|
@ -25,6 +25,9 @@ type operationType struct {
|
|||||||
|
|
||||||
var orOpType = &operationType{Type: "OR", NumArgs: 2, Precedence: 20, Handler: orOperator}
|
var orOpType = &operationType{Type: "OR", NumArgs: 2, Precedence: 20, Handler: orOperator}
|
||||||
var andOpType = &operationType{Type: "AND", NumArgs: 2, Precedence: 20, Handler: andOperator}
|
var andOpType = &operationType{Type: "AND", NumArgs: 2, Precedence: 20, Handler: andOperator}
|
||||||
|
var reduceOpType = &operationType{Type: "REDUCE", NumArgs: 2, Precedence: 5, Handler: reduceOperator}
|
||||||
|
|
||||||
|
var blockOpType = &operationType{Type: "BLOCK", Precedence: 10, NumArgs: 2, Handler: emptyOperator}
|
||||||
|
|
||||||
var unionOpType = &operationType{Type: "UNION", NumArgs: 2, Precedence: 10, Handler: unionOperator}
|
var unionOpType = &operationType{Type: "UNION", NumArgs: 2, Precedence: 10, Handler: unionOperator}
|
||||||
|
|
||||||
@ -80,7 +83,7 @@ var selfReferenceOpType = &operationType{Type: "SELF", NumArgs: 0, Precedence: 5
|
|||||||
var valueOpType = &operationType{Type: "VALUE", NumArgs: 0, Precedence: 50, Handler: valueOperator}
|
var valueOpType = &operationType{Type: "VALUE", NumArgs: 0, Precedence: 50, Handler: valueOperator}
|
||||||
var envOpType = &operationType{Type: "ENV", NumArgs: 0, Precedence: 50, Handler: envOperator}
|
var envOpType = &operationType{Type: "ENV", NumArgs: 0, Precedence: 50, Handler: envOperator}
|
||||||
var notOpType = &operationType{Type: "NOT", NumArgs: 0, Precedence: 50, Handler: notOperator}
|
var notOpType = &operationType{Type: "NOT", NumArgs: 0, Precedence: 50, Handler: notOperator}
|
||||||
var emptyOpType = &operationType{Type: "EMPTY", NumArgs: 50, Handler: emptyOperator}
|
var emptyOpType = &operationType{Type: "EMPTY", Precedence: 50, Handler: emptyOperator}
|
||||||
|
|
||||||
var recursiveDescentOpType = &operationType{Type: "RECURSIVE_DESCENT", NumArgs: 0, Precedence: 50, Handler: recursiveDescentOperator}
|
var recursiveDescentOpType = &operationType{Type: "RECURSIVE_DESCENT", NumArgs: 0, Precedence: 50, Handler: recursiveDescentOperator}
|
||||||
|
|
||||||
|
59
pkg/yqlib/operator_reduce.go
Normal file
59
pkg/yqlib/operator_reduce.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/list"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func reduceOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
|
log.Debugf("-- reduceOp")
|
||||||
|
//.a as $var reduce (0; . + $var)
|
||||||
|
//lhs is the assignment operator
|
||||||
|
//rhs is the reduce block
|
||||||
|
// '.' refers to the current accumulator, initialised to 0
|
||||||
|
// $var references a single element from the .a
|
||||||
|
|
||||||
|
//ensure lhs is actually an assignment
|
||||||
|
//and rhs is a block (empty)
|
||||||
|
if expressionNode.Lhs.Operation.OperationType != assignVariableOpType {
|
||||||
|
return Context{}, fmt.Errorf("reduce must be given a variables assignment, got %v instead", expressionNode.Lhs.Operation.OperationType.Type)
|
||||||
|
} else if expressionNode.Rhs.Operation.OperationType != blockOpType {
|
||||||
|
return Context{}, fmt.Errorf("reduce must be given a block, got %v instead", expressionNode.Rhs.Operation.OperationType.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayExpNode := expressionNode.Lhs.Lhs
|
||||||
|
array, err := d.GetMatchingNodes(context, arrayExpNode)
|
||||||
|
|
||||||
|
log.Debugf("array of %v things", array.MatchingNodes.Len())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
variableName := expressionNode.Lhs.Rhs.Operation.StringValue
|
||||||
|
|
||||||
|
initExp := expressionNode.Rhs.Lhs
|
||||||
|
|
||||||
|
accum, err := d.GetMatchingNodes(context, initExp)
|
||||||
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("with variable %v", variableName)
|
||||||
|
|
||||||
|
blockExp := expressionNode.Rhs.Rhs
|
||||||
|
for el := array.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
log.Debugf("REDUCING WITH %v", NodeToString(candidate))
|
||||||
|
l := list.New()
|
||||||
|
l.PushBack(candidate)
|
||||||
|
accum.SetVariable(variableName, l)
|
||||||
|
|
||||||
|
accum, err = d.GetMatchingNodes(accum, blockExp)
|
||||||
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return accum, nil
|
||||||
|
}
|
22
pkg/yqlib/operator_reduce_test.go
Normal file
22
pkg/yqlib/operator_reduce_test.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var reduceOperatorScenarios = []expressionScenario{
|
||||||
|
{
|
||||||
|
document: `[10,2, 5, 3]`,
|
||||||
|
expression: `.[] as $item reduce (0; . + $item)`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!int)::20\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReduceOperatorScenarios(t *testing.T) {
|
||||||
|
for _, tt := range reduceOperatorScenarios {
|
||||||
|
testScenario(t, &tt)
|
||||||
|
}
|
||||||
|
// documentScenarios(t, "Reduce", reduceOperatorScenarios)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user