forked from jshiffer/matterbridge
145 lines
3.5 KiB
Go
145 lines
3.5 KiB
Go
|
package ast
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"unsafe"
|
||
|
|
||
|
"github.com/pelletier/go-toml/v2/internal/danger"
|
||
|
)
|
||
|
|
||
|
// Iterator starts uninitialized, you need to call Next() first.
|
||
|
//
|
||
|
// For example:
|
||
|
//
|
||
|
// it := n.Children()
|
||
|
// for it.Next() {
|
||
|
// it.Node()
|
||
|
// }
|
||
|
type Iterator struct {
|
||
|
started bool
|
||
|
node *Node
|
||
|
}
|
||
|
|
||
|
// Next moves the iterator forward and returns true if points to a
|
||
|
// node, false otherwise.
|
||
|
func (c *Iterator) Next() bool {
|
||
|
if !c.started {
|
||
|
c.started = true
|
||
|
} else if c.node.Valid() {
|
||
|
c.node = c.node.Next()
|
||
|
}
|
||
|
return c.node.Valid()
|
||
|
}
|
||
|
|
||
|
// IsLast returns true if the current node of the iterator is the last
|
||
|
// one. Subsequent call to Next() will return false.
|
||
|
func (c *Iterator) IsLast() bool {
|
||
|
return c.node.next == 0
|
||
|
}
|
||
|
|
||
|
// Node returns a copy of the node pointed at by the iterator.
|
||
|
func (c *Iterator) Node() *Node {
|
||
|
return c.node
|
||
|
}
|
||
|
|
||
|
// Root contains a full AST.
|
||
|
//
|
||
|
// It is immutable once constructed with Builder.
|
||
|
type Root struct {
|
||
|
nodes []Node
|
||
|
}
|
||
|
|
||
|
// Iterator over the top level nodes.
|
||
|
func (r *Root) Iterator() Iterator {
|
||
|
it := Iterator{}
|
||
|
if len(r.nodes) > 0 {
|
||
|
it.node = &r.nodes[0]
|
||
|
}
|
||
|
return it
|
||
|
}
|
||
|
|
||
|
func (r *Root) at(idx Reference) *Node {
|
||
|
return &r.nodes[idx]
|
||
|
}
|
||
|
|
||
|
// Arrays have one child per element in the array. InlineTables have
|
||
|
// one child per key-value pair in the table. KeyValues have at least
|
||
|
// two children. The first one is the value. The rest make a
|
||
|
// potentially dotted key. Table and Array table have one child per
|
||
|
// element of the key they represent (same as KeyValue, but without
|
||
|
// the last node being the value).
|
||
|
type Node struct {
|
||
|
Kind Kind
|
||
|
Raw Range // Raw bytes from the input.
|
||
|
Data []byte // Node value (either allocated or referencing the input).
|
||
|
|
||
|
// References to other nodes, as offsets in the backing array
|
||
|
// from this node. References can go backward, so those can be
|
||
|
// negative.
|
||
|
next int // 0 if last element
|
||
|
child int // 0 if no child
|
||
|
}
|
||
|
|
||
|
type Range struct {
|
||
|
Offset uint32
|
||
|
Length uint32
|
||
|
}
|
||
|
|
||
|
// Next returns a copy of the next node, or an invalid Node if there
|
||
|
// is no next node.
|
||
|
func (n *Node) Next() *Node {
|
||
|
if n.next == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
ptr := unsafe.Pointer(n)
|
||
|
size := unsafe.Sizeof(Node{})
|
||
|
return (*Node)(danger.Stride(ptr, size, n.next))
|
||
|
}
|
||
|
|
||
|
// Child returns a copy of the first child node of this node. Other
|
||
|
// children can be accessed calling Next on the first child. Returns
|
||
|
// an invalid Node if there is none.
|
||
|
func (n *Node) Child() *Node {
|
||
|
if n.child == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
ptr := unsafe.Pointer(n)
|
||
|
size := unsafe.Sizeof(Node{})
|
||
|
return (*Node)(danger.Stride(ptr, size, n.child))
|
||
|
}
|
||
|
|
||
|
// Valid returns true if the node's kind is set (not to Invalid).
|
||
|
func (n *Node) Valid() bool {
|
||
|
return n != nil
|
||
|
}
|
||
|
|
||
|
// Key returns the child nodes making the Key on a supported
|
||
|
// node. Panics otherwise. They are guaranteed to be all be of the
|
||
|
// Kind Key. A simple key would return just one element.
|
||
|
func (n *Node) Key() Iterator {
|
||
|
switch n.Kind {
|
||
|
case KeyValue:
|
||
|
value := n.Child()
|
||
|
if !value.Valid() {
|
||
|
panic(fmt.Errorf("KeyValue should have at least two children"))
|
||
|
}
|
||
|
return Iterator{node: value.Next()}
|
||
|
case Table, ArrayTable:
|
||
|
return Iterator{node: n.Child()}
|
||
|
default:
|
||
|
panic(fmt.Errorf("Key() is not supported on a %s", n.Kind))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Value returns a pointer to the value node of a KeyValue.
|
||
|
// Guaranteed to be non-nil. Panics if not called on a KeyValue node,
|
||
|
// or if the Children are malformed.
|
||
|
func (n *Node) Value() *Node {
|
||
|
return n.Child()
|
||
|
}
|
||
|
|
||
|
// Children returns an iterator over a node's children.
|
||
|
func (n *Node) Children() Iterator {
|
||
|
return Iterator{node: n.Child()}
|
||
|
}
|