89f970069c
Range() existed to recover byte offsets from Highlight subslices. Now that ParserError carries an explicit Offset field, Range() is unnecessary. Remove it along with the private subsliceOffset helper in ast.go. Tests now use perr.Offset directly and construct Range literals for Shape() calls. Co-authored-by: Thomas Pelletier <thomas@pelletier.dev>
150 lines
3.7 KiB
Go
150 lines
3.7 KiB
Go
package unstable
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// Iterator over a sequence of nodes.
|
|
//
|
|
// Starts uninitialized, you need to call Next() first.
|
|
//
|
|
// For example:
|
|
//
|
|
// it := n.Children()
|
|
// for it.Next() {
|
|
// n := it.Node()
|
|
// // do something with n
|
|
// }
|
|
type Iterator struct {
|
|
nodes *[]Node
|
|
idx int32
|
|
started bool
|
|
}
|
|
|
|
// Next moves the iterator forward and returns true if points to a
|
|
// node, false otherwise.
|
|
func (c *Iterator) Next() bool {
|
|
if c.nodes == nil {
|
|
return false
|
|
}
|
|
nodes := *c.nodes
|
|
if !c.started {
|
|
c.started = true
|
|
} else {
|
|
idx := c.idx
|
|
if idx >= 0 && int(idx) < len(nodes) {
|
|
c.idx = nodes[idx].next
|
|
}
|
|
}
|
|
return c.idx >= 0 && int(c.idx) < len(nodes)
|
|
}
|
|
|
|
// IsLast returns true if the current node of the iterator is the last
|
|
// one. Subsequent calls to Next() will return false.
|
|
func (c *Iterator) IsLast() bool {
|
|
return c.nodes == nil || c.idx < 0 || (*c.nodes)[c.idx].next < 0
|
|
}
|
|
|
|
// Node returns a pointer to the node pointed at by the iterator.
|
|
func (c *Iterator) Node() *Node {
|
|
if c.nodes == nil || c.idx < 0 {
|
|
return nil
|
|
}
|
|
n := &(*c.nodes)[c.idx]
|
|
n.nodes = c.nodes
|
|
return n
|
|
}
|
|
|
|
// Node in a TOML expression AST.
|
|
//
|
|
// Depending on Kind, its sequence of children should be interpreted
|
|
// differently.
|
|
//
|
|
// - Array have one child per element in the array.
|
|
// - InlineTable have one child per key-value in the table (each of kind
|
|
// InlineTable).
|
|
// - KeyValue have at least two children. The first one is the value. The rest
|
|
// make a potentially dotted key.
|
|
// - Table and ArrayTable's children represent a dotted key (same as
|
|
// KeyValue, but without the first node being the value).
|
|
//
|
|
// When relevant, Raw describes the range of bytes this node is referring to in
|
|
// the input document. Use Parser.Raw() to retrieve the actual bytes.
|
|
type Node struct {
|
|
Kind Kind
|
|
Raw Range // Raw bytes from the input.
|
|
Data []byte // Node value (either allocated or referencing the input).
|
|
|
|
// Absolute indices into the backing nodes slice. -1 means none.
|
|
next int32
|
|
child int32
|
|
|
|
// Reference to the backing nodes slice for navigation.
|
|
nodes *[]Node
|
|
}
|
|
|
|
// Range of bytes in the document.
|
|
type Range struct {
|
|
Offset uint32
|
|
Length uint32
|
|
}
|
|
|
|
// Next returns a pointer to the next node, or nil if there is no next node.
|
|
func (n *Node) Next() *Node {
|
|
if n.next < 0 {
|
|
return nil
|
|
}
|
|
next := &(*n.nodes)[n.next]
|
|
next.nodes = n.nodes
|
|
return next
|
|
}
|
|
|
|
// Child returns a pointer to the first child node of this node. Other children
|
|
// can be accessed calling Next on the first child. Returns nil if this Node
|
|
// has no child.
|
|
func (n *Node) Child() *Node {
|
|
if n.child < 0 {
|
|
return nil
|
|
}
|
|
child := &(*n.nodes)[n.child]
|
|
child.nodes = n.nodes
|
|
return 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 children 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:
|
|
child := n.child
|
|
if child < 0 {
|
|
panic(errors.New("KeyValue should have at least two children"))
|
|
}
|
|
valueNode := &(*n.nodes)[child]
|
|
return Iterator{nodes: n.nodes, idx: valueNode.next}
|
|
case Table, ArrayTable:
|
|
return Iterator{nodes: n.nodes, idx: 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{nodes: n.nodes, idx: n.child}
|
|
}
|