72 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			72 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package unstable
 | |
| 
 | |
| // 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]
 | |
| }
 | |
| 
 | |
| type reference int
 | |
| 
 | |
| const invalidReference reference = -1
 | |
| 
 | |
| func (r reference) Valid() bool {
 | |
| 	return r != invalidReference
 | |
| }
 | |
| 
 | |
| type builder struct {
 | |
| 	tree    root
 | |
| 	lastIdx int
 | |
| }
 | |
| 
 | |
| func (b *builder) Tree() *root {
 | |
| 	return &b.tree
 | |
| }
 | |
| 
 | |
| func (b *builder) NodeAt(ref reference) *Node {
 | |
| 	return b.tree.at(ref)
 | |
| }
 | |
| 
 | |
| func (b *builder) Reset() {
 | |
| 	b.tree.nodes = b.tree.nodes[:0]
 | |
| 	b.lastIdx = 0
 | |
| }
 | |
| 
 | |
| func (b *builder) Push(n Node) reference {
 | |
| 	b.lastIdx = len(b.tree.nodes)
 | |
| 	b.tree.nodes = append(b.tree.nodes, n)
 | |
| 	return reference(b.lastIdx)
 | |
| }
 | |
| 
 | |
| func (b *builder) PushAndChain(n Node) reference {
 | |
| 	newIdx := len(b.tree.nodes)
 | |
| 	b.tree.nodes = append(b.tree.nodes, n)
 | |
| 	if b.lastIdx >= 0 {
 | |
| 		b.tree.nodes[b.lastIdx].next = newIdx - b.lastIdx
 | |
| 	}
 | |
| 	b.lastIdx = newIdx
 | |
| 	return reference(b.lastIdx)
 | |
| }
 | |
| 
 | |
| func (b *builder) AttachChild(parent reference, child reference) {
 | |
| 	b.tree.nodes[parent].child = int(child) - int(parent)
 | |
| }
 | |
| 
 | |
| func (b *builder) Chain(from reference, to reference) {
 | |
| 	b.tree.nodes[from].next = int(to) - int(from)
 | |
| }
 |