mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 13:48:06 +00:00
Can now properly handle .a[] expressions
This commit is contained in:
parent
a3e422ff76
commit
db60746e4e
@ -17,6 +17,21 @@ var pathTests = []struct {
|
|||||||
append(make([]interface{}, 0), "[", "]"),
|
append(make([]interface{}, 0), "[", "]"),
|
||||||
append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`.a[]`,
|
||||||
|
append(make([]interface{}, 0), "a", "SHORT_PIPE", "[]"),
|
||||||
|
append(make([]interface{}, 0), "a", "[]", "SHORT_PIPE"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`.a.[]`,
|
||||||
|
append(make([]interface{}, 0), "a", "SHORT_PIPE", "[]"),
|
||||||
|
append(make([]interface{}, 0), "a", "[]", "SHORT_PIPE"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`.a[].c`,
|
||||||
|
append(make([]interface{}, 0), "a", "SHORT_PIPE", "[]", "SHORT_PIPE", "c"),
|
||||||
|
append(make([]interface{}, 0), "a", "[]", "SHORT_PIPE", "c", "SHORT_PIPE"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
`[3]`,
|
`[3]`,
|
||||||
append(make([]interface{}, 0), "[", "3 (int64)", "]"),
|
append(make([]interface{}, 0), "[", "3 (int64)", "]"),
|
||||||
|
@ -21,6 +21,7 @@ const (
|
|||||||
CloseCollect
|
CloseCollect
|
||||||
OpenCollectObject
|
OpenCollectObject
|
||||||
CloseCollectObject
|
CloseCollectObject
|
||||||
|
SplatOrEmptyCollect
|
||||||
)
|
)
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
@ -47,6 +48,8 @@ func (t *Token) toString() string {
|
|||||||
return "{"
|
return "{"
|
||||||
} else if t.TokenType == CloseCollectObject {
|
} else if t.TokenType == CloseCollectObject {
|
||||||
return "}"
|
return "}"
|
||||||
|
} else if t.TokenType == SplatOrEmptyCollect {
|
||||||
|
return "[]?"
|
||||||
} else {
|
} else {
|
||||||
return "NFI"
|
return "NFI"
|
||||||
}
|
}
|
||||||
@ -247,6 +250,8 @@ func initLexer() (*lex.Lexer, error) {
|
|||||||
|
|
||||||
lexer.Add([]byte(`"[^ "]*"`), stringValue(true))
|
lexer.Add([]byte(`"[^ "]*"`), stringValue(true))
|
||||||
|
|
||||||
|
lexer.Add([]byte(`\[\]`), literalToken(SplatOrEmptyCollect, true))
|
||||||
|
|
||||||
lexer.Add([]byte(`\[`), literalToken(OpenCollect, false))
|
lexer.Add([]byte(`\[`), literalToken(OpenCollect, false))
|
||||||
lexer.Add([]byte(`\]`), literalToken(CloseCollect, true))
|
lexer.Add([]byte(`\]`), literalToken(CloseCollect, true))
|
||||||
lexer.Add([]byte(`\{`), literalToken(OpenCollectObject, false))
|
lexer.Add([]byte(`\{`), literalToken(OpenCollectObject, false))
|
||||||
@ -301,10 +306,39 @@ func (p *pathTokeniser) Tokenise(path string) ([]*Token, error) {
|
|||||||
|
|
||||||
skipNextToken := false
|
skipNextToken := false
|
||||||
|
|
||||||
for index, token := range tokens {
|
for index := range tokens {
|
||||||
if skipNextToken {
|
if skipNextToken {
|
||||||
skipNextToken = false
|
skipNextToken = false
|
||||||
} else {
|
} else {
|
||||||
|
postProcessedTokens, skipNextToken = p.handleToken(tokens, index, postProcessedTokens)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return postProcessedTokens, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pathTokeniser) handleToken(tokens []*Token, index int, postProcessedTokens []*Token) (tokensAccum []*Token, skipNextToken bool) {
|
||||||
|
skipNextToken = false
|
||||||
|
token := tokens[index]
|
||||||
|
if token.TokenType == SplatOrEmptyCollect {
|
||||||
|
if index > 0 && tokens[index-1].TokenType == OperationToken &&
|
||||||
|
tokens[index-1].Operation.OperationType == TraversePath {
|
||||||
|
// must be a splat without a preceding dot , e.g. .a[]
|
||||||
|
// lets put a pipe in front of it, and convert it to a traverse "[]" token
|
||||||
|
pipeOp := &Operation{OperationType: ShortPipe, Value: "PIPE"}
|
||||||
|
|
||||||
|
postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OperationToken, Operation: pipeOp})
|
||||||
|
|
||||||
|
traverseOp := &Operation{OperationType: TraversePath, Value: "[]", StringValue: "[]"}
|
||||||
|
token = &Token{TokenType: OperationToken, Operation: traverseOp, CheckForPostTraverse: true}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// gotta be a collect empty array, we need to split this into two tokens
|
||||||
|
// one OpenCollect, the other CloseCollect
|
||||||
|
postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OpenCollect})
|
||||||
|
token = &Token{TokenType: CloseCollect, CheckForPostTraverse: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if index != len(tokens)-1 && token.AssignOperation != nil &&
|
if index != len(tokens)-1 && token.AssignOperation != nil &&
|
||||||
tokens[index+1].TokenType == OperationToken &&
|
tokens[index+1].TokenType == OperationToken &&
|
||||||
@ -321,8 +355,5 @@ func (p *pathTokeniser) Tokenise(path string) ([]*Token, error) {
|
|||||||
op := &Operation{OperationType: ShortPipe, Value: "PIPE"}
|
op := &Operation{OperationType: ShortPipe, Value: "PIPE"}
|
||||||
postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OperationToken, Operation: op})
|
postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OperationToken, Operation: op})
|
||||||
}
|
}
|
||||||
}
|
return postProcessedTokens, skipNextToken
|
||||||
}
|
|
||||||
|
|
||||||
return postProcessedTokens, nil
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user