mirror of
https://github.com/mikefarah/yq.git
synced 2026-09-06 02:03:24 +08:00
Generic ast (#1829)
Remove dependency on yaml.Node for internal AST representation. Yaml decoder is now just another decoder.
This commit is contained in:
@@ -3,64 +3,59 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func entrySeqFor(key *yaml.Node, value *yaml.Node) *yaml.Node {
|
||||
var keyKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "key"}
|
||||
var valueKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "value"}
|
||||
func entrySeqFor(key *CandidateNode, value *CandidateNode) *CandidateNode {
|
||||
var keyKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "key"}
|
||||
var valueKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "value"}
|
||||
|
||||
return &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
return &CandidateNode{
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
Content: []*yaml.Node{keyKey, key, valueKey, value},
|
||||
Content: []*CandidateNode{keyKey, key, valueKey, value},
|
||||
}
|
||||
}
|
||||
|
||||
func toEntriesFromMap(candidateNode *CandidateNode) *CandidateNode {
|
||||
var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
|
||||
var sequence = candidateNode.CreateReplacementWithComments(SequenceNode, "!!seq", 0)
|
||||
|
||||
var contents = unwrapDoc(candidateNode.Node).Content
|
||||
var contents = candidateNode.Content
|
||||
for index := 0; index < len(contents); index = index + 2 {
|
||||
key := contents[index]
|
||||
value := contents[index+1]
|
||||
|
||||
sequence.Content = append(sequence.Content, entrySeqFor(key, value))
|
||||
sequence.AddChild(entrySeqFor(key, value))
|
||||
}
|
||||
return entriesNode
|
||||
return sequence
|
||||
}
|
||||
|
||||
func toEntriesfromSeq(candidateNode *CandidateNode) *CandidateNode {
|
||||
var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
|
||||
var sequence = candidateNode.CreateReplacementWithComments(SequenceNode, "!!seq", 0)
|
||||
|
||||
var contents = unwrapDoc(candidateNode.Node).Content
|
||||
var contents = candidateNode.Content
|
||||
for index := 0; index < len(contents); index = index + 1 {
|
||||
key := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)}
|
||||
key := &CandidateNode{Kind: ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)}
|
||||
value := contents[index]
|
||||
|
||||
sequence.Content = append(sequence.Content, entrySeqFor(key, value))
|
||||
sequence.AddChild(entrySeqFor(key, value))
|
||||
}
|
||||
return entriesNode
|
||||
return sequence
|
||||
}
|
||||
|
||||
func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
var results = list.New()
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
|
||||
switch candidateNode.Kind {
|
||||
case yaml.MappingNode:
|
||||
switch candidate.Kind {
|
||||
case MappingNode:
|
||||
results.PushBack(toEntriesFromMap(candidate))
|
||||
|
||||
case yaml.SequenceNode:
|
||||
case SequenceNode:
|
||||
results.PushBack(toEntriesfromSeq(candidate))
|
||||
default:
|
||||
if candidateNode.Tag != "!!null" {
|
||||
return Context{}, fmt.Errorf("%v has no keys", candidate.Node.Tag)
|
||||
if candidate.Tag != "!!null" {
|
||||
return Context{}, fmt.Errorf("%v has no keys", candidate.Tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,9 +63,8 @@ func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error) {
|
||||
func parseEntry(candidateNode *CandidateNode, position int) (*CandidateNode, *CandidateNode, error) {
|
||||
prefs := traversePreferences{DontAutoCreate: true}
|
||||
candidateNode := &CandidateNode{Node: entry}
|
||||
|
||||
keyResults, err := traverseMap(Context{}, candidateNode, createStringScalarNode("key"), prefs, false)
|
||||
|
||||
@@ -88,15 +82,14 @@ func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error)
|
||||
return nil, nil, fmt.Errorf("expected to find one 'value' entry but found %v in position %v", valueResults.Len(), position)
|
||||
}
|
||||
|
||||
return keyResults.Front().Value.(*CandidateNode).Node, valueResults.Front().Value.(*CandidateNode).Node, nil
|
||||
return keyResults.Front().Value.(*CandidateNode), valueResults.Front().Value.(*CandidateNode), nil
|
||||
|
||||
}
|
||||
|
||||
func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) {
|
||||
var node = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
|
||||
var mapCandidateNode = candidateNode.CreateReplacementWithDocWrappers(node)
|
||||
var node = candidateNode.CopyWithoutContent()
|
||||
|
||||
var contents = unwrapDoc(candidateNode.Node).Content
|
||||
var contents = candidateNode.Content
|
||||
|
||||
for index := 0; index < len(contents); index = index + 1 {
|
||||
key, value, err := parseEntry(contents[index], index)
|
||||
@@ -104,19 +97,20 @@ func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node.Content = append(node.Content, key, value)
|
||||
node.AddKeyValueChild(key, value)
|
||||
}
|
||||
return mapCandidateNode, nil
|
||||
node.Kind = MappingNode
|
||||
node.Tag = "!!map"
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func fromEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
var results = list.New()
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
|
||||
switch candidateNode.Kind {
|
||||
case yaml.SequenceNode:
|
||||
switch candidate.Kind {
|
||||
case SequenceNode:
|
||||
mapResult, err := fromEntries(candidate)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
@@ -162,8 +156,13 @@ func withEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
log.Debug("candidate %v", NodeToString(candidate))
|
||||
log.Debug("candidate leading content: %v", candidate.LeadingContent)
|
||||
collected.LeadingContent = candidate.LeadingContent
|
||||
collected.TrailingContent = candidate.TrailingContent
|
||||
log.Debug("candidate FootComment: [%v]", candidate.FootComment)
|
||||
|
||||
collected.HeadComment = candidate.HeadComment
|
||||
collected.FootComment = candidate.FootComment
|
||||
|
||||
log.Debugf("**** collected %v", collected.LeadingContent)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user