1 using System;
2 using System.Collections;
3 using Assembly			= System.Reflection.Assembly;
4 using ArrayList			= System.Collections.ArrayList;
5 using Debug				= System.Diagnostics.Debug;
6 using AST				= antlr.collections.AST;
7 using ASTArray			= antlr.collections.impl.ASTArray;
8 using ANTLRException	= antlr.ANTLRException;
9 
10 namespace antlr
11 {
12 	/*ANTLR Translator Generator
13 	* Project led by Terence Parr at http://www.jGuru.com
14 	* Software rights: http://www.antlr.org/license.html
15 	*
16 	* $Id:$
17 	*/
18 
19 	//
20 	// ANTLR C# Code Generator by Micheal Jordan
21 	//                            Kunle Odutola       : kunle UNDERSCORE odutola AT hotmail DOT com
22 	//                            Anthony Oguntimehin
23 	//
24 	// With many thanks to Eric V. Smith from the ANTLR list.
25 	//
26 
27 
28 	// HISTORY:
29 	//
30 	// 19-Aug-2002 kunle    Augmented the basic flexibility of the default ASTFactory with a map
31 	//                      of TokenID-to-NodeTypeName. It's now a proper GoF-style Factory ;-)
32 	//
33 
34 	/// <summary>
35 	/// AST Support code shared by TreeParser and Parser.
36 	/// </summary>
37 	/// <remarks>
38 	/// <para>
39 	/// We use delegation to share code (and have only one
40 	/// bit of code to maintain) rather than subclassing
41 	/// or superclassing (forces AST support code to be
42 	/// loaded even when you don't want to do AST stuff).
43 	/// </para>
44 	/// <para>
45 	/// Typically, <see cref="setASTNodeType"/>  is used to specify the
46 	/// homogeneous type of node to create, but you can override
47 	/// <see cref="create"/>  to make heterogeneous nodes etc...
48 	/// </para>
49 	/// </remarks>
50 	public class ASTFactory
51 	{
52 		//---------------------------------------------------------------------
53 		// CONSTRUCTORS
54 		//---------------------------------------------------------------------
55 
56 		/// <summary>
57 		/// Constructs an <c>ASTFactory</c> with the default AST node type of
58 		/// <see cref="antlr.CommonAST"/>.
59 		/// </summary>
ASTFactory()60 		public ASTFactory() : this(typeof(antlr.CommonAST))
61 		{
62 		}
63 
64 		/// <summary>
65 		/// Constructs an <c>ASTFactory</c> and use the specified AST node type
66 		/// as the default.
67 		/// </summary>
68 		/// <param name="nodeTypeName">
69 		///		Name of default AST node type for this factory.
70 		/// </param>
ASTFactory(string nodeTypeName)71 		public ASTFactory(string nodeTypeName)
72 			: this( loadNodeTypeObject(nodeTypeName) )
73 		{
74 		}
75 
76 		/// <summary>
77 		/// Constructs an <c>ASTFactory</c> and use the specified AST node type
78 		/// as the default.
79 		/// </summary>
80 		/// <param name="nodeType">
81 		///		MetaType of default AST node type for this factory.
82 		/// </param>
ASTFactory(Type nodeType)83 		public ASTFactory(Type nodeType)
84 		{
85 			heteroList_					= new FactoryEntry[Token.MIN_USER_TYPE+1];
86 			defaultASTNodeTypeObject_	= nodeType;
87 			defaultCreator_				= null;
88 			typename2creator_			= new Hashtable(32, (float) 0.3);
89 			typename2creator_["antlr.CommonAST"]					= CommonAST.Creator;
90 			typename2creator_["antlr.CommonASTWithHiddenTokens"]	= CommonASTWithHiddenTokens.Creator;
91 
92 		}
93 
94 		//---------------------------------------------------------------------
95 		// DATA MEMBERS
96 		//---------------------------------------------------------------------
97 
98 		/// <summary>
99 		/// Stores the Type of the default AST node class to be used during tree construction.
100 		/// </summary>
101 		protected Type				defaultASTNodeTypeObject_;
102 		protected ASTNodeCreator	defaultCreator_;
103 
104 		/// <summary>
105 		/// Stores the mapping between custom AST NodeTypes and their NodeTypeName/NodeTypeClass
106 		/// and ASTNodeCreator.
107 		/// </summary>
108 		protected FactoryEntry[]	heteroList_;
109 
110 		/// <summary>
111 		/// Stores the mapping between AST node typenames and their token ID.
112 		/// </summary>
113 		protected Hashtable			typename2creator_;
114 
115 		//---------------------------------------------------------------------
116 		// FUNCTION MEMBERS
117 		//---------------------------------------------------------------------
118 
119 		/// <summary>
120 		/// Specify an "override" for the <see cref="AST"/> type created for
121 		/// the specified Token type.
122 		/// </summary>
123 		/// <remarks>
124 		/// This method is useful for situations that ANTLR cannot oridinarily deal
125 		/// with (i.e., when you  create a token based upon a nonliteral token symbol
126 		/// like #[LT(1)].  This is a runtime value and ANTLR cannot determine the token
127 		/// type (and hence the AST) statically.
128 		/// </remarks>
129 		/// <param name="tokenType">Token type to override.</param>
130 		/// <param name="NodeTypeName">
131 		///		Fully qualified AST typename (or null to specify
132 		///		the factory's default AST type).
133 		/// </param>
setTokenTypeASTNodeType(int tokenType, string NodeTypeName)134 		public void setTokenTypeASTNodeType(int tokenType, string NodeTypeName)
135 		{
136 			// check validity of arguments...
137 			if( tokenType < Token.MIN_USER_TYPE )
138 				throw new ANTLRException("Internal parser error: Cannot change AST Node Type for Token ID '" + tokenType + "'");
139 
140 			// resize up to and including 'type' and initialize any gaps to default
141 			// factory.
142 			if (tokenType > (heteroList_.Length+1))
143 				setMaxNodeType(tokenType);
144 			// And add new thing..
145 			if (heteroList_[tokenType] == null)
146                 heteroList_[tokenType] = new FactoryEntry(loadNodeTypeObject(NodeTypeName));
147 			else
148 				heteroList_[tokenType].NodeTypeObject = loadNodeTypeObject(NodeTypeName);
149 		}
150 
151 		/// <summary>
152 		/// Register an AST Node Type for a given Token type ID.
153 		/// </summary>
154 		/// <param name="NodeType">The Token type ID.</param>
155 		/// <param name="NodeTypeName">The AST Node Type to register.</param>
156 		[Obsolete("Replaced by setTokenTypeASTNodeType(int, string) since version 2.7.2.6", true)]
registerFactory(int NodeType, string NodeTypeName)157 		public void registerFactory(int NodeType, string NodeTypeName)
158 		{
159 			setTokenTypeASTNodeType(NodeType, NodeTypeName);
160 		}
161 
162 		/// <summary>
163 		/// Register an ASTNodeCreator for a given Token type ID.
164 		/// </summary>
165 		/// <param name="NodeType">The Token type ID.</param>
166 		/// <param name="creator">The creater to register.</param>
setTokenTypeASTNodeCreator(int NodeType, ASTNodeCreator creator)167 		public void setTokenTypeASTNodeCreator(int NodeType, ASTNodeCreator creator)
168 		{
169 			// check validity of arguments...
170 			if( NodeType < Token.MIN_USER_TYPE )
171 				throw new ANTLRException("Internal parser error: Cannot change AST Node Type for Token ID '" + NodeType + "'");
172 
173 			// resize up to and including 'type' and initialize any gaps to default
174 			// factory.
175 			if (NodeType > (heteroList_.Length+1))
176 				setMaxNodeType(NodeType);
177 			// And add new thing..
178 			if (heteroList_[NodeType] == null)
179 				heteroList_[NodeType] = new FactoryEntry(creator);
180 			else
181 				heteroList_[NodeType].Creator = creator;
182 
183 			//typename2creator_[NodeType.ToString()]		= creator;
184 			typename2creator_[creator.ASTNodeTypeName]	= creator;
185 		}
186 
187 		/// <summary>
188 		/// Register an ASTNodeCreator to be used for creating node by default.
189 		/// </summary>
190 		/// <param name="creator">The ASTNodeCreator.</param>
setASTNodeCreator(ASTNodeCreator creator)191 		public void setASTNodeCreator(ASTNodeCreator creator)
192 		{
193 			defaultCreator_ = creator;
194 		}
195 
196 		/// <summary>
197 		/// Pre-expands the internal list of TokenTypeID-to-ASTNodeType mappings
198 		/// to the specified size.
199 		/// This is primarily a convenience method that can be used to prevent
200 		/// unnecessary and costly re-org of the mappings list.
201 		/// </summary>
202 		/// <param name="NodeType">Maximum Token Type ID.</param>
setMaxNodeType( int NodeType )203 		public void setMaxNodeType( int NodeType )
204 		{
205 			//Debug.WriteLine(this, "NodeType = " + NodeType + " and NodeList.Length = " + nodeTypeList_.Length);
206 			if (heteroList_ == null)
207 			{
208 				heteroList_ = new FactoryEntry[NodeType+1];
209 			}
210 			else
211 			{
212 				int length = heteroList_.Length;
213 
214 				if ( NodeType >= length )
215 				{
216 					FactoryEntry[] newList = new FactoryEntry[NodeType+1];
217 					Array.Copy(heteroList_, 0, newList, 0, length);
218 					heteroList_ = newList;
219 				}
220 				else if ( NodeType < length )
221 				{
222 					FactoryEntry[] newList = new FactoryEntry[NodeType+1];
223 					Array.Copy(heteroList_, 0, newList, 0, (NodeType+1));
224 					heteroList_ = newList;
225 				}
226 			}
227 			//Debug.WriteLine(this, "NodeType = " + NodeType + " and NodeList.Length = " + nodeTypeList_.Length);
228 		}
229 
230 		/// <summary>
231 		/// Add a child to the current AST
232 		/// </summary>
233 		/// <param name="currentAST">The AST to add a child to</param>
234 		/// <param name="child">The child AST to be added</param>
addASTChild(ref ASTPair currentAST, AST child)235 		public virtual void  addASTChild(ref ASTPair currentAST, AST child)
236 		{
237 			if (child != null)
238 			{
239 				if (currentAST.root == null)
240 				{
241 					// Make new child the current root
242 					currentAST.root = child;
243 				}
244 				else
245 				{
246 					if (currentAST.child == null)
247 					{
248 						// Add new child to current root
249 						currentAST.root.setFirstChild(child);
250 					}
251 					else
252 					{
253 						currentAST.child.setNextSibling(child);
254 					}
255 				}
256 				// Make new child the current child
257 				currentAST.child = child;
258 				currentAST.advanceChildToEnd();
259 			}
260 		}
261 
262 		/// <summary>
263 		/// Creates a new uninitialized AST node. Since a specific AST Node Type
264 		/// wasn't indicated, the new AST node is created using the current default
265 		/// AST Node type - <see cref="defaultASTNodeTypeObject_"/>
266 		/// </summary>
267 		/// <returns>An uninitialized AST node object.</returns>
create()268 		public virtual AST create()
269 		{
270 			AST newNode;
271 
272 			if (defaultCreator_ == null)
273 				newNode = createFromNodeTypeObject(defaultASTNodeTypeObject_);
274 			else
275 				newNode = defaultCreator_.Create();
276 
277 			return newNode;
278 		}
279 
280 		/// <summary>
281 		/// Creates and initializes a new AST node using the specified Token Type ID.
282 		/// The <see cref="System.Type"/> used for creating this new AST node is
283 		/// determined by the following:
284 		/// <list type="bullet">
285 		///		<item>the current TokenTypeID-to-ASTNodeType mapping (if any) or,</item>
286 		///		<item>the <see cref="defaultASTNodeTypeObject_"/> otherwise</item>
287 		/// </list>
288 		/// </summary>
289 		/// <param name="type">Token type ID to be used to create new AST Node.</param>
290 		/// <returns>An initialized AST node object.</returns>
create(int type)291 		public virtual AST create(int type)
292 		{
293 			AST newNode = createFromNodeType(type);
294 			newNode.initialize(type, "");
295 			return newNode;
296 		}
297 
298 		/// <summary>
299 		/// Creates and initializes a new AST node using the specified Token Type ID.
300 		/// The <see cref="System.Type"/> used for creating this new AST node is
301 		/// determined by the following:
302 		/// <list type="bullet">
303 		///		<item>the current TokenTypeID-to-ASTNodeType mapping (if any) or,</item>
304 		///		<item>the <see cref="defaultASTNodeTypeObject_"/> otherwise</item>
305 		/// </list>
306 		/// </summary>
307 		/// <param name="type">Token type ID to be used to create new AST Node.</param>
308 		/// <param name="txt">Text for initializing the new AST Node.</param>
309 		/// <returns>An initialized AST node object.</returns>
create(int type, string txt)310 		public virtual AST create(int type, string txt)
311 		{
312 			AST newNode = createFromNodeType(type);
313 			newNode.initialize(type, txt);
314 			return newNode;
315 		}
316 
317 		/// <summary>
318 		/// Creates a new AST node using the specified AST Node Type name. Once created,
319 		/// the new AST node is initialized with the specified Token type ID and string.
320 		/// The <see cref="System.Type"/> used for creating this new AST node is
321 		/// determined solely by <c>ASTNodeTypeName</c>.
322 		/// The AST Node type must have a default/parameterless constructor.
323 		/// </summary>
324 		/// <param name="type">Token type ID to be used to create new AST Node.</param>
325 		/// <param name="txt">Text for initializing the new AST Node.</param>
326 		/// <param name="ASTNodeTypeName">Fully qualified name of the Type to be used for creating the new AST Node.</param>
327 		/// <returns>An initialized AST node object.</returns>
create(int type, string txt, string ASTNodeTypeName)328 		public virtual AST create(int type, string txt, string ASTNodeTypeName)
329 		{
330 			AST newNode = createFromNodeName(ASTNodeTypeName);
331 			newNode.initialize(type, txt);
332 			return newNode;
333 		}
334 
335 		/// <summary>
336 		/// Creates a new AST node using the specified AST Node Type name.
337 		/// </summary>
338 		/// <param name="tok">Token instance to be used to initialize the new AST Node.</param>
339 		/// <param name="ASTNodeTypeName">
340 		///		Fully qualified name of the Type to be used for creating the new AST Node.
341 		///	</param>
342 		/// <returns>A newly created and initialized AST node object.</returns>
343 		/// <remarks>
344 		/// Once created, the new AST node is initialized with the specified Token
345 		/// instance. The <see cref="System.Type"/> used for creating this new AST
346 		/// node is  determined solely by <c>ASTNodeTypeName</c>.
347 		/// <para>The AST Node type must have a default/parameterless constructor.</para>
348 		/// </remarks>
create(IToken tok, string ASTNodeTypeName)349 		public virtual AST create(IToken tok, string ASTNodeTypeName)
350 		{
351 			AST newNode = createFromNodeName(ASTNodeTypeName);
352 			newNode.initialize(tok);
353 			return newNode;
354 		}
355 
356 		/// <summary>
357 		/// Creates and initializes a new AST node using the specified AST Node instance.
358 		/// the new AST node is initialized with the specified Token type ID and string.
359 		/// The <see cref="System.Type"/> used for creating this new AST node is
360 		/// determined solely by <c>aNode</c>.
361 		/// The AST Node type must have a default/parameterless constructor.
362 		/// </summary>
363 		/// <param name="aNode">AST Node instance to be used for creating the new AST Node.</param>
364 		/// <returns>An initialized AST node object.</returns>
create(AST aNode)365 		public virtual AST create(AST aNode)
366 		{
367 			AST	newNode;
368 
369 			if (aNode == null)
370 				newNode = null;
371 			else
372 			{
373 				newNode = createFromAST(aNode);
374 				newNode.initialize(aNode);
375 			}
376 			return newNode;
377 		}
378 
379 		/// <summary>
380 		/// Creates and initializes a new AST node using the specified Token instance.
381 		/// The <see cref="System.Type"/> used for creating this new AST node is
382 		/// determined by the following:
383 		/// <list type="bullet">
384 		///		<item>the current TokenTypeID-to-ASTNodeType mapping (if any) or,</item>
385 		///		<item>the <see cref="defaultASTNodeTypeObject_"/> otherwise</item>
386 		/// </list>
387 		/// </summary>
388 		/// <param name="tok">Token instance to be used to create new AST Node.</param>
389 		/// <returns>An initialized AST node object.</returns>
create(IToken tok)390 		public virtual AST create(IToken tok)
391 		{
392 			AST newNode;
393 
394 			if (tok == null)
395 				newNode = null;
396 			else
397 			{
398 				newNode = createFromNodeType(tok.Type);
399 				newNode.initialize(tok);
400 			}
401 			return newNode;
402 		}
403 
404 		/// <summary>
405 		/// Returns a copy of the specified AST Node instance. The copy is obtained by
406 		/// using the <see cref="ICloneable"/> method Clone().
407 		/// </summary>
408 		/// <param name="t">AST Node to copy.</param>
409 		/// <returns>An AST Node (or null if <c>t</c> is null).</returns>
dup(AST t)410 		public virtual AST dup(AST t)
411 		{
412 			// The Java version is implemented using code like this:
413 			if (t == null)
414 				return null;
415 
416 			AST dup_edNode = createFromAST(t);
417 			dup_edNode.initialize(t);
418 			return dup_edNode;
419 		}
420 
421 		/// <summary>
422 		/// Duplicate AST Node tree rooted at specified AST node and all of it's siblings.
423 		/// </summary>
424 		/// <param name="t">Root of AST Node tree.</param>
425 		/// <returns>Root node of new AST Node tree (or null if <c>t</c> is null).</returns>
dupList(AST t)426 		public virtual AST dupList(AST t)
427 		{
428 			AST result = dupTree(t); // if t == null, then result==null
429 			AST nt = result;
430 			while (t != null)
431 			{
432 				// for each sibling of the root
433 				t = t.getNextSibling();
434 				nt.setNextSibling(dupTree(t)); // dup each subtree, building new tree
435 				nt = nt.getNextSibling();
436 			}
437 			return result;
438 		}
439 
440 		/// <summary>
441 		/// Duplicate AST Node tree rooted at specified AST node. Ignore it's siblings.
442 		/// </summary>
443 		/// <param name="t">Root of AST Node tree.</param>
444 		/// <returns>Root node of new AST Node tree (or null if <c>t</c> is null).</returns>
dupTree(AST t)445 		public virtual AST dupTree(AST t)
446 		{
447 			AST result = dup(t); // make copy of root
448 			// copy all children of root.
449 			if (t != null)
450 			{
451 				result.setFirstChild(dupList(t.getFirstChild()));
452 			}
453 			return result;
454 		}
455 
456 		/// <summary>
457 		/// Make a tree from a list of nodes.  The first element in the
458 		/// array is the root.  If the root is null, then the tree is
459 		/// a simple list not a tree.  Handles null children nodes correctly.
460 		/// For example, build(a, b, null, c) yields tree (a b c).  build(null,a,b)
461 		/// yields tree (nil a b).
462 		/// </summary>
463 		/// <param name="nodes">List of Nodes.</param>
464 		/// <returns>AST Node tree.</returns>
make(params AST[] nodes)465 		public virtual AST make(params AST[] nodes)
466 		{
467 			if (nodes == null || nodes.Length == 0)
468 				return null;
469 			AST root = nodes[0];
470 			AST tail = null;
471 			if (root != null)
472 			{
473 				root.setFirstChild(null); // don't leave any old pointers set
474 			}
475 			// link in children;
476 			for (int i = 1; i < nodes.Length; i++)
477 			{
478 				if (nodes[i] == null)
479 					continue;
480 				// ignore null nodes
481 				if (root == null)
482 				{
483 					// Set the root and set it up for a flat list
484 					root = (tail = nodes[i]);
485 				}
486 				else if (tail == null)
487 				{
488 					root.setFirstChild(nodes[i]);
489 					tail = root.getFirstChild();
490 				}
491 				else
492 				{
493 					tail.setNextSibling(nodes[i]);
494 					tail = tail.getNextSibling();
495 				}
496 				// Chase tail to last sibling
497 				while (tail.getNextSibling() != null)
498 				{
499 					tail = tail.getNextSibling();
500 				}
501 			}
502 			return root;
503 		}
504 
505 		/// <summary>
506 		/// Make a tree from a list of nodes, where the nodes are contained
507 		/// in an ASTArray object.
508 		/// </summary>
509 		/// <param name="nodes">List of Nodes.</param>
510 		/// <returns>AST Node tree.</returns>
make(ASTArray nodes)511 		public virtual AST make(ASTArray nodes)
512 		{
513 			return make(nodes.array);
514 		}
515 
516 		/// <summary>
517 		/// Make an AST the root of current AST.
518 		/// </summary>
519 		/// <param name="currentAST"></param>
520 		/// <param name="root"></param>
makeASTRoot(ref ASTPair currentAST, AST root)521 		public virtual void  makeASTRoot(ref ASTPair currentAST, AST root)
522 		{
523 			if (root != null)
524 			{
525 				// Add the current root as a child of new root
526 				root.addChild(currentAST.root);
527 				// The new current child is the last sibling of the old root
528 				currentAST.child = currentAST.root;
529 				currentAST.advanceChildToEnd();
530 				// Set the new root
531 				currentAST.root = root;
532 			}
533 		}
534 
535 		/// <summary>
536 		/// Sets the global default AST Node Type for this ASTFactory instance.
537 		/// This method also attempts to load the <see cref="System.Type"/> instance
538 		/// for the specified typename.
539 		/// </summary>
540 		/// <param name="t">Fully qualified AST Node Type name.</param>
setASTNodeType(string t)541 		public virtual void  setASTNodeType(string t)
542 		{
543 			if (defaultCreator_ != null)
544 			{
545 				if (t != defaultCreator_.ASTNodeTypeName)
546 				{
547 					defaultCreator_ = null;
548 				}
549 			}
550 			defaultASTNodeTypeObject_ = loadNodeTypeObject(t);
551 		}
552 
553 		/// <summary>
554 		/// To change where error messages go, can subclass/override this method
555 		/// and then setASTFactory in Parser and TreeParser.  This method removes
556 		/// a prior dependency on class antlr.Tool.
557 		/// </summary>
558 		/// <param name="e"></param>
error(string e)559 		public virtual void  error(string e)
560 		{
561 			Console.Error.WriteLine(e);
562 		}
563 
564 		//---------------------------------------------------------------------
565 		// PRIVATE FUNCTION MEMBERS
566 		//---------------------------------------------------------------------
567 
loadNodeTypeObject(string nodeTypeName)568 		private static Type loadNodeTypeObject(string nodeTypeName)
569 		{
570 			Type	nodeTypeObject	= null;
571 			bool	typeCreated		= false;
572 
573 			if (nodeTypeName != null)
574 			{
575 				foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
576 				{
577 					try
578 					{
579 						nodeTypeObject = assem.GetType(nodeTypeName);
580 						if (nodeTypeObject != null)
581 						{
582 							typeCreated = true;
583 							break;
584 						}
585 					}
586 					catch
587 					{
588 						typeCreated = false;
589 					}
590 				}
591 			}
592 			if (!typeCreated)
593 			{
594 				throw new TypeLoadException("Unable to load AST Node Type: '" + nodeTypeName + "'");
595 			}
596 			return nodeTypeObject;
597 		}
598 
createFromAST(AST node)599 		private AST createFromAST(AST node)
600 		{
601 			AST		newNode			= null;
602 			Type	nodeAsTypeObj	= node.GetType();
603 
604 			ASTNodeCreator creator = (ASTNodeCreator) typename2creator_[nodeAsTypeObj.FullName];
605 			if (creator != null)
606 			{
607 				newNode = creator.Create();
608 				if (newNode == null)
609 				{
610 					throw new ArgumentException("Unable to create AST Node Type: '" + nodeAsTypeObj.FullName + "'");
611 				}
612 			}
613 			else
614 			{
615 				newNode = createFromNodeTypeObject(nodeAsTypeObj);
616 			}
617 			return newNode;
618 		}
619 
createFromNodeName(string nodeTypeName)620 		private AST createFromNodeName(string nodeTypeName)
621 		{
622 			AST		newNode			= null;
623 
624 			ASTNodeCreator creator = (ASTNodeCreator) typename2creator_[nodeTypeName];
625 			if (creator != null)
626 			{
627 				newNode = creator.Create();
628 				if (newNode == null)
629 				{
630 					throw new ArgumentException("Unable to create AST Node Type: '" + nodeTypeName + "'");
631 				}
632 			}
633 			else
634 			{
635 				newNode = createFromNodeTypeObject( loadNodeTypeObject(nodeTypeName) );
636 			}
637 			return newNode;
638 		}
639 
createFromNodeType(int nodeTypeIndex)640 		private AST createFromNodeType(int nodeTypeIndex)
641 		{
642 			Debug.Assert((nodeTypeIndex >= 0) && (nodeTypeIndex <= heteroList_.Length), "Invalid AST node type!");
643 			AST newNode = null;
644 
645 			FactoryEntry	entry = heteroList_[nodeTypeIndex];
646 			if ((entry != null) && (entry.Creator != null))
647 			{
648 				newNode = entry.Creator.Create();
649 			}
650 			else
651 			{
652 				if ((entry == null) || (entry.NodeTypeObject == null))
653 				{
654 					if (defaultCreator_ == null)
655 					{
656 						newNode = createFromNodeTypeObject(defaultASTNodeTypeObject_);
657 					}
658 					else
659 						newNode = defaultCreator_.Create();
660 				}
661 				else
662                     newNode = createFromNodeTypeObject( entry.NodeTypeObject );
663 			}
664 			return newNode;
665 		}
666 
createFromNodeTypeObject(Type nodeTypeObject)667 		private AST createFromNodeTypeObject(Type nodeTypeObject)
668 		{
669 			AST		newNode			= null;
670 
671 			try
672 			{
673 				newNode = (AST) Activator.CreateInstance(nodeTypeObject);
674 				if (newNode == null)
675 				{
676 					throw new ArgumentException("Unable to create AST Node Type: '" + nodeTypeObject.FullName + "'");
677 				}
678 			}
679 			catch(Exception ex)
680 			{
681 				throw new ArgumentException("Unable to create AST Node Type: '" + nodeTypeObject.FullName + "'", ex);
682 			}
683 			return newNode;
684 		}
685 
686 		protected class FactoryEntry
687 		{
FactoryEntry(Type typeObj, ASTNodeCreator creator)688 			public FactoryEntry(Type typeObj, ASTNodeCreator creator)
689 			{
690 				NodeTypeObject	= typeObj;
691 				Creator			= creator;
692 			}
693 
FactoryEntry(Type typeObj)694 			public FactoryEntry(Type typeObj)
695 			{
696 				NodeTypeObject	= typeObj;
697 			}
698 
FactoryEntry(ASTNodeCreator creator)699 			public FactoryEntry(ASTNodeCreator creator)
700 			{
701 				Creator			= creator;
702 			}
703 
704 			public Type				NodeTypeObject;
705 			public ASTNodeCreator	Creator;
706 		}
707 	}
708 }