package ast import ( "fmt" ) // Iterator starts uninitialized, you need to call Next() first. // // For example: // // it := n.Children() // for it.Next() { // it.Node() // } type Iterator interface { // Next moves the iterator forward and returns true if points to a node, false // otherwise. Next() bool // Node returns a copy of the node pointed at by the iterator. Node() Node } type chainIterator struct { started bool node Node } func (c *chainIterator) Next() bool { if !c.started { c.started = true } else if c.node.Valid() { c.node = c.node.Next() } return c.node.Valid() } func (c *chainIterator) Node() Node { return c.node } type Root struct { nodes []Node } func (r *Root) Iterator() Iterator { it := &chainIterator{} if len(r.nodes) > 0 { it.node = r.nodes[0] } return it } func (r *Root) Reset() { r.nodes = r.nodes[:0] } func (r *Root) at(idx int) Node { // TODO: unsafe to point to the node directly 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). // children []Node type Node struct { Kind Kind Data []byte // Raw bytes from the input // next idx (in the root array). 0 if last of the collection. next int // child idx (in the root array). 0 if no child. child int // pointer to the root array root *Root } // 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 NoNode } return n.root.at(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 NoNode } return n.root.at(n.child) } func (n Node) Valid() bool { return n.Kind != Invalid } var NoNode = Node{} // 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 &chainIterator{node: value.Next()} case Table, ArrayTable: return &chainIterator{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 { assertKind(KeyValue, n) return n.Child() } func (n Node) Children() Iterator { return &chainIterator{node: n.Child()} } func assertKind(k Kind, n Node) { if n.Kind != k { panic(fmt.Errorf("method was expecting a %s, not a %s", k, n.Kind)) } }