assign operator

This commit is contained in:
Mike Farah 2020-10-10 15:24:37 +11:00
parent 8170eec6d1
commit ac076cd34a
6 changed files with 76 additions and 8 deletions

View File

@ -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}
} }

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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'

View File

@ -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)