This commit is contained in:
Mike Farah 2020-10-19 20:05:38 +11:00
parent 1910563bfe
commit 4bc98776a6
8 changed files with 41 additions and 8 deletions

View File

@ -15,6 +15,7 @@ type PathElementType uint32
const ( const (
PathKey PathElementType = 1 << iota PathKey PathElementType = 1 << iota
DocumentKey
Operation Operation
SelfReference SelfReference
OpenBracket OpenBracket
@ -75,6 +76,8 @@ func (p *PathElement) toString() string {
switch p.PathElementType { switch p.PathElementType {
case PathKey: case PathKey:
result = result + fmt.Sprintf("%v", p.Value) result = result + fmt.Sprintf("%v", p.Value)
case DocumentKey:
result = result + fmt.Sprintf("D%v", p.Value)
case SelfReference: case SelfReference:
result = result + fmt.Sprintf("SELF") result = result + fmt.Sprintf("SELF")
case Operation: case Operation:

View File

@ -11,6 +11,12 @@ var collectOperatorScenarios = []expressionScenario{
expected: []string{ expected: []string{
"D0, P[], (!!seq)::- cat\n", "D0, P[], (!!seq)::- cat\n",
}, },
}, {
document: `{}`,
expression: `[true]`,
expected: []string{
"D0, P[], (!!seq)::- true\n",
},
}, { }, {
document: `{}`, document: `{}`,
expression: `["cat", "dog"]`, expression: `["cat", "dog"]`,

View File

@ -38,7 +38,8 @@ func MultiplyOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap
} }
func multiply(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { func multiply(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
if lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode { if lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode ||
(lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) {
var results = orderedmap.NewOrderedMap() var results = orderedmap.NewOrderedMap()
recursiveDecent(d, results, nodeToMap(rhs)) recursiveDecent(d, results, nodeToMap(rhs))

View File

@ -61,6 +61,12 @@ b:
also: "me" also: "me"
`, `,
}, },
}, {
document: `{a: [1,2,3], b: [3,4,5]}`,
expression: `.a * .b`,
expected: []string{
"D0, P[], (!!map)::{a: [3, 4, 5], b: [3, 4, 5]}\n",
},
}, },
} }

View File

@ -39,6 +39,11 @@ var pathTests = []struct {
// {`."[a", ."b]"`, append(make([]interface{}, 0), "[a", "OR", "b]")}, // {`."[a", ."b]"`, append(make([]interface{}, 0), "[a", "OR", "b]")},
// {`.a[]`, append(make([]interface{}, 0), "a", "PIPE", "[]")}, // {`.a[]`, append(make([]interface{}, 0), "a", "PIPE", "[]")},
// {`.[].a`, append(make([]interface{}, 0), "[]", "PIPE", "a")}, // {`.[].a`, append(make([]interface{}, 0), "[]", "PIPE", "a")},
{
`d0.a`,
append(make([]interface{}, 0), int64(0), "PIPE", "a"),
append(make([]interface{}, 0), "D0", "a", "PIPE"),
},
{ {
`.a | (.[].b == "apple")`, `.a | (.[].b == "apple")`,
append(make([]interface{}, 0), "a", "PIPE", "(", "[]", "PIPE", "b", "EQUALS", "apple", ")"), append(make([]interface{}, 0), "a", "PIPE", "(", "[]", "PIPE", "b", "EQUALS", "apple", ")"),
@ -52,7 +57,7 @@ var pathTests = []struct {
{ {
`[true]`, `[true]`,
append(make([]interface{}, 0), "[", true, "]"), append(make([]interface{}, 0), "[", true, "]"),
append(make([]interface{}, 0), "true (bool)", "COLLECT"), append(make([]interface{}, 0), "true (bool)", "COLLECT", "PIPE"),
}, },
// {".animals | .==cat", append(make([]interface{}, 0), "animals", "TRAVERSE", "SELF", "EQUALS", "cat")}, // {".animals | .==cat", append(make([]interface{}, 0), "animals", "TRAVERSE", "SELF", "EQUALS", "cat")},

View File

@ -37,7 +37,7 @@ func (p *pathPostFixer) ConvertToPostfix(infixTokens []*Token) ([]*PathElement,
var candidateNode = BuildCandidateNodeFrom(token) var candidateNode = BuildCandidateNodeFrom(token)
var pathElement = PathElement{PathElementType: token.PathElementType, Value: token.Value, StringValue: token.StringValue, CandidateNode: candidateNode} var pathElement = PathElement{PathElementType: token.PathElementType, Value: token.Value, StringValue: token.StringValue, CandidateNode: candidateNode}
result = append(result, &pathElement) result = append(result, &pathElement)
case PathKey, SelfReference: case PathKey, SelfReference, DocumentKey:
var pathElement = PathElement{PathElementType: token.PathElementType, Value: token.Value, StringValue: token.StringValue} var pathElement = PathElement{PathElementType: token.PathElementType, Value: token.Value, StringValue: token.StringValue}
result = append(result, &pathElement) result = append(result, &pathElement)
case OpenBracket, OpenCollect: case OpenBracket, OpenCollect:

View File

@ -32,6 +32,18 @@ func pathToken(wrapped bool) lex.Action {
} }
} }
func documentToken() lex.Action {
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
var numberString = string(m.Bytes)
numberString = numberString[1:len(numberString)]
var number, errParsingInt = strconv.ParseInt(numberString, 10, 64) // nolint
if errParsingInt != nil {
return nil, errParsingInt
}
return &Token{PathElementType: DocumentKey, OperationType: None, Value: number, StringValue: numberString, CheckForPostTraverse: true}, nil
}
}
func opToken(op *OperationType) lex.Action { func opToken(op *OperationType) lex.Action {
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
value := string(m.Bytes) value := string(m.Bytes)
@ -136,6 +148,8 @@ func initLexer() (*lex.Lexer, error) {
lexer.Add([]byte("( |\t|\n|\r)+"), skip) lexer.Add([]byte("( |\t|\n|\r)+"), skip)
lexer.Add([]byte(`d[0-9]+`), documentToken()) // $0
lexer.Add([]byte(`\."[^ "]+"`), pathToken(true)) lexer.Add([]byte(`\."[^ "]+"`), pathToken(true))
lexer.Add([]byte(`\.[^ \[\],\|\.\[\(\)=]+`), pathToken(false)) lexer.Add([]byte(`\.[^ \[\],\|\.\[\(\)=]+`), pathToken(false))
lexer.Add([]byte(`\.`), selfToken()) lexer.Add([]byte(`\.`), selfToken())

View File

@ -1,6 +1,4 @@
{ {
"a": { "a": [1,2],
"b": "apple", "b": [3,4]
"c": "cactus"
}
} }