mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	Fixes nested array indexing #824
This commit is contained in:
		
							parent
							
								
									77edbb9f5c
								
							
						
					
					
						commit
						d18a6963f6
					
				| @ -54,7 +54,7 @@ func (p *expressionPostFixerImpl) ConvertToPostfix(infixTokens []*token) ([]*Ope | |||||||
| 			opStack = opStack[0 : len(opStack)-1] | 			opStack = opStack[0 : len(opStack)-1] | ||||||
| 			log.Debugf("deleteing open bracket from opstack") | 			log.Debugf("deleteing open bracket from opstack") | ||||||
| 
 | 
 | ||||||
| 			//and append a collect to the opStack | 			//and append a collect to the result | ||||||
| 			// hack - see if there's the optional traverse flag | 			// hack - see if there's the optional traverse flag | ||||||
| 			// on the close op - move it to the collect op. | 			// on the close op - move it to the collect op. | ||||||
| 			// allows for .["cat"]? | 			// allows for .["cat"]? | ||||||
| @ -68,6 +68,12 @@ func (p *expressionPostFixerImpl) ConvertToPostfix(infixTokens []*token) ([]*Ope | |||||||
| 			result = append(result, &Operation{OperationType: shortPipeOpType}) | 			result = append(result, &Operation{OperationType: shortPipeOpType}) | ||||||
| 			log.Debugf("put shortpipe onto the result") | 			log.Debugf("put shortpipe onto the result") | ||||||
| 
 | 
 | ||||||
|  | 			//traverseArrayCollect is a sneaky op that needs to be included too | ||||||
|  | 			//when closing a [] | ||||||
|  | 			if len(opStack) > 0 && opStack[len(opStack)-1].Operation != nil && opStack[len(opStack)-1].Operation.OperationType == traverseArrayOpType { | ||||||
|  | 				opStack, result = popOpToResult(opStack, result) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 		case closeBracket: | 		case closeBracket: | ||||||
| 			for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != openBracket { | 			for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != openBracket { | ||||||
| 				opStack, result = popOpToResult(opStack, result) | 				opStack, result = popOpToResult(opStack, result) | ||||||
|  | |||||||
| @ -12,6 +12,16 @@ var pathTests = []struct { | |||||||
| 	expectedTokens  []interface{} | 	expectedTokens  []interface{} | ||||||
| 	expectedPostFix []interface{} | 	expectedPostFix []interface{} | ||||||
| }{ | }{ | ||||||
|  | 	{ | ||||||
|  | 		`.[0]`, | ||||||
|  | 		append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"), | ||||||
|  | 		append(make([]interface{}, 0), "SELF", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"), | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		`.[0][1]`, | ||||||
|  | 		append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]", "TRAVERSE_ARRAY", "[", "1 (int64)", "]"), | ||||||
|  | 		append(make([]interface{}, 0), "SELF", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "1 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"), | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		`"\""`, | 		`"\""`, | ||||||
| 		append(make([]interface{}, 0), "\" (string)"), | 		append(make([]interface{}, 0), "\" (string)"), | ||||||
|  | |||||||
| @ -411,16 +411,19 @@ func (p *expressionTokeniserImpl) handleToken(tokens []*token, index int, postPr | |||||||
| 	skipNextToken = false | 	skipNextToken = false | ||||||
| 	currentToken := tokens[index] | 	currentToken := tokens[index] | ||||||
| 
 | 
 | ||||||
|  | 	log.Debug("processing %v", currentToken.toString(true)) | ||||||
|  | 
 | ||||||
| 	if currentToken.TokenType == traverseArrayCollect { | 	if currentToken.TokenType == traverseArrayCollect { | ||||||
| 		//need to put a traverse array then a collect currentToken | 		//need to put a traverse array then a collect currentToken | ||||||
| 		// do this by adding traverse then converting currentToken to collect | 		// do this by adding traverse then converting currentToken to collect | ||||||
| 
 | 
 | ||||||
| 		if index == 0 || tokens[index-1].TokenType != operationToken || | 		if index == 0 || tokens[index-1].TokenType != operationToken || | ||||||
| 			tokens[index-1].Operation.OperationType != traversePathOpType { | 			tokens[index-1].Operation.OperationType != traversePathOpType { | ||||||
|  | 			log.Debug("  adding self") | ||||||
| 			op := &Operation{OperationType: selfReferenceOpType, StringValue: "SELF"} | 			op := &Operation{OperationType: selfReferenceOpType, StringValue: "SELF"} | ||||||
| 			postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | 			postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | ||||||
| 		} | 		} | ||||||
| 
 | 		log.Debug("  adding traverse array") | ||||||
| 		op := &Operation{OperationType: traverseArrayOpType, StringValue: "TRAVERSE_ARRAY"} | 		op := &Operation{OperationType: traverseArrayOpType, StringValue: "TRAVERSE_ARRAY"} | ||||||
| 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | ||||||
| 
 | 
 | ||||||
| @ -431,17 +434,19 @@ func (p *expressionTokeniserImpl) handleToken(tokens []*token, index int, postPr | |||||||
| 	if index != len(tokens)-1 && currentToken.AssignOperation != nil && | 	if index != len(tokens)-1 && currentToken.AssignOperation != nil && | ||||||
| 		tokens[index+1].TokenType == operationToken && | 		tokens[index+1].TokenType == operationToken && | ||||||
| 		tokens[index+1].Operation.OperationType == assignOpType { | 		tokens[index+1].Operation.OperationType == assignOpType { | ||||||
|  | 		log.Debug("  its an update assign") | ||||||
| 		currentToken.Operation = currentToken.AssignOperation | 		currentToken.Operation = currentToken.AssignOperation | ||||||
| 		currentToken.Operation.UpdateAssign = tokens[index+1].Operation.UpdateAssign | 		currentToken.Operation.UpdateAssign = tokens[index+1].Operation.UpdateAssign | ||||||
| 		skipNextToken = true | 		skipNextToken = true | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	log.Debug("  adding token to the fixed list") | ||||||
| 	postProcessedTokens = append(postProcessedTokens, currentToken) | 	postProcessedTokens = append(postProcessedTokens, currentToken) | ||||||
| 
 | 
 | ||||||
| 	if index != len(tokens)-1 && | 	if index != len(tokens)-1 && | ||||||
| 		((currentToken.TokenType == openCollect && tokens[index+1].TokenType == closeCollect) || | 		((currentToken.TokenType == openCollect && tokens[index+1].TokenType == closeCollect) || | ||||||
| 			(currentToken.TokenType == openCollectObject && tokens[index+1].TokenType == closeCollectObject)) { | 			(currentToken.TokenType == openCollectObject && tokens[index+1].TokenType == closeCollectObject)) { | ||||||
| 
 | 		log.Debug("  adding empty") | ||||||
| 		op := &Operation{OperationType: emptyOpType, StringValue: "EMPTY"} | 		op := &Operation{OperationType: emptyOpType, StringValue: "EMPTY"} | ||||||
| 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | ||||||
| 	} | 	} | ||||||
| @ -449,12 +454,19 @@ func (p *expressionTokeniserImpl) handleToken(tokens []*token, index int, postPr | |||||||
| 	if index != len(tokens)-1 && currentToken.CheckForPostTraverse && | 	if index != len(tokens)-1 && currentToken.CheckForPostTraverse && | ||||||
| 		tokens[index+1].TokenType == operationToken && | 		tokens[index+1].TokenType == operationToken && | ||||||
| 		tokens[index+1].Operation.OperationType == traversePathOpType { | 		tokens[index+1].Operation.OperationType == traversePathOpType { | ||||||
|  | 		log.Debug("  adding pipe because the next thing is traverse") | ||||||
| 		op := &Operation{OperationType: shortPipeOpType, Value: "PIPE"} | 		op := &Operation{OperationType: shortPipeOpType, Value: "PIPE"} | ||||||
| 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | ||||||
| 	} | 	} | ||||||
| 	if index != len(tokens)-1 && currentToken.CheckForPostTraverse && | 	if index != len(tokens)-1 && currentToken.CheckForPostTraverse && | ||||||
| 		tokens[index+1].TokenType == openCollect { | 		tokens[index+1].TokenType == openCollect { | ||||||
| 
 | 
 | ||||||
|  | 		// if tokens[index].TokenType == closeCollect { | ||||||
|  | 		// 	log.Debug("  adding pipe because next is opencollect") | ||||||
|  | 		// 	op := &Operation{OperationType: shortPipeOpType, Value: "PIPE"} | ||||||
|  | 		// 	postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | ||||||
|  | 		// } | ||||||
|  | 		log.Debug("  adding traverArray because next is opencollect") | ||||||
| 		op := &Operation{OperationType: traverseArrayOpType} | 		op := &Operation{OperationType: traverseArrayOpType} | ||||||
| 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | 		postProcessedTokens = append(postProcessedTokens, &token{TokenType: operationToken, Operation: op}) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -27,6 +27,22 @@ foobar: | |||||||
| ` | ` | ||||||
| 
 | 
 | ||||||
| var traversePathOperatorScenarios = []expressionScenario{ | var traversePathOperatorScenarios = []expressionScenario{ | ||||||
|  | 	{ | ||||||
|  | 		skipDoc:    true, | ||||||
|  | 		document:   `[[1]]`, | ||||||
|  | 		expression: `.[0][0]`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[0 0], (!!int)::1\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		skipDoc:    true, | ||||||
|  | 		document:   `[[[1]]]`, | ||||||
|  | 		expression: `.[0][0][0]`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[0 0 0], (!!int)::1\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		description: "Simple map navigation", | 		description: "Simple map navigation", | ||||||
| 		document:    `{a: {b: apple}}`, | 		document:    `{a: {b: apple}}`, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user