go-yaml/parser/node.go
Masaaki Goshima c331468e5b
support entry token for flow style. (#646)
- add sequence entry node for flow sequence.
- add collect entry token field to mapping value node for flow mapping.
2025-02-11 12:15:41 +09:00

257 lines
6.5 KiB
Go

package parser
import (
"fmt"
"github.com/goccy/go-yaml/ast"
"github.com/goccy/go-yaml/internal/errors"
"github.com/goccy/go-yaml/token"
)
func newMappingNode(ctx *context, tk *Token, isFlow bool, values ...*ast.MappingValueNode) (*ast.MappingNode, error) {
node := ast.Mapping(tk.RawToken(), isFlow, values...)
node.SetPath(ctx.path)
return node, nil
}
func newMappingValueNode(ctx *context, colonTk, entryTk *Token, key ast.MapKeyNode, value ast.Node) (*ast.MappingValueNode, error) {
node := ast.MappingValue(colonTk.RawToken(), key, value)
node.SetPath(ctx.path)
node.CollectEntry = entryTk.RawToken()
if key.GetToken().Position.Line == value.GetToken().Position.Line {
// originally key was commented, but now that null value has been added, value must be commented.
if err := setLineComment(ctx, value, colonTk); err != nil {
return nil, err
}
// set line comment by colonTk or entryTk.
if err := setLineComment(ctx, value, entryTk); err != nil {
return nil, err
}
} else {
if err := setLineComment(ctx, key, colonTk); err != nil {
return nil, err
}
// set line comment by colonTk or entryTk.
if err := setLineComment(ctx, key, entryTk); err != nil {
return nil, err
}
}
return node, nil
}
func newMappingKeyNode(ctx *context, tk *Token) (*ast.MappingKeyNode, error) {
node := ast.MappingKey(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newAnchorNode(ctx *context, tk *Token) (*ast.AnchorNode, error) {
node := ast.Anchor(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newAliasNode(ctx *context, tk *Token) (*ast.AliasNode, error) {
node := ast.Alias(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newDirectiveNode(ctx *context, tk *Token) (*ast.DirectiveNode, error) {
node := ast.Directive(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newMergeKeyNode(ctx *context, tk *Token) (*ast.MergeKeyNode, error) {
node := ast.MergeKey(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newNullNode(ctx *context, tk *Token) (*ast.NullNode, error) {
node := ast.Null(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newBoolNode(ctx *context, tk *Token) (*ast.BoolNode, error) {
node := ast.Bool(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newIntegerNode(ctx *context, tk *Token) (*ast.IntegerNode, error) {
node := ast.Integer(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newFloatNode(ctx *context, tk *Token) (*ast.FloatNode, error) {
node := ast.Float(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newInfinityNode(ctx *context, tk *Token) (*ast.InfinityNode, error) {
node := ast.Infinity(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newNanNode(ctx *context, tk *Token) (*ast.NanNode, error) {
node := ast.Nan(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newStringNode(ctx *context, tk *Token) (*ast.StringNode, error) {
node := ast.String(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newLiteralNode(ctx *context, tk *Token) (*ast.LiteralNode, error) {
node := ast.Literal(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newTagNode(ctx *context, tk *Token) (*ast.TagNode, error) {
node := ast.Tag(tk.RawToken())
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newSequenceNode(ctx *context, tk *Token, isFlow bool) (*ast.SequenceNode, error) {
node := ast.Sequence(tk.RawToken(), isFlow)
node.SetPath(ctx.path)
if err := setLineComment(ctx, node, tk); err != nil {
return nil, err
}
return node, nil
}
func newTagDefaultScalarValueNode(ctx *context, tag *token.Token) (ast.ScalarNode, error) {
pos := *(tag.Position)
pos.Column++
var (
tk *Token
node ast.ScalarNode
)
switch token.ReservedTagKeyword(tag.Value) {
case token.IntegerTag:
tk = &Token{Token: token.New("0", "0", &pos)}
n, err := newIntegerNode(ctx, tk)
if err != nil {
return nil, err
}
node = n
case token.FloatTag:
tk = &Token{Token: token.New("0", "0", &pos)}
n, err := newFloatNode(ctx, tk)
if err != nil {
return nil, err
}
node = n
case token.StringTag, token.BinaryTag, token.TimestampTag:
tk = &Token{Token: token.New("", "", &pos)}
n, err := newStringNode(ctx, tk)
if err != nil {
return nil, err
}
node = n
case token.BooleanTag:
tk = &Token{Token: token.New("false", "false", &pos)}
n, err := newBoolNode(ctx, tk)
if err != nil {
return nil, err
}
node = n
case token.NullTag:
tk = &Token{Token: token.New("null", "null", &pos)}
n, err := newNullNode(ctx, tk)
if err != nil {
return nil, err
}
node = n
default:
return nil, errors.ErrSyntax(fmt.Sprintf("cannot assign default value for %q tag", tag.Value), tag)
}
ctx.insertToken(tk)
ctx.goNext()
return node, nil
}
func setLineComment(ctx *context, node ast.Node, tk *Token) error {
if tk == nil || tk.LineComment == nil {
return nil
}
comment := ast.CommentGroup([]*token.Token{tk.LineComment})
comment.SetPath(ctx.path)
if err := node.SetComment(comment); err != nil {
return err
}
return nil
}
func setHeadComment(cm *ast.CommentGroupNode, value ast.Node) error {
if cm == nil {
return nil
}
switch n := value.(type) {
case *ast.MappingNode:
if len(n.Values) != 0 && value.GetComment() == nil {
cm.SetPath(n.Values[0].GetPath())
return n.Values[0].SetComment(cm)
}
case *ast.MappingValueNode:
cm.SetPath(n.GetPath())
return n.SetComment(cm)
}
cm.SetPath(value.GetPath())
return value.SetComment(cm)
}