1	package antlr;
2	
3	import antlr.collections.AST;
4	import antlr.collections.impl.ASTArray;
5	
6	/** AST Support code shared by TreeParser and Parser.
7	 *  We use delegation to share code (and have only one
8	 *  bit of code to maintain) rather than subclassing
9	 *  or superclassing (forces AST support code to be
10	 *  loaded even when you don't want to do AST stuff).
11	 *
12	 *  Typically, setASTNodeType is used to specify the
13	 *  type of node to create, but you can override
14	 *  create to make heterogeneous nodes etc...
15	 */
16	public class ASTFactory {
17		/** Name of AST class to create during tree construction.
18		 *  Null implies that the create method should create
19		 *  a default AST type such as CommonAST.
20		 */
21		protected String theASTNodeType = null;
22		protected Class theASTNodeTypeClass = null;
23	
24	
25		/** Add a child to the current AST */
26		public void addASTChild(ASTPair currentAST, AST child) {
27			if (child != null) {
28				if (currentAST.root == null) {
29					// Make new child the current root
30					currentAST.root = child;
31				} 
32				else {
33					if (currentAST.child == null) {
34						// Add new child to current root
35						currentAST.root.setFirstChild(child);
36					}
37					else {
38						currentAST.child.setNextSibling(child);
39					}
40				}
41				// Make new child the current child
42				currentAST.child = child;
43				currentAST.advanceChildToEnd();
44			}
45		}
46	/** Create a new empty AST node; if the user did not specify
47	 *  an AST node type, then create a default one: CommonAST.
48	 */
49	public AST create() {
50		AST t = null;
51		if (theASTNodeTypeClass == null) {
52			t = new CommonAST();
53		} else {
54			try {
55				t = (AST) theASTNodeTypeClass.newInstance(); // make a new one
56			} catch (Exception e) {
57				antlr.Tool.warning("Can't create AST Node " + theASTNodeType);
58				return null;
59			}
60		}
61		return t;
62	}
63		public AST create(int type) { 
64			AST t = create();
65			t.initialize(type,"");
66			return t;	
67		}
68		public AST create(int type, String txt) { 
69			AST t = create();
70			t.initialize(type,txt);
71			return t;	
72		}
73		/** Create a new empty AST node; if the user did not specify
74		 *  an AST node type, then create a default one: CommonAST.
75		 */
76		public AST create(AST tr) { 
77			if ( tr==null ) return null;		// create(null) == null
78			AST t = create();
79			t.initialize(tr);
80			return t;	
81		}
82		public AST create(Token tok) { 
83			AST t = create();
84			t.initialize(tok);
85			return t;	
86		}
87		/** Copy a single node.  clone() is not used because
88		 *  we want to return an AST not a plain object...a type
89		 *  safety issue.  Further, we want to have all AST node
90		 *  creation go through the factory so creation can be
91		 *  tracked.  Returns null if t is null.
92		 */
93		public AST dup(AST t) {
94			return create(t);		// if t==null, create returns null
95		}
96		/** Duplicate tree including siblings of root. */
97		public AST dupList(AST t) {
98		AST result = dupTree(t);            // if t == null, then result==null
99		AST nt = result;
100		while (t != null) {						// for each sibling of the root
101			t = t.getNextSibling();
102			nt.setNextSibling(dupTree(t));	// dup each subtree, building new tree
103			nt = nt.getNextSibling();
104		}
105		return result;
106	}
107		/**Duplicate a tree, assuming this is a root node of a tree--
108		 * duplicate that node and what's below; ignore siblings of root node.
109		 */
110		public AST dupTree(AST t) {
111		AST result = dup(t);		// make copy of root
112		// copy all children of root.
113		if ( t!=null ) {
114			result.setFirstChild( dupList(t.getFirstChild()) );
115		}
116		return result;
117		}
118		/** Make a tree from a list of nodes.  The first element in the
119		 *  array is the root.  If the root is null, then the tree is
120		 *  a simple list not a tree.  Handles null children nodes correctly.
121		 *  For example, build(a, b, null, c) yields tree (a b c).  build(null,a,b)
122		 *  yields tree (nil a b).
123		 */
124		public AST make(AST[] nodes) {
125			if ( nodes==null || nodes.length==0 ) return null;
126			AST root = nodes[0];
127			AST tail = null;
128			if (root != null) {
129				root.setFirstChild(null);	// don't leave any old pointers set
130			}
131			// link in children;
132			for (int i=1; i<nodes.length; i++) {
133				if ( nodes[i]==null ) continue;	// ignore null nodes
134				if (root == null) {
135					// Set the root and set it up for a flat list
136					root = tail = nodes[i];
137				}
138				else if ( tail==null ) {
139					root.setFirstChild(nodes[i]);
140					tail = root.getFirstChild();
141				}
142				else {
143					tail.setNextSibling(nodes[i]);
144					tail = tail.getNextSibling();
145				}
146				// Chase tail to last sibling
147				while (tail.getNextSibling() != null) {
148					tail = tail.getNextSibling();
149				}
150			}
151			return root;
152		}
153		/** Make a tree from a list of nodes, where the nodes are contained
154		  * in an ASTArray object
155		  */
156		public AST make(ASTArray nodes) {
157			return make(nodes.array);
158		}
159		/** Make an AST the root of current AST */
160		public void makeASTRoot(ASTPair currentAST, AST root) {
161			if (root != null) {
162				// Add the current root as a child of new root
163				root.addChild(currentAST.root);
164				// The new current child is the last sibling of the old root
165				currentAST.child = currentAST.root;
166				currentAST.advanceChildToEnd();
167				// Set the new root
168				currentAST.root = root;
169			}
170		}
171	public void setASTNodeType(String t) {
172		theASTNodeType = t;
173		try {
174			theASTNodeTypeClass = Class.forName(t); // get class def
175		} catch (Exception e) {
176			// either class not found,
177			// class is interface/abstract, or
178			// class or initializer is not accessible.
179			antlr.Tool.warning("Can't find/access AST Node type"+t);
180		}
181	}
182	}
183