mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	assign operator
This commit is contained in:
		
							parent
							
								
									8170eec6d1
								
							
						
					
					
						commit
						ac076cd34a
					
				| @ -27,6 +27,7 @@ func NewDataTreeNavigator(navigationPrefs NavigationPrefs) DataTreeNavigator { | |||||||
| 	operatorHandlers[Equals] = EqualsOperator | 	operatorHandlers[Equals] = EqualsOperator | ||||||
| 	operatorHandlers[Or] = UnionOperator | 	operatorHandlers[Or] = UnionOperator | ||||||
| 	operatorHandlers[And] = IntersectionOperator | 	operatorHandlers[And] = IntersectionOperator | ||||||
|  | 	operatorHandlers[Assign] = AssignOperator | ||||||
| 
 | 
 | ||||||
| 	return &dataTreeNavigator{leafTraverser, operatorHandlers} | 	return &dataTreeNavigator{leafTraverser, operatorHandlers} | ||||||
| } | } | ||||||
|  | |||||||
| @ -78,6 +78,31 @@ func TestDataTreeNavigatorArraySimple(t *testing.T) { | |||||||
| 	test.AssertResult(t, expected, resultsToString(results)) | 	test.AssertResult(t, expected, resultsToString(results)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestDataTreeNavigatorSimpleAssign(t *testing.T) { | ||||||
|  | 
 | ||||||
|  | 	nodes := readDoc(t, `a:  | ||||||
|  |   b: apple`) | ||||||
|  | 
 | ||||||
|  | 	path, errPath := treeCreator.ParsePath("a.b := frog") | ||||||
|  | 	if errPath != nil { | ||||||
|  | 		t.Error(errPath) | ||||||
|  | 	} | ||||||
|  | 	results, errNav := treeNavigator.GetMatchingNodes(nodes, path) | ||||||
|  | 
 | ||||||
|  | 	if errNav != nil { | ||||||
|  | 		t.Error(errNav) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	expected := ` | ||||||
|  | -- Node -- | ||||||
|  |   Document 0, path: [a b] | ||||||
|  |   Tag: !!str, Kind: ScalarNode, Anchor:  | ||||||
|  |   frog | ||||||
|  | ` | ||||||
|  | 
 | ||||||
|  | 	test.AssertResult(t, expected, resultsToString(results)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestDataTreeNavigatorArraySplat(t *testing.T) { | func TestDataTreeNavigatorArraySplat(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	nodes := readDoc(t, `- b: apple | 	nodes := readDoc(t, `- b: apple | ||||||
|  | |||||||
| @ -12,6 +12,18 @@ func TraverseOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap | |||||||
| 	return d.getMatchingNodes(lhs, pathNode.Rhs) | 	return d.getMatchingNodes(lhs, pathNode.Rhs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func AssignOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) { | ||||||
|  | 	lhs, err := d.getMatchingNodes(matchingNodes, pathNode.Lhs) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	for el := lhs.Front(); el != nil; el = el.Next() { | ||||||
|  | 		node := el.Value.(*CandidateNode) | ||||||
|  | 		node.Node.Value = pathNode.Rhs.PathElement.StringValue | ||||||
|  | 	} | ||||||
|  | 	return lhs, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func UnionOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) { | func UnionOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) { | ||||||
| 	lhs, err := d.getMatchingNodes(matchingNodes, pathNode.Lhs) | 	lhs, err := d.getMatchingNodes(matchingNodes, pathNode.Lhs) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | |||||||
| @ -26,6 +26,7 @@ const ( | |||||||
| 	And | 	And | ||||||
| 	Equals | 	Equals | ||||||
| 	EqualsSelf | 	EqualsSelf | ||||||
|  | 	Assign | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type PathElement struct { | type PathElement struct { | ||||||
| @ -54,6 +55,8 @@ func (p *PathElement) toString() string { | |||||||
| 			result = result + "EQUALS\n" | 			result = result + "EQUALS\n" | ||||||
| 		case EqualsSelf: | 		case EqualsSelf: | ||||||
| 			result = result + "EQUALS SELF\n" | 			result = result + "EQUALS SELF\n" | ||||||
|  | 		case Assign: | ||||||
|  | 			result = result + "ASSIGN\n" | ||||||
| 		case Traverse: | 		case Traverse: | ||||||
| 			result = result + "TRAVERSE\n" | 			result = result + "TRAVERSE\n" | ||||||
| 		} | 		} | ||||||
| @ -82,6 +85,9 @@ func initMaps() { | |||||||
| 	precedenceMap[TokenIds["EQUALS_SELF_OPERATOR"]] = 30 | 	precedenceMap[TokenIds["EQUALS_SELF_OPERATOR"]] = 30 | ||||||
| 	operationTypeMapper[TokenIds["EQUALS_SELF_OPERATOR"]] = EqualsSelf | 	operationTypeMapper[TokenIds["EQUALS_SELF_OPERATOR"]] = EqualsSelf | ||||||
| 
 | 
 | ||||||
|  | 	precedenceMap[TokenIds["ASSIGN_OPERATOR"]] = 35 | ||||||
|  | 	operationTypeMapper[TokenIds["ASSIGN_OPERATOR"]] = Assign | ||||||
|  | 
 | ||||||
| 	precedenceMap[TokenIds["TRAVERSE_OPERATOR"]] = 40 | 	precedenceMap[TokenIds["TRAVERSE_OPERATOR"]] = 40 | ||||||
| 	operationTypeMapper[TokenIds["TRAVERSE_OPERATOR"]] = Traverse | 	operationTypeMapper[TokenIds["TRAVERSE_OPERATOR"]] = Traverse | ||||||
| } | } | ||||||
| @ -122,14 +128,6 @@ func (p *pathPostFixer) ConvertToPostfix(infixTokens []*lex.Token) ([]*PathEleme | |||||||
| 			result = append(result, &pathElement) | 			result = append(result, &pathElement) | ||||||
| 		case TokenIds["("]: | 		case TokenIds["("]: | ||||||
| 			opStack = append(opStack, token) | 			opStack = append(opStack, token) | ||||||
| 		case TokenIds["OR_OPERATOR"], TokenIds["AND_OPERATOR"], TokenIds["EQUALS_OPERATOR"], TokenIds["EQUALS_SELF_OPERATOR"], TokenIds["TRAVERSE_OPERATOR"]: |  | ||||||
| 			var currentPrecedence = precedenceMap[token.Type] |  | ||||||
| 			// pop off higher precedent operators onto the result |  | ||||||
| 			for len(opStack) > 0 && precedenceMap[opStack[len(opStack)-1].Type] >= currentPrecedence { |  | ||||||
| 				opStack, result = popOpToResult(opStack, result) |  | ||||||
| 			} |  | ||||||
| 			// add this operator to the opStack |  | ||||||
| 			opStack = append(opStack, token) |  | ||||||
| 		case TokenIds[")"]: | 		case TokenIds[")"]: | ||||||
| 			for len(opStack) > 0 && opStack[len(opStack)-1].Type != TokenIds["("] { | 			for len(opStack) > 0 && opStack[len(opStack)-1].Type != TokenIds["("] { | ||||||
| 				opStack, result = popOpToResult(opStack, result) | 				opStack, result = popOpToResult(opStack, result) | ||||||
| @ -139,6 +137,14 @@ func (p *pathPostFixer) ConvertToPostfix(infixTokens []*lex.Token) ([]*PathEleme | |||||||
| 			} | 			} | ||||||
| 			// now we should have ( as the last element on the opStack, get rid of it | 			// now we should have ( as the last element on the opStack, get rid of it | ||||||
| 			opStack = opStack[0 : len(opStack)-1] | 			opStack = opStack[0 : len(opStack)-1] | ||||||
|  | 		default: | ||||||
|  | 			var currentPrecedence = precedenceMap[token.Type] | ||||||
|  | 			// pop off higher precedent operators onto the result | ||||||
|  | 			for len(opStack) > 0 && precedenceMap[opStack[len(opStack)-1].Type] >= currentPrecedence { | ||||||
|  | 				opStack, result = popOpToResult(opStack, result) | ||||||
|  | 			} | ||||||
|  | 			// add this operator to the opStack | ||||||
|  | 			opStack = append(opStack, token) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return result, nil | 	return result, nil | ||||||
|  | |||||||
| @ -75,6 +75,28 @@ Operation - TRAVERSE | |||||||
| 	test.AssertResultComplex(t, expectedOutput, actual) | 	test.AssertResultComplex(t, expectedOutput, actual) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestPostFixSimpleAssign(t *testing.T) { | ||||||
|  | 	var infix = "a.b := frog" | ||||||
|  | 	var expectedOutput = `PathKey - 'a' | ||||||
|  | -------- | ||||||
|  | PathKey - 'b' | ||||||
|  | -------- | ||||||
|  | Operation - TRAVERSE | ||||||
|  | -------- | ||||||
|  | PathKey - 'frog' | ||||||
|  | -------- | ||||||
|  | Operation - ASSIGN | ||||||
|  | -------- | ||||||
|  | ` | ||||||
|  | 
 | ||||||
|  | 	actual, err := testExpression(infix) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Error(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	test.AssertResultComplex(t, expectedOutput, actual) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestPostFixSimplePathNumbersExample(t *testing.T) { | func TestPostFixSimplePathNumbersExample(t *testing.T) { | ||||||
| 	var infix = "apples[0].cat" | 	var infix = "apples[0].cat" | ||||||
| 	var expectedOutput = `PathKey - 'apples' | 	var expectedOutput = `PathKey - 'apples' | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ func initTokens() { | |||||||
| 		"AND_OPERATOR", | 		"AND_OPERATOR", | ||||||
| 		"EQUALS_OPERATOR", | 		"EQUALS_OPERATOR", | ||||||
| 		"EQUALS_SELF_OPERATOR", | 		"EQUALS_SELF_OPERATOR", | ||||||
|  | 		"ASSIGN_OPERATOR", | ||||||
| 		"TRAVERSE_OPERATOR", | 		"TRAVERSE_OPERATOR", | ||||||
| 		"PATH_KEY",    // apples | 		"PATH_KEY",    // apples | ||||||
| 		"ARRAY_INDEX", // 123 | 		"ARRAY_INDEX", // 123 | ||||||
| @ -90,6 +91,7 @@ func initLexer() (*lex.Lexer, error) { | |||||||
| 	lexer.Add([]byte(`([Aa][Nn][Dd])`), token("AND_OPERATOR")) | 	lexer.Add([]byte(`([Aa][Nn][Dd])`), token("AND_OPERATOR")) | ||||||
| 	lexer.Add([]byte(`\.\s*==\s*`), token("EQUALS_SELF_OPERATOR")) | 	lexer.Add([]byte(`\.\s*==\s*`), token("EQUALS_SELF_OPERATOR")) | ||||||
| 	lexer.Add([]byte(`\s*==\s*`), token("EQUALS_OPERATOR")) | 	lexer.Add([]byte(`\s*==\s*`), token("EQUALS_OPERATOR")) | ||||||
|  | 	lexer.Add([]byte(`\s*:=\s*`), token("ASSIGN_OPERATOR")) | ||||||
| 	lexer.Add([]byte(`\[-?[0-9]+\]`), numberToken("ARRAY_INDEX", true)) | 	lexer.Add([]byte(`\[-?[0-9]+\]`), numberToken("ARRAY_INDEX", true)) | ||||||
| 	lexer.Add([]byte(`-?[0-9]+`), numberToken("ARRAY_INDEX", false)) | 	lexer.Add([]byte(`-?[0-9]+`), numberToken("ARRAY_INDEX", false)) | ||||||
| 	lexer.Add([]byte("( |\t|\n|\r)+"), skip) | 	lexer.Add([]byte("( |\t|\n|\r)+"), skip) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user