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> |
---|
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> |
---|
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> |
---|
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> |
---|
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)] |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
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> |
---|
559 | public virtual void error(string e) |
---|
560 | { |
---|
561 | Console.Error.WriteLine(e); |
---|
562 | } |
---|
563 | |
---|
564 | //--------------------------------------------------------------------- |
---|
565 | // PRIVATE FUNCTION MEMBERS |
---|
566 | //--------------------------------------------------------------------- |
---|
567 | |
---|
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 | |
---|
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 | |
---|
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 | |
---|
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 | |
---|
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 | { |
---|
688 | public FactoryEntry(Type typeObj, ASTNodeCreator creator) |
---|
689 | { |
---|
690 | NodeTypeObject = typeObj; |
---|
691 | Creator = creator; |
---|
692 | } |
---|
693 | |
---|
694 | public FactoryEntry(Type typeObj) |
---|
695 | { |
---|
696 | NodeTypeObject = typeObj; |
---|
697 | } |
---|
698 | |
---|
699 | public FactoryEntry(ASTNodeCreator creator) |
---|
700 | { |
---|
701 | Creator = creator; |
---|
702 | } |
---|
703 | |
---|
704 | public Type NodeTypeObject; |
---|
705 | public ASTNodeCreator Creator; |
---|
706 | } |
---|
707 | } |
---|
708 | } |
---|