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 (
|
const (
|
||||||
None OperationType = 1 << iota
|
None OperationType = 1 << iota
|
||||||
|
Traverse
|
||||||
Or
|
Or
|
||||||
And
|
And
|
||||||
Equals
|
Equals
|
||||||
|
EqualsSelf
|
||||||
)
|
)
|
||||||
|
|
||||||
type PathElement struct {
|
type PathElement struct {
|
||||||
PathElementType PathElementType
|
PathElementType PathElementType
|
||||||
OperationType OperationType
|
OperationType OperationType
|
||||||
Value interface{}
|
Value interface{}
|
||||||
ChildElements [][]*PathElement
|
|
||||||
Finished bool
|
Finished bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// debugging purposes only
|
// debugging purposes only
|
||||||
func (p *PathElement) toString() string {
|
func (p *PathElement) toString() string {
|
||||||
var result string = `Type: `
|
var result string = ``
|
||||||
switch p.PathElementType {
|
switch p.PathElementType {
|
||||||
case PathKey:
|
case PathKey:
|
||||||
result = result + fmt.Sprintf("PathKey - %v", p.Value)
|
result = result + fmt.Sprintf("PathKey - '%v'\n", p.Value)
|
||||||
for _, next := range p.ChildElements[0] {
|
|
||||||
result = result + fmt.Sprintf(".%v", next.Value)
|
|
||||||
}
|
|
||||||
result = result + "\n"
|
|
||||||
case ArrayIndex:
|
case ArrayIndex:
|
||||||
result = result + fmt.Sprintf("ArrayIndex - %v\n", p.Value)
|
result = result + fmt.Sprintf("ArrayIndex - '%v'\n", p.Value)
|
||||||
case Operation:
|
case Operation:
|
||||||
result = result + "Operation - "
|
result = result + "Operation - "
|
||||||
switch p.OperationType {
|
switch p.OperationType {
|
||||||
@ -55,7 +52,12 @@ func (p *PathElement) toString() string {
|
|||||||
result = result + "AND\n"
|
result = result + "AND\n"
|
||||||
case Equals:
|
case Equals:
|
||||||
result = result + "EQUALS\n"
|
result = result + "EQUALS\n"
|
||||||
|
case EqualsSelf:
|
||||||
|
result = result + "EQUALS SELF\n"
|
||||||
|
case Traverse:
|
||||||
|
result = result + "TRAVERSE\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -76,11 +78,16 @@ func initMaps() {
|
|||||||
|
|
||||||
precedenceMap[TokenIds["EQUALS_OPERATOR"]] = 30
|
precedenceMap[TokenIds["EQUALS_OPERATOR"]] = 30
|
||||||
operationTypeMapper[TokenIds["EQUALS_OPERATOR"]] = Equals
|
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 {
|
func createOperationPathElement(opToken *lex.Token) PathElement {
|
||||||
var childElements = make([][]*PathElement, 2)
|
var pathElement = PathElement{PathElementType: Operation, OperationType: operationTypeMapper[opToken.Type]}
|
||||||
var pathElement = PathElement{PathElementType: Operation, OperationType: operationTypeMapper[opToken.Type], ChildElements: childElements}
|
|
||||||
return pathElement
|
return pathElement
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,22 +126,15 @@ func (p *pathPostFixer) ConvertToPostfix(infixTokens []*lex.Token) ([]*PathEleme
|
|||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
case TokenIds["PATH_KEY"]: // handle splats and array appends here too
|
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}
|
||||||
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)
|
result = append(result, &pathElement)
|
||||||
}
|
|
||||||
case TokenIds["("]:
|
case TokenIds["("]:
|
||||||
opStack = append(opStack, token)
|
opStack = append(opStack, token)
|
||||||
finishPathKey(result)
|
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]
|
var currentPrecedence = precedenceMap[token.Type]
|
||||||
// pop off higher precedent operators onto the result
|
// 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)
|
opStack, result = popOpToResult(opStack, result)
|
||||||
}
|
}
|
||||||
// add this operator to the opStack
|
// add this operator to the opStack
|
||||||
|
@ -25,9 +25,9 @@ func testExpression(expression string) (string, error) {
|
|||||||
return formatted, nil
|
return formatted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostFixSimple(t *testing.T) {
|
func TestPostFixSimpleExample(t *testing.T) {
|
||||||
var infix = "a"
|
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)
|
test.AssertResultComplex(t, expectedOutput, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostFixSimplePath(t *testing.T) {
|
func TestPostFixSimplePathExample(t *testing.T) {
|
||||||
var infix = "apples.bananas*.cat"
|
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)
|
test.AssertResultComplex(t, expectedOutput, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostFixOr(t *testing.T) {
|
func TestPostFixOrExample(t *testing.T) {
|
||||||
var infix = "a OR b"
|
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)
|
test.AssertResultComplex(t, expectedOutput, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostFixOrWithEquals(t *testing.T) {
|
func TestPostFixOrWithEqualsExample(t *testing.T) {
|
||||||
var infix = "a==thing OR b==thongs"
|
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)
|
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 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{
|
Tokens = []string{
|
||||||
"BEGIN_SUB_EXPRESSION",
|
|
||||||
"END_SUB_EXPRESSION",
|
|
||||||
"OR_OPERATOR",
|
"OR_OPERATOR",
|
||||||
"AND_OPERATOR",
|
"AND_OPERATOR",
|
||||||
"EQUALS_OPERATOR",
|
"EQUALS_OPERATOR",
|
||||||
|
Loading…
Reference in New Issue
Block a user