mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
postfix with traverse op
This commit is contained in:
parent
95bc1e1599
commit
c2159d9861
@ -21,31 +21,28 @@ type OperationType uint32
|
||||
|
||||
const (
|
||||
None OperationType = 1 << iota
|
||||
Traverse
|
||||
Or
|
||||
And
|
||||
Equals
|
||||
EqualsSelf
|
||||
)
|
||||
|
||||
type PathElement struct {
|
||||
PathElementType PathElementType
|
||||
OperationType OperationType
|
||||
Value interface{}
|
||||
ChildElements [][]*PathElement
|
||||
Finished bool
|
||||
}
|
||||
|
||||
// debugging purposes only
|
||||
func (p *PathElement) toString() string {
|
||||
var result string = `Type: `
|
||||
var result string = ``
|
||||
switch p.PathElementType {
|
||||
case PathKey:
|
||||
result = result + fmt.Sprintf("PathKey - %v", p.Value)
|
||||
for _, next := range p.ChildElements[0] {
|
||||
result = result + fmt.Sprintf(".%v", next.Value)
|
||||
}
|
||||
result = result + "\n"
|
||||
result = result + fmt.Sprintf("PathKey - '%v'\n", p.Value)
|
||||
case ArrayIndex:
|
||||
result = result + fmt.Sprintf("ArrayIndex - %v\n", p.Value)
|
||||
result = result + fmt.Sprintf("ArrayIndex - '%v'\n", p.Value)
|
||||
case Operation:
|
||||
result = result + "Operation - "
|
||||
switch p.OperationType {
|
||||
@ -55,7 +52,12 @@ func (p *PathElement) toString() string {
|
||||
result = result + "AND\n"
|
||||
case Equals:
|
||||
result = result + "EQUALS\n"
|
||||
case EqualsSelf:
|
||||
result = result + "EQUALS SELF\n"
|
||||
case Traverse:
|
||||
result = result + "TRAVERSE\n"
|
||||
}
|
||||
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -76,11 +78,16 @@ func initMaps() {
|
||||
|
||||
precedenceMap[TokenIds["EQUALS_OPERATOR"]] = 30
|
||||
operationTypeMapper[TokenIds["EQUALS_OPERATOR"]] = Equals
|
||||
|
||||
precedenceMap[TokenIds["EQUALS_SELF_OPERATOR"]] = 30
|
||||
operationTypeMapper[TokenIds["EQUALS_SELF_OPERATOR"]] = EqualsSelf
|
||||
|
||||
precedenceMap[TokenIds["TRAVERSE_OPERATOR"]] = 40
|
||||
operationTypeMapper[TokenIds["TRAVERSE_OPERATOR"]] = Traverse
|
||||
}
|
||||
|
||||
func createOperationPathElement(opToken *lex.Token) PathElement {
|
||||
var childElements = make([][]*PathElement, 2)
|
||||
var pathElement = PathElement{PathElementType: Operation, OperationType: operationTypeMapper[opToken.Type], ChildElements: childElements}
|
||||
var pathElement = PathElement{PathElementType: Operation, OperationType: operationTypeMapper[opToken.Type]}
|
||||
return pathElement
|
||||
}
|
||||
|
||||
@ -119,22 +126,15 @@ func (p *pathPostFixer) ConvertToPostfix(infixTokens []*lex.Token) ([]*PathEleme
|
||||
for _, token := range tokens {
|
||||
switch token.Type {
|
||||
case TokenIds["PATH_KEY"]: // handle splats and array appends here too
|
||||
var emptyArray = [][]*PathElement{make([]*PathElement, 0)}
|
||||
var pathElement = PathElement{PathElementType: PathKey, Value: token.Value, ChildElements: emptyArray}
|
||||
|
||||
if len(result) > 0 && result[len(result)-1].PathElementType == PathKey && !result[len(result)-1].Finished {
|
||||
var lastElement = result[len(result)-1]
|
||||
lastElement.ChildElements[0] = append(lastElement.ChildElements[0], &pathElement)
|
||||
} else {
|
||||
result = append(result, &pathElement)
|
||||
}
|
||||
var pathElement = PathElement{PathElementType: PathKey, Value: token.Value}
|
||||
result = append(result, &pathElement)
|
||||
case TokenIds["("]:
|
||||
opStack = append(opStack, token)
|
||||
finishPathKey(result)
|
||||
case TokenIds["OR_OPERATOR"], TokenIds["AND_OPERATOR"], TokenIds["EQUALS_OPERATOR"]:
|
||||
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 {
|
||||
for len(opStack) > 0 && precedenceMap[opStack[len(opStack)-1].Type] >= currentPrecedence {
|
||||
opStack, result = popOpToResult(opStack, result)
|
||||
}
|
||||
// add this operator to the opStack
|
||||
|
@ -25,9 +25,9 @@ func testExpression(expression string) (string, error) {
|
||||
return formatted, nil
|
||||
}
|
||||
|
||||
func TestPostFixSimple(t *testing.T) {
|
||||
func TestPostFixSimpleExample(t *testing.T) {
|
||||
var infix = "a"
|
||||
var expectedOutput = `Type: PathKey - a
|
||||
var expectedOutput = `PathKey - 'a'
|
||||
--------
|
||||
`
|
||||
|
||||
@ -39,9 +39,17 @@ func TestPostFixSimple(t *testing.T) {
|
||||
test.AssertResultComplex(t, expectedOutput, actual)
|
||||
}
|
||||
|
||||
func TestPostFixSimplePath(t *testing.T) {
|
||||
func TestPostFixSimplePathExample(t *testing.T) {
|
||||
var infix = "apples.bananas*.cat"
|
||||
var expectedOutput = `Type: PathKey - apples.bananas*.cat
|
||||
var expectedOutput = `PathKey - 'apples'
|
||||
--------
|
||||
PathKey - 'bananas*'
|
||||
--------
|
||||
Operation - TRAVERSE
|
||||
--------
|
||||
PathKey - 'cat'
|
||||
--------
|
||||
Operation - TRAVERSE
|
||||
--------
|
||||
`
|
||||
|
||||
@ -53,13 +61,13 @@ func TestPostFixSimplePath(t *testing.T) {
|
||||
test.AssertResultComplex(t, expectedOutput, actual)
|
||||
}
|
||||
|
||||
func TestPostFixOr(t *testing.T) {
|
||||
func TestPostFixOrExample(t *testing.T) {
|
||||
var infix = "a OR b"
|
||||
var expectedOutput = `Type: PathKey - a
|
||||
var expectedOutput = `PathKey - 'a'
|
||||
--------
|
||||
Type: PathKey - b
|
||||
PathKey - 'b'
|
||||
--------
|
||||
Type: Operation - OR
|
||||
Operation - OR
|
||||
--------
|
||||
`
|
||||
|
||||
@ -71,21 +79,21 @@ Type: Operation - OR
|
||||
test.AssertResultComplex(t, expectedOutput, actual)
|
||||
}
|
||||
|
||||
func TestPostFixOrWithEquals(t *testing.T) {
|
||||
func TestPostFixOrWithEqualsExample(t *testing.T) {
|
||||
var infix = "a==thing OR b==thongs"
|
||||
var expectedOutput = `Type: PathKey - a
|
||||
var expectedOutput = `PathKey - 'a'
|
||||
--------
|
||||
Type: PathKey - thing
|
||||
PathKey - 'thing'
|
||||
--------
|
||||
Type: Operation - EQUALS
|
||||
Operation - EQUALS
|
||||
--------
|
||||
Type: PathKey - b
|
||||
PathKey - 'b'
|
||||
--------
|
||||
Type: PathKey - thongs
|
||||
PathKey - 'thongs'
|
||||
--------
|
||||
Type: Operation - EQUALS
|
||||
Operation - EQUALS
|
||||
--------
|
||||
Type: Operation - OR
|
||||
Operation - OR
|
||||
--------
|
||||
`
|
||||
|
||||
@ -97,21 +105,29 @@ Type: Operation - OR
|
||||
test.AssertResultComplex(t, expectedOutput, actual)
|
||||
}
|
||||
|
||||
func TestPostFixOrWithEqualsPath(t *testing.T) {
|
||||
func TestPostFixOrWithEqualsPathExample(t *testing.T) {
|
||||
var infix = "apples.monkeys==thing OR bogs.bobos==thongs"
|
||||
var expectedOutput = `Type: PathKey - apples.monkeys
|
||||
var expectedOutput = `PathKey - 'apples'
|
||||
--------
|
||||
Type: PathKey - thing
|
||||
PathKey - 'monkeys'
|
||||
--------
|
||||
Type: Operation - EQUALS
|
||||
Operation - TRAVERSE
|
||||
--------
|
||||
Type: PathKey - bogs.bobos
|
||||
PathKey - 'thing'
|
||||
--------
|
||||
Type: PathKey - thongs
|
||||
Operation - EQUALS
|
||||
--------
|
||||
Type: Operation - EQUALS
|
||||
PathKey - 'bogs'
|
||||
--------
|
||||
Type: Operation - OR
|
||||
PathKey - 'bobos'
|
||||
--------
|
||||
Operation - TRAVERSE
|
||||
--------
|
||||
PathKey - 'thongs'
|
||||
--------
|
||||
Operation - EQUALS
|
||||
--------
|
||||
Operation - OR
|
||||
--------
|
||||
`
|
||||
|
||||
|
@ -25,8 +25,6 @@ func initTokens() {
|
||||
")",
|
||||
}
|
||||
Tokens = []string{
|
||||
"BEGIN_SUB_EXPRESSION",
|
||||
"END_SUB_EXPRESSION",
|
||||
"OR_OPERATOR",
|
||||
"AND_OPERATOR",
|
||||
"EQUALS_OPERATOR",
|
||||
|
Loading…
Reference in New Issue
Block a user