mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-14 15:18:06 +00:00
collect object operator!
This commit is contained in:
parent
65e6e492cd
commit
badd476730
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ require (
|
|||||||
github.com/elliotchance/orderedmap v1.3.0 // indirect
|
github.com/elliotchance/orderedmap v1.3.0 // indirect
|
||||||
github.com/fatih/color v1.9.0
|
github.com/fatih/color v1.9.0
|
||||||
github.com/goccy/go-yaml v1.8.1
|
github.com/goccy/go-yaml v1.8.1
|
||||||
|
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.7 // indirect
|
github.com/mattn/go-colorable v0.1.7 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
2
go.sum
2
go.sum
@ -49,6 +49,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
|
|||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o=
|
||||||
|
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,6 +19,12 @@ func (n *CandidateNode) GetKey() string {
|
|||||||
return fmt.Sprintf("%v - %v - %v", n.Document, n.Path, n.Node.Value)
|
return fmt.Sprintf("%v - %v - %v", n.Document, n.Path, n.Node.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *CandidateNode) Copy() *CandidateNode {
|
||||||
|
clone := &CandidateNode{}
|
||||||
|
copier.Copy(clone, n)
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
|
||||||
// updates this candidate from the given candidate node
|
// updates this candidate from the given candidate node
|
||||||
func (n *CandidateNode) UpdateFrom(other *CandidateNode) {
|
func (n *CandidateNode) UpdateFrom(other *CandidateNode) {
|
||||||
n.UpdateAttributesFrom(other)
|
n.UpdateAttributesFrom(other)
|
||||||
@ -34,7 +41,10 @@ func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode) {
|
|||||||
}
|
}
|
||||||
n.Node.Kind = other.Node.Kind
|
n.Node.Kind = other.Node.Kind
|
||||||
n.Node.Tag = other.Node.Tag
|
n.Node.Tag = other.Node.Tag
|
||||||
n.Node.Style = other.Node.Style
|
// not sure if this ever should happen here...
|
||||||
|
// if other.Node.Style != 0 {
|
||||||
|
// n.Node.Style = other.Node.Style
|
||||||
|
// }
|
||||||
n.Node.FootComment = other.Node.FootComment
|
n.Node.FootComment = other.Node.FootComment
|
||||||
n.Node.HeadComment = other.Node.HeadComment
|
n.Node.HeadComment = other.Node.HeadComment
|
||||||
n.Node.LineComment = other.Node.LineComment
|
n.Node.LineComment = other.Node.LineComment
|
||||||
|
@ -1,2 +1,39 @@
|
|||||||
package treeops
|
package treeops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var collectObjectOperatorScenarios = []expressionScenario{
|
||||||
|
{
|
||||||
|
document: `{name: Mike, age: 32}`,
|
||||||
|
expression: `{.name: .age}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[0], (!!map)::Mike: 32\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
document: `{name: Mike, pets: [cat, dog]}`,
|
||||||
|
expression: `{.name: .pets[]}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[0], (!!map)::Mike: cat\n",
|
||||||
|
"D0, P[1], (!!map)::Mike: dog\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
document: `{name: Mike, pets: [cat, dog], food: [hotdog, burger]}`,
|
||||||
|
expression: `{.name: .pets[], "f":.food[]}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!map)::Mike: cat\nf: hotdog\n",
|
||||||
|
"D0, P[], (!!map)::Mike: cat\nf: burger\n",
|
||||||
|
"D0, P[], (!!map)::Mike: dog\nf: hotdog\n",
|
||||||
|
"D0, P[], (!!map)::Mike: dog\nf: burger\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCollectObjectOperatorScenarios(t *testing.T) {
|
||||||
|
for _, tt := range collectObjectOperatorScenarios {
|
||||||
|
testScenario(t, &tt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,8 +1,57 @@
|
|||||||
package treeops
|
package treeops
|
||||||
|
|
||||||
import "container/list"
|
import (
|
||||||
|
"container/list"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
[Mike: cat, Bob: dog]
|
||||||
|
[Thing: rabbit, peter: sam]
|
||||||
|
|
||||||
|
==> cross multiply
|
||||||
|
|
||||||
|
{Mike: cat, Thing: rabbit}
|
||||||
|
{Mike: cat, peter: sam}
|
||||||
|
...
|
||||||
|
*/
|
||||||
|
|
||||||
func CollectObjectOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
func CollectObjectOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||||
log.Debugf("-- collectObjectOperation")
|
log.Debugf("-- collectObjectOperation")
|
||||||
return nil, nil
|
return collect(d, list.New(), matchMap)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func collect(d *dataTreeNavigator, aggregate *list.List, remainingMatches *list.List) (*list.List, error) {
|
||||||
|
if remainingMatches.Len() == 0 {
|
||||||
|
return aggregate, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
candidate := remainingMatches.Remove(remainingMatches.Front()).(*CandidateNode)
|
||||||
|
splatted, err := Splat(d, nodeToMap(candidate))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if aggregate.Len() == 0 {
|
||||||
|
return collect(d, splatted, remainingMatches)
|
||||||
|
}
|
||||||
|
|
||||||
|
newAgg := list.New()
|
||||||
|
|
||||||
|
for el := aggregate.Front(); el != nil; el = el.Next() {
|
||||||
|
aggCandidate := el.Value.(*CandidateNode)
|
||||||
|
for splatEl := splatted.Front(); splatEl != nil; splatEl = splatEl.Next() {
|
||||||
|
splatCandidate := splatEl.Value.(*CandidateNode)
|
||||||
|
newCandidate := aggCandidate.Copy()
|
||||||
|
newCandidate.Path = nil
|
||||||
|
|
||||||
|
newCandidate, err := multiply(d, newCandidate, splatCandidate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newAgg.PushBack(newCandidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collect(d, newAgg, remainingMatches)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,14 @@ var createMapOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[], (!!seq)::- Mike: cat\n- Mike: dog\n",
|
"D0, P[], (!!seq)::- Mike: cat\n- Mike: dog\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
document: `{name: Mike, pets: [cat, dog], food: [hotdog, burger]}`,
|
||||||
|
expression: `.name: .pets[], "f":.food[]`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!seq)::- Mike: cat\n- Mike: dog\n",
|
||||||
|
"D0, P[], (!!seq)::- f: hotdog\n- f: burger\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateMapOperatorScenarios(t *testing.T) {
|
func TestCreateMapOperatorScenarios(t *testing.T) {
|
||||||
|
@ -6,67 +6,65 @@ import (
|
|||||||
|
|
||||||
var multiplyOperatorScenarios = []expressionScenario{
|
var multiplyOperatorScenarios = []expressionScenario{
|
||||||
{
|
{
|
||||||
// document: `{a: {also: [1]}, b: {also: me}}`,
|
document: `{a: {also: [1]}, b: {also: me}}`,
|
||||||
// expression: `.a * .b`,
|
expression: `. * {"a" : .b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// "D0, P[], (!!map)::{a: {also: me}, b: {also: me}}\n",
|
"D0, P[], (!!map)::{a: {also: me}, b: {also: me}}\n",
|
||||||
// },
|
},
|
||||||
// }, {
|
}, {
|
||||||
// document: `{a: {also: me}, b: {also: [1]}}`,
|
document: `{a: {also: me}, b: {also: [1]}}`,
|
||||||
// expression: `.a * .b`,
|
expression: `. * {"a":.b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// "D0, P[], (!!map)::{a: {also: [1]}, b: {also: [1]}}\n",
|
"D0, P[], (!!map)::{a: {also: [1]}, b: {also: [1]}}\n",
|
||||||
// },
|
},
|
||||||
// }, {
|
}, {
|
||||||
// document: `{a: {also: me}, b: {also: {g: wizz}}}`,
|
document: `{a: {also: me}, b: {also: {g: wizz}}}`,
|
||||||
// expression: `.a * .b`,
|
expression: `. * {"a":.b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// "D0, P[], (!!map)::{a: {also: {g: wizz}}, b: {also: {g: wizz}}}\n",
|
"D0, P[], (!!map)::{a: {also: {g: wizz}}, b: {also: {g: wizz}}}\n",
|
||||||
// },
|
},
|
||||||
// }, {
|
}, {
|
||||||
// document: `{a: {also: {g: wizz}}, b: {also: me}}`,
|
document: `{a: {also: {g: wizz}}, b: {also: me}}`,
|
||||||
// expression: `.a * .b`,
|
expression: `. * {"a":.b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// "D0, P[], (!!map)::{a: {also: me}, b: {also: me}}\n",
|
"D0, P[], (!!map)::{a: {also: me}, b: {also: me}}\n",
|
||||||
// },
|
},
|
||||||
// }, {
|
}, {
|
||||||
// document: `{a: {also: {g: wizz}}, b: {also: [1]}}`,
|
document: `{a: {also: {g: wizz}}, b: {also: [1]}}`,
|
||||||
// expression: `.a * .b`,
|
expression: `. * {"a":.b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// "D0, P[], (!!map)::{a: {also: [1]}, b: {also: [1]}}\n",
|
"D0, P[], (!!map)::{a: {also: [1]}, b: {also: [1]}}\n",
|
||||||
// },
|
},
|
||||||
// }, {
|
}, {
|
||||||
// document: `{a: {also: [1]}, b: {also: {g: wizz}}}`,
|
document: `{a: {also: [1]}, b: {also: {g: wizz}}}`,
|
||||||
// expression: `.a * .b`,
|
expression: `. * {"a":.b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// "D0, P[], (!!map)::{a: {also: {g: wizz}}, b: {also: {g: wizz}}}\n",
|
"D0, P[], (!!map)::{a: {also: {g: wizz}}, b: {also: {g: wizz}}}\n",
|
||||||
// },
|
},
|
||||||
// }, {
|
}, {
|
||||||
// document: `{a: {things: great}, b: {also: me}}`,
|
document: `{a: {things: great}, b: {also: me}}`,
|
||||||
// expression: `.a * .b`,
|
expression: `. * {"a":.b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// "D0, P[], (!!map)::{a: {things: great, also: me}, b: {also: me}}\n",
|
"D0, P[], (!!map)::{a: {things: great, also: me}, b: {also: me}}\n",
|
||||||
// },
|
},
|
||||||
// }, {
|
}, {
|
||||||
// document: `a: {things: great}
|
document: `a: {things: great}
|
||||||
// b:
|
b:
|
||||||
// also: "me"
|
also: "me"
|
||||||
// `,
|
`,
|
||||||
// expression: `(.a * .b)`,
|
expression: `. * {"a":.b}`,
|
||||||
// expected: []string{
|
expected: []string{
|
||||||
// `D0, P[], (!!map)::a:
|
`D0, P[], (!!map)::a: {things: great, also: me}
|
||||||
// things: great
|
b:
|
||||||
// also: "me"
|
also: "me"
|
||||||
// b:
|
`,
|
||||||
// also: "me"
|
},
|
||||||
// `,
|
}, {
|
||||||
// },
|
document: `{a: [1,2,3], b: [3,4,5]}`,
|
||||||
// }, {
|
expression: `. * {"a":.b}`,
|
||||||
// document: `{a: [1,2,3], b: [3,4,5]}`,
|
expected: []string{
|
||||||
// expression: `.a * .b`,
|
"D0, P[], (!!map)::{a: [3, 4, 5], b: [3, 4, 5]}\n",
|
||||||
// expected: []string{
|
},
|
||||||
// "D0, P[], (!!map)::{a: [3, 4, 5], b: [3, 4, 5]}\n",
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,14 +16,11 @@ func RecursiveDescentOperator(d *dataTreeNavigator, matchMap *list.List, pathNod
|
|||||||
}
|
}
|
||||||
|
|
||||||
func recursiveDecent(d *dataTreeNavigator, results *list.List, matchMap *list.List) error {
|
func recursiveDecent(d *dataTreeNavigator, results *list.List, matchMap *list.List) error {
|
||||||
splatOperation := &Operation{OperationType: TraversePath, Value: "[]"}
|
|
||||||
splatTreeNode := &PathTreeNode{Operation: splatOperation}
|
|
||||||
|
|
||||||
for el := matchMap.Front(); el != nil; el = el.Next() {
|
for el := matchMap.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
results.PushBack(candidate)
|
results.PushBack(candidate)
|
||||||
|
|
||||||
children, err := TraversePathOperator(d, nodeToMap(candidate), splatTreeNode)
|
children, err := Splat(d, nodeToMap(candidate))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -8,6 +8,12 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Splat(d *dataTreeNavigator, matches *list.List) (*list.List, error) {
|
||||||
|
splatOperation := &Operation{OperationType: TraversePath, Value: "[]"}
|
||||||
|
splatTreeNode := &PathTreeNode{Operation: splatOperation}
|
||||||
|
return TraversePathOperator(d, matches, splatTreeNode)
|
||||||
|
}
|
||||||
|
|
||||||
func TraversePathOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
func TraversePathOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||||
log.Debugf("-- Traversing")
|
log.Debugf("-- Traversing")
|
||||||
var matchingNodeMap = list.New()
|
var matchingNodeMap = list.New()
|
||||||
|
@ -59,6 +59,11 @@ var pathTests = []struct {
|
|||||||
append(make([]interface{}, 0), "[", "true (bool)", "]"),
|
append(make([]interface{}, 0), "[", "true (bool)", "]"),
|
||||||
append(make([]interface{}, 0), "true (bool)", "COLLECT", "PIPE"),
|
append(make([]interface{}, 0), "true (bool)", "COLLECT", "PIPE"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`[true, false]`,
|
||||||
|
append(make([]interface{}, 0), "[", "true (bool)", "UNION", "false (bool)", "]"),
|
||||||
|
append(make([]interface{}, 0), "true (bool)", "false (bool)", "UNION", "COLLECT", "PIPE"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
`"mike": .a`,
|
`"mike": .a`,
|
||||||
append(make([]interface{}, 0), "mike (string)", "CREATE_MAP", "a"),
|
append(make([]interface{}, 0), "mike (string)", "CREATE_MAP", "a"),
|
||||||
@ -69,6 +74,21 @@ var pathTests = []struct {
|
|||||||
append(make([]interface{}, 0), "a", "CREATE_MAP", "mike (string)"),
|
append(make([]interface{}, 0), "a", "CREATE_MAP", "mike (string)"),
|
||||||
append(make([]interface{}, 0), "a", "mike (string)", "CREATE_MAP"),
|
append(make([]interface{}, 0), "a", "mike (string)", "CREATE_MAP"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`{"mike": .a}`,
|
||||||
|
append(make([]interface{}, 0), "{", "mike (string)", "CREATE_MAP", "a", "}"),
|
||||||
|
append(make([]interface{}, 0), "mike (string)", "a", "CREATE_MAP", "COLLECT_OBJECT", "PIPE"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`{.a: "mike"}`,
|
||||||
|
append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "mike (string)", "}"),
|
||||||
|
append(make([]interface{}, 0), "a", "mike (string)", "CREATE_MAP", "COLLECT_OBJECT", "PIPE"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`{.a: .c, .b[]: .f.g[]}`,
|
||||||
|
append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "c", "UNION", "b", "PIPE", "[]", "CREATE_MAP", "f", "PIPE", "g", "PIPE", "[]", "}"),
|
||||||
|
append(make([]interface{}, 0), "a", "c", "CREATE_MAP", "b", "[]", "PIPE", "f", "g", "PIPE", "[]", "PIPE", "CREATE_MAP", "UNION", "COLLECT_OBJECT", "PIPE"),
|
||||||
|
},
|
||||||
|
|
||||||
// {".animals | .==cat", append(make([]interface{}, 0), "animals", "TRAVERSE", "SELF", "EQUALS", "cat")},
|
// {".animals | .==cat", append(make([]interface{}, 0), "animals", "TRAVERSE", "SELF", "EQUALS", "cat")},
|
||||||
// {".animals | (. == cat)", append(make([]interface{}, 0), "animals", "TRAVERSE", "(", "SELF", "EQUALS", "cat", ")")},
|
// {".animals | (. == cat)", append(make([]interface{}, 0), "animals", "TRAVERSE", "(", "SELF", "EQUALS", "cat", ")")},
|
||||||
|
@ -32,10 +32,16 @@ func (p *pathPostFixer) ConvertToPostfix(infixTokens []*Token) ([]*Operation, er
|
|||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
log.Debugf("postfix processing token %v, %v", token.toString(), token.Operation)
|
log.Debugf("postfix processing token %v, %v", token.toString(), token.Operation)
|
||||||
switch token.TokenType {
|
switch token.TokenType {
|
||||||
case OpenBracket, OpenCollect:
|
case OpenBracket, OpenCollect, OpenCollectObject:
|
||||||
opStack = append(opStack, token)
|
opStack = append(opStack, token)
|
||||||
case CloseCollect:
|
case CloseCollect, CloseCollectObject:
|
||||||
for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != OpenCollect {
|
var opener TokenType = OpenCollect
|
||||||
|
var collectOperator *OperationType = Collect
|
||||||
|
if token.TokenType == CloseCollectObject {
|
||||||
|
opener = OpenCollectObject
|
||||||
|
collectOperator = CollectObject
|
||||||
|
}
|
||||||
|
for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != opener {
|
||||||
opStack, result = popOpToResult(opStack, result)
|
opStack, result = popOpToResult(opStack, result)
|
||||||
}
|
}
|
||||||
if len(opStack) == 0 {
|
if len(opStack) == 0 {
|
||||||
@ -45,7 +51,7 @@ func (p *pathPostFixer) ConvertToPostfix(infixTokens []*Token) ([]*Operation, er
|
|||||||
opStack = opStack[0 : len(opStack)-1]
|
opStack = opStack[0 : len(opStack)-1]
|
||||||
//and append a collect to the opStack
|
//and append a collect to the opStack
|
||||||
opStack = append(opStack, &Token{TokenType: OperationToken, Operation: &Operation{OperationType: Pipe}})
|
opStack = append(opStack, &Token{TokenType: OperationToken, Operation: &Operation{OperationType: Pipe}})
|
||||||
opStack = append(opStack, &Token{TokenType: OperationToken, Operation: &Operation{OperationType: Collect}})
|
opStack = append(opStack, &Token{TokenType: OperationToken, Operation: &Operation{OperationType: collectOperator}})
|
||||||
case CloseBracket:
|
case CloseBracket:
|
||||||
for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != OpenBracket {
|
for len(opStack) > 0 && opStack[len(opStack)-1].TokenType != OpenBracket {
|
||||||
opStack, result = popOpToResult(opStack, result)
|
opStack, result = popOpToResult(opStack, result)
|
||||||
|
Loading…
Reference in New Issue
Block a user