mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 13:48:06 +00: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…
Reference in New Issue
Block a user