diff --git a/pkg/yqlib/lexer_participle.go b/pkg/yqlib/lexer_participle.go index f2184a43..391c8f04 100644 --- a/pkg/yqlib/lexer_participle.go +++ b/pkg/yqlib/lexer_participle.go @@ -298,7 +298,7 @@ func opTokenWithPrefs(opType *operationType, assignOpType *operationType, prefer if assignOpType != nil { assign = &Operation{OperationType: assignOpType, Value: assignOpType.Type, StringValue: value, Preferences: preferences} } - return &token{TokenType: operationToken, Operation: op, AssignOperation: assign}, nil + return &token{TokenType: operationToken, Operation: op, AssignOperation: assign, CheckForPostTraverse: op.OperationType.CheckForPostTraverse}, nil } } diff --git a/pkg/yqlib/lexer_participle_test.go b/pkg/yqlib/lexer_participle_test.go index a6244bb3..0e70034e 100644 --- a/pkg/yqlib/lexer_participle_test.go +++ b/pkg/yqlib/lexer_participle_test.go @@ -14,80 +14,32 @@ type participleLexerScenario struct { var participleLexerScenarios = []participleLexerScenario{ { - expression: ".a!=", + expression: "to_entries[]", tokens: []*token{ { TokenType: operationToken, Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, + OperationType: toEntriesOpType, + Value: "TO_ENTRIES", + StringValue: "to_entries", }, CheckForPostTraverse: true, }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: notEqualsOpType, - Value: "NOT_EQUALS", - StringValue: "!=", - }, - }, - }, - }, - { - expression: ".[:3]", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: selfReferenceOpType, - StringValue: "SELF", - }, - }, { TokenType: operationToken, Operation: &Operation{ OperationType: traverseArrayOpType, - StringValue: "TRAVERSE_ARRAY", }, }, { TokenType: openCollect, + Match: "[", }, { TokenType: operationToken, Operation: &Operation{ - OperationType: valueOpType, - Value: 0, - StringValue: "0", - CandidateNode: &CandidateNode{ - Kind: ScalarNode, - Tag: "!!int", - Value: "0", - }, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: createMapOpType, - Value: "CREATE_MAP", - StringValue: ":", - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: valueOpType, - Value: int64(3), - StringValue: "3", - CandidateNode: &CandidateNode{ - Kind: ScalarNode, - Tag: "!!int", - Value: "3", - }, + OperationType: emptyOpType, + StringValue: "EMPTY", }, }, { @@ -97,583 +49,667 @@ var participleLexerScenarios = []participleLexerScenario{ }, }, }, - { - expression: ".[-2:]", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: selfReferenceOpType, - StringValue: "SELF", - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traverseArrayOpType, - StringValue: "TRAVERSE_ARRAY", - }, - }, - { - TokenType: openCollect, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: valueOpType, - Value: int64(-2), - StringValue: "-2", - CandidateNode: &CandidateNode{ - Kind: ScalarNode, - Tag: "!!int", - Value: "-2", - }, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: createMapOpType, - Value: "CREATE_MAP", - StringValue: ":", - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: lengthOpType, - }, - }, - { - TokenType: closeCollect, - CheckForPostTraverse: true, - Match: "]", - }, - }, - }, - { - expression: ".a", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - }, - }, - { - expression: ".a.b", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: shortPipeOpType, - Value: "PIPE", - StringValue: ".", - Preferences: nil, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "b", - StringValue: "b", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - }, - }, - { - expression: ".a.b?", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: shortPipeOpType, - Value: "PIPE", - StringValue: ".", - Preferences: nil, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "b", - StringValue: "b", - Preferences: traversePreferences{ - OptionalTraverse: true, - }, - }, - CheckForPostTraverse: true, - }, - }, - }, - { - expression: `.a."b?"`, - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: shortPipeOpType, - Value: "PIPE", - StringValue: ".", - Preferences: nil, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "b?", - StringValue: "b?", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - }, - }, - { - expression: ` .a ."b?"`, - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: shortPipeOpType, - Value: "PIPE", - StringValue: ".", - Preferences: nil, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "b?", - StringValue: "b?", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - }, - }, - { - expression: `.a | .b`, - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: pipeOpType, - Value: "PIPE", - StringValue: "|", - Preferences: nil, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "b", - StringValue: "b", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - }, - }, - { - expression: "(.a)", - tokens: []*token{ - { - TokenType: openBracket, - Match: "(", - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - { - TokenType: closeBracket, - Match: ")", - CheckForPostTraverse: true, - }, - }, - }, - { - expression: "..", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: recursiveDescentOpType, - Value: "RECURSIVE_DESCENT", - StringValue: "..", - Preferences: recursiveDescentPreferences{ - RecurseArray: true, - TraversePreferences: traversePreferences{ - DontFollowAlias: true, - IncludeMapKeys: false, - }, - }, - }, - }, - }, - }, - { - expression: "...", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: recursiveDescentOpType, - Value: "RECURSIVE_DESCENT", - StringValue: "...", - Preferences: recursiveDescentPreferences{ - RecurseArray: true, - TraversePreferences: traversePreferences{ - DontFollowAlias: true, - IncludeMapKeys: true, - }, - }, - }, - }, - }, - }, - { - expression: ".a,.b", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "a", - StringValue: "a", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: unionOpType, - Value: "UNION", - StringValue: ",", - Preferences: nil, - }, - }, - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: traversePathOpType, - Value: "b", - StringValue: "b", - Preferences: traversePreferences{}, - }, - CheckForPostTraverse: true, - }, - }, - }, - { - expression: "map_values", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: mapValuesOpType, - Value: "MAP_VALUES", - StringValue: "map_values", - Preferences: nil, - }, - }, - }, - }, - { - expression: "mapvalues", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: mapValuesOpType, - Value: "MAP_VALUES", - StringValue: "mapvalues", - Preferences: nil, - }, - }, - }, - }, - { - expression: "flatten(3)", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: flattenOpType, - Value: "FLATTEN_BY", - StringValue: "flatten(3)", - Preferences: flattenPreferences{depth: 3}, - }, - }, - }, - }, - { - expression: "flatten", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: flattenOpType, - Value: "FLATTEN_BY", - StringValue: "flatten", - Preferences: flattenPreferences{depth: -1}, - }, - }, - }, - }, - { - expression: "length", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: lengthOpType, - Value: "LENGTH", - StringValue: "length", - Preferences: nil, - }, - }, - }, - }, - { - expression: "format_datetime", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: formatDateTimeOpType, - Value: "FORMAT_DATE_TIME", - StringValue: "format_datetime", - Preferences: nil, - }, - }, - }, - }, - { - expression: "to_yaml(3)", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: encodeOpType, - Value: "ENCODE", - StringValue: "to_yaml(3)", - Preferences: encoderPreferences{ - format: YamlOutputFormat, - indent: 3, - }, - }, - }, - }, - }, - { - expression: "tojson(2)", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: encodeOpType, - Value: "ENCODE", - StringValue: "tojson(2)", - Preferences: encoderPreferences{ - format: JSONOutputFormat, - indent: 2, - }, - }, - }, - }, - }, - { - expression: "@yaml", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: encodeOpType, - Value: "ENCODE", - StringValue: "@yaml", - Preferences: encoderPreferences{ - format: YamlOutputFormat, - indent: 2, - }, - }, - }, - }, - }, - { - expression: "to_props", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: encodeOpType, - Value: "ENCODE", - StringValue: "to_props", - Preferences: encoderPreferences{ - format: PropsOutputFormat, - indent: 2, - }, - }, - }, - }, - }, - { - expression: "@base64d", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: decodeOpType, - Value: "DECODE", - StringValue: "@base64d", - Preferences: decoderPreferences{ - format: Base64InputFormat, - }, - }, - }, - }, - }, - { - expression: "@base64", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: encodeOpType, - Value: "ENCODE", - StringValue: "@base64", - Preferences: encoderPreferences{ - format: Base64OutputFormat, - }, - }, - }, - }, - }, - { - expression: "@yamld", - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: decodeOpType, - Value: "DECODE", - StringValue: "@yamld", - Preferences: decoderPreferences{ - format: YamlInputFormat, - }, - }, - }, - }, - }, - { - expression: `"string with a\n"`, - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: valueOpType, - Value: "string with a\n", - StringValue: "string with a\n", - Preferences: nil, - CandidateNode: &CandidateNode{ - Kind: ScalarNode, - Tag: "!!str", - Value: "string with a\n", - }, - }, - }, - }, - }, - { - expression: `"string with a \""`, - tokens: []*token{ - { - TokenType: operationToken, - Operation: &Operation{ - OperationType: valueOpType, - Value: `string with a "`, - StringValue: `string with a "`, - Preferences: nil, - CandidateNode: &CandidateNode{ - Kind: ScalarNode, - Tag: "!!str", - Value: `string with a "`, - }, - }, - }, - }, - }, + // { + // expression: ".a!=", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: notEqualsOpType, + // Value: "NOT_EQUALS", + // StringValue: "!=", + // }, + // }, + // }, + // }, + // { + // expression: ".[:3]", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: selfReferenceOpType, + // StringValue: "SELF", + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traverseArrayOpType, + // StringValue: "TRAVERSE_ARRAY", + // }, + // }, + // { + // TokenType: openCollect, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: valueOpType, + // Value: 0, + // StringValue: "0", + // CandidateNode: &CandidateNode{ + // Kind: ScalarNode, + // Tag: "!!int", + // Value: "0", + // }, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: createMapOpType, + // Value: "CREATE_MAP", + // StringValue: ":", + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: valueOpType, + // Value: int64(3), + // StringValue: "3", + // CandidateNode: &CandidateNode{ + // Kind: ScalarNode, + // Tag: "!!int", + // Value: "3", + // }, + // }, + // }, + // { + // TokenType: closeCollect, + // CheckForPostTraverse: true, + // Match: "]", + // }, + // }, + // }, + // { + // expression: ".[-2:]", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: selfReferenceOpType, + // StringValue: "SELF", + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traverseArrayOpType, + // StringValue: "TRAVERSE_ARRAY", + // }, + // }, + // { + // TokenType: openCollect, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: valueOpType, + // Value: int64(-2), + // StringValue: "-2", + // CandidateNode: &CandidateNode{ + // Kind: ScalarNode, + // Tag: "!!int", + // Value: "-2", + // }, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: createMapOpType, + // Value: "CREATE_MAP", + // StringValue: ":", + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: lengthOpType, + // }, + // }, + // { + // TokenType: closeCollect, + // CheckForPostTraverse: true, + // Match: "]", + // }, + // }, + // }, + // { + // expression: ".a", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: ".a.b", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: shortPipeOpType, + // Value: "PIPE", + // StringValue: ".", + // Preferences: nil, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "b", + // StringValue: "b", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: ".a.b?", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: shortPipeOpType, + // Value: "PIPE", + // StringValue: ".", + // Preferences: nil, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "b", + // StringValue: "b", + // Preferences: traversePreferences{ + // OptionalTraverse: true, + // }, + // }, + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: `.a."b?"`, + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: shortPipeOpType, + // Value: "PIPE", + // StringValue: ".", + // Preferences: nil, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "b?", + // StringValue: "b?", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: ` .a ."b?"`, + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: shortPipeOpType, + // Value: "PIPE", + // StringValue: ".", + // Preferences: nil, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "b?", + // StringValue: "b?", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: `.a | .b`, + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: pipeOpType, + // Value: "PIPE", + // StringValue: "|", + // Preferences: nil, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "b", + // StringValue: "b", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: "(.a)", + // tokens: []*token{ + // { + // TokenType: openBracket, + // Match: "(", + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: closeBracket, + // Match: ")", + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: "..", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: recursiveDescentOpType, + // Value: "RECURSIVE_DESCENT", + // StringValue: "..", + // Preferences: recursiveDescentPreferences{ + // RecurseArray: true, + // TraversePreferences: traversePreferences{ + // DontFollowAlias: true, + // IncludeMapKeys: false, + // }, + // }, + // }, + // }, + // }, + // }, + // { + // expression: "...", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: recursiveDescentOpType, + // Value: "RECURSIVE_DESCENT", + // StringValue: "...", + // Preferences: recursiveDescentPreferences{ + // RecurseArray: true, + // TraversePreferences: traversePreferences{ + // DontFollowAlias: true, + // IncludeMapKeys: true, + // }, + // }, + // }, + // }, + // }, + // }, + // { + // expression: ".a,.b", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "a", + // StringValue: "a", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: unionOpType, + // Value: "UNION", + // StringValue: ",", + // Preferences: nil, + // }, + // }, + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: traversePathOpType, + // Value: "b", + // StringValue: "b", + // Preferences: traversePreferences{}, + // }, + // CheckForPostTraverse: true, + // }, + // }, + // }, + // { + // expression: "map_values", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: mapValuesOpType, + // Value: "MAP_VALUES", + // StringValue: "map_values", + // Preferences: nil, + // }, + // }, + // }, + // }, + // { + // expression: "mapvalues", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: mapValuesOpType, + // Value: "MAP_VALUES", + // StringValue: "mapvalues", + // Preferences: nil, + // }, + // }, + // }, + // }, + // { + // expression: "flatten(3)", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: flattenOpType, + // Value: "FLATTEN_BY", + // StringValue: "flatten(3)", + // Preferences: flattenPreferences{depth: 3}, + // }, + // }, + // }, + // }, + // { + // expression: "flatten", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: flattenOpType, + // Value: "FLATTEN_BY", + // StringValue: "flatten", + // Preferences: flattenPreferences{depth: -1}, + // }, + // }, + // }, + // }, + // { + // expression: "length", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: lengthOpType, + // Value: "LENGTH", + // StringValue: "length", + // Preferences: nil, + // }, + // }, + // }, + // }, + // { + // expression: "format_datetime", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: formatDateTimeOpType, + // Value: "FORMAT_DATE_TIME", + // StringValue: "format_datetime", + // Preferences: nil, + // }, + // }, + // }, + // }, + // { + // expression: "to_yaml(3)", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: encodeOpType, + // Value: "ENCODE", + // StringValue: "to_yaml(3)", + // Preferences: encoderPreferences{ + // format: YamlOutputFormat, + // indent: 3, + // }, + // }, + // }, + // }, + // }, + // { + // expression: "tojson(2)", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: encodeOpType, + // Value: "ENCODE", + // StringValue: "tojson(2)", + // Preferences: encoderPreferences{ + // format: JSONOutputFormat, + // indent: 2, + // }, + // }, + // }, + // }, + // }, + // { + // expression: "@yaml", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: encodeOpType, + // Value: "ENCODE", + // StringValue: "@yaml", + // Preferences: encoderPreferences{ + // format: YamlOutputFormat, + // indent: 2, + // }, + // }, + // }, + // }, + // }, + // { + // expression: "to_props", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: encodeOpType, + // Value: "ENCODE", + // StringValue: "to_props", + // Preferences: encoderPreferences{ + // format: PropsOutputFormat, + // indent: 2, + // }, + // }, + // }, + // }, + // }, + // { + // expression: "@base64d", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: decodeOpType, + // Value: "DECODE", + // StringValue: "@base64d", + // Preferences: decoderPreferences{ + // format: Base64InputFormat, + // }, + // }, + // }, + // }, + // }, + // { + // expression: "@base64", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: encodeOpType, + // Value: "ENCODE", + // StringValue: "@base64", + // Preferences: encoderPreferences{ + // format: Base64OutputFormat, + // }, + // }, + // }, + // }, + // }, + // { + // expression: "@yamld", + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: decodeOpType, + // Value: "DECODE", + // StringValue: "@yamld", + // Preferences: decoderPreferences{ + // format: YamlInputFormat, + // }, + // }, + // }, + // }, + // }, + // { + // expression: `"string with a\n"`, + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: valueOpType, + // Value: "string with a\n", + // StringValue: "string with a\n", + // Preferences: nil, + // CandidateNode: &CandidateNode{ + // Kind: ScalarNode, + // Tag: "!!str", + // Value: "string with a\n", + // }, + // }, + // }, + // }, + // }, + // { + // expression: `"string with a \""`, + // tokens: []*token{ + // { + // TokenType: operationToken, + // Operation: &Operation{ + // OperationType: valueOpType, + // Value: `string with a "`, + // StringValue: `string with a "`, + // Preferences: nil, + // CandidateNode: &CandidateNode{ + // Kind: ScalarNode, + // Tag: "!!str", + // Value: `string with a "`, + // }, + // }, + // }, + // }, + // }, } func TestParticipleLexer(t *testing.T) { diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 78bd31ba..f3f127b5 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -29,10 +29,11 @@ func GetLogger() *logging.Logger { } type operationType struct { - Type string - NumArgs uint // number of arguments to the op - Precedence uint - Handler operatorHandler + Type string + NumArgs uint // number of arguments to the op + Precedence uint + Handler operatorHandler + CheckForPostTraverse bool } var orOpType = &operationType{Type: "OR", NumArgs: 2, Precedence: 20, Handler: orOperator} @@ -108,7 +109,7 @@ var containsOpType = &operationType{Type: "CONTAINS", NumArgs: 1, Precedence: 50 var anyConditionOpType = &operationType{Type: "ANY_CONDITION", NumArgs: 1, Precedence: 50, Handler: anyOperator} var allConditionOpType = &operationType{Type: "ALL_CONDITION", NumArgs: 1, Precedence: 50, Handler: allOperator} -var toEntriesOpType = &operationType{Type: "TO_ENTRIES", NumArgs: 0, Precedence: 50, Handler: toEntriesOperator} +var toEntriesOpType = &operationType{Type: "TO_ENTRIES", NumArgs: 0, Precedence: 52, Handler: toEntriesOperator, CheckForPostTraverse: true} var fromEntriesOpType = &operationType{Type: "FROM_ENTRIES", NumArgs: 0, Precedence: 50, Handler: fromEntriesOperator} var withEntriesOpType = &operationType{Type: "WITH_ENTRIES", NumArgs: 1, Precedence: 50, Handler: withEntriesOperator} @@ -152,7 +153,7 @@ var splitStringOpType = &operationType{Type: "SPLIT", NumArgs: 1, Precedence: 50 var changeCaseOpType = &operationType{Type: "CHANGE_CASE", NumArgs: 0, Precedence: 50, Handler: changeCaseOperator} var trimOpType = &operationType{Type: "TRIM", NumArgs: 0, Precedence: 50, Handler: trimSpaceOperator} -var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 50, Handler: loadYamlOperator} +var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 52, Handler: loadYamlOperator} var keysOpType = &operationType{Type: "KEYS", NumArgs: 0, Precedence: 50, Handler: keysOperator} diff --git a/pkg/yqlib/operator_entries_test.go b/pkg/yqlib/operator_entries_test.go index 7d27095a..701f6d82 100644 --- a/pkg/yqlib/operator_entries_test.go +++ b/pkg/yqlib/operator_entries_test.go @@ -5,6 +5,16 @@ import ( ) var entriesOperatorScenarios = []expressionScenario{ + { + description: "to_entries splat", + skipDoc: true, + document: `{a: 1, b: 2}`, + expression: `to_entries[]`, + expected: []string{ + "D0, P[0], (!!map)::key: a\nvalue: 1\n", + "D0, P[1], (!!map)::key: b\nvalue: 2\n", + }, + }, { description: "to_entries, delete key", skipDoc: true, diff --git a/pkg/yqlib/operator_load_test.go b/pkg/yqlib/operator_load_test.go index 2b1f96f6..15acb2d9 100644 --- a/pkg/yqlib/operator_load_test.go +++ b/pkg/yqlib/operator_load_test.go @@ -13,6 +13,22 @@ var loadScenarios = []expressionScenario{ "D0, P[], (!!null)::# comment\n", }, }, + { + skipDoc: true, + description: "Load and splat", + expression: `load("../../examples/small.yaml")[]`, + expected: []string{ + "D0, P[a], (!!str)::cat\n", + }, + }, + { + skipDoc: true, + description: "Load and traverse", + expression: `load("../../examples/small.yaml").a`, + expected: []string{ + "D0, P[a], (!!str)::cat\n", + }, + }, { skipDoc: true, description: "Load file with a header comment into an array",