Tree.java: resolve any lifting at Tree-creation time
[sbp.git] / src / edu / berkeley / sbp / Tree.java
1 // Copyright 2006 all rights reserved; see LICENSE file for BSD-style license
2
3 package edu.berkeley.sbp;
4 import edu.berkeley.sbp.*;
5 import edu.berkeley.sbp.util.*;
6 import java.io.*;
7 import java.util.*;
8 import java.lang.reflect.*;
9
10 /** <font color=blue>a tree (or node in a tree); see jargon.txt for details</font> */
11 public class Tree<NodeType>
12     extends PrintableTree<Tree<NodeType>>
13     implements Iterable<Tree<NodeType>> {
14
15     private final Input.Region     location;
16     private final NodeType         ihead;
17     private final Tree<NodeType>[] children;
18
19     /** the number of children the tree has */
20     public int               size() { return children.length; }
21
22     /** the element at the head of the tree */
23     public NodeType                 head()        { return ihead; }
24     public NodeType              getHead()        { return ihead; }
25
26     /** the tree's children */
27     public Iterable<Tree<NodeType>> children()    { return this; }
28
29     /** the tree's children */
30     public Iterator<Tree<NodeType>> iterator()    { return new ArrayIterator(children); }
31
32     /** get the <tt>i</t>th child */
33     public Tree<NodeType> child(int i)            { return children[i]; }
34
35     /** get the input region that this tree was parsed from */
36     public Input.Region    getRegion() { return location; }
37
38     public Tree(Input.Region loc, NodeType head)                            { this(loc, head, null); }
39     public Tree(Input.Region loc, NodeType head, Tree<NodeType>[] children) { this(loc, head, children, false); }
40
41     // FIXME: fairly inefficient because we keep copying arrays
42     /** package-private constructor, allows setting the "lift" bit */
43     Tree(Input.Region loc, NodeType head, Tree<NodeType>[] children, boolean lift) {
44         this.location = loc;
45         this.ihead = head;
46         if (lift && children != null && children.length > 0) {
47             Tree<NodeType> last = children[children.length-1];
48             this.children = new Tree[(children.length-1)+last.children.length];
49             System.arraycopy(children, 0, this.children, 0, children.length-1);
50             if (last.children.length > 0)
51                 System.arraycopy(last.children, 0, this.children, children.length-1, last.children.length);
52         } else {
53             this.children = ArrayUtil.clone(children, Tree.class);
54         }
55     }
56
57
58     // PrintableTree /////////////////////////////////////////////////////////////////////////////
59
60     protected String headToString() { return head()==null?null:head().toString(); }
61     protected String headToJava()   {
62       // FIXME
63         if (head()==null) return null;
64         if (head() instanceof ToJava) {
65             StringBuffer sb = new StringBuffer();
66             ((ToJava)head()).toJava(sb);
67             return sb.toString();
68         }
69         return (head()==null?"null":("\""+StringUtil.toJavaString(head().toString())+"\""));
70     }
71     protected String left()   { return "{"; }
72     protected String right()  { return "}"; }
73     protected boolean ignoreSingleton() { return false; }
74
75
76 }