View Javadoc

1   /***
2    *
3    * Copyright 2004 James Strachan
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   **/
18  package org.codehaus.groovy.antlr;
19  
20  import antlr.RecognitionException;
21  import antlr.TokenStreamException;
22  import antlr.TokenStreamRecognitionException;
23  import antlr.collections.AST;
24  import com.thoughtworks.xstream.XStream;
25  
26  import org.codehaus.groovy.GroovyBugError;
27  import org.codehaus.groovy.antlr.parser.GroovyLexer;
28  import org.codehaus.groovy.antlr.parser.GroovyRecognizer;
29  import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
30  import org.codehaus.groovy.antlr.treewalker.*;
31  import org.codehaus.groovy.ast.*;
32  import org.codehaus.groovy.ast.expr.*;
33  import org.codehaus.groovy.ast.stmt.*;
34  import org.codehaus.groovy.control.CompilationFailedException;
35  import org.codehaus.groovy.control.ParserPlugin;
36  import org.codehaus.groovy.control.SourceUnit;
37  import org.codehaus.groovy.syntax.*;
38  import org.objectweb.asm.Opcodes;
39  
40  import java.io.*;
41  import java.security.AccessController;
42  import java.security.PrivilegedAction;
43  import java.util.ArrayList;
44  import java.util.Iterator;
45  import java.util.List;
46  
47  /***
48   * A parser plugin which adapts the JSR Antlr Parser to the Groovy runtime
49   *
50   * @author <a href="mailto:jstrachan@protique.com">James Strachan</a>
51   * @version $Revision: 1.70 $
52   */
53  public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, GroovyTokenTypes {
54  
55      private AST ast;
56      private ClassNode classNode;
57      private String[] tokenNames;
58  
59  
60      public Reduction parseCST(final SourceUnit sourceUnit, Reader reader) throws CompilationFailedException {
61          ast = null;
62  
63          setController(sourceUnit);
64  
65          SourceBuffer sourceBuffer = new SourceBuffer();
66          UnicodeEscapingReader unicodeReader = new UnicodeEscapingReader(reader,sourceBuffer);
67          GroovyLexer lexer = new GroovyLexer(unicodeReader);
68          unicodeReader.setLexer(lexer);
69          GroovyRecognizer parser = GroovyRecognizer.make(lexer);
70          parser.setSourceBuffer(sourceBuffer);
71          tokenNames = parser.getTokenNames();
72          parser.setFilename(sourceUnit.getName());
73  
74          // start parsing at the compilationUnit rule
75          try {
76              parser.compilationUnit();
77          }
78          catch (TokenStreamRecognitionException tsre) {
79              RecognitionException e = tsre.recog;
80              SyntaxException se = new SyntaxException(e.getMessage(),e,e.getLine(),e.getColumn());
81              se.setFatal(true);
82              sourceUnit.addError(se);
83          }
84          catch (RecognitionException e) {
85              SyntaxException se = new SyntaxException(e.getMessage(),e,e.getLine(),e.getColumn());
86              se.setFatal(true);
87              sourceUnit.addError(se);
88          }
89          catch (TokenStreamException e) {
90              sourceUnit.addException(e);
91          }
92  
93          ast = parser.getAST();
94  
95          AntlrASTProcessor snippets = new AntlrASTProcessSnippets(sourceBuffer);
96          ast = snippets.process(ast);
97          
98          AccessController.doPrivileged(new PrivilegedAction() {
99              public Object run() {
100             	outputASTInVariousFormsIfNeeded(sourceUnit);
101                 return null;
102             }
103         });
104         
105         return null; //new Reduction(Tpken.EOF);
106     }
107 
108     public SourceSummary getSummary() {
109         SummaryCollector summaryCollector = new SummaryCollector();
110         AntlrASTProcessor treewalker = new PreOrderTraversal(summaryCollector);
111         treewalker.process(ast);
112         return summaryCollector.getSourceSummary();
113     }
114 
115     private void outputASTInVariousFormsIfNeeded(SourceUnit sourceUnit) {
116         // straight xstream output of AST
117         if ("xml".equals(System.getProperty("antlr.ast"))) {
118             saveAsXML(sourceUnit.getName(), ast);
119         }
120 
121         // 'pretty printer' output of AST
122         if ("groovy".equals(System.getProperty("antlr.ast"))) {
123             try {
124                 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".pretty.groovy"));
125                 Visitor visitor = new SourcePrinter(out,tokenNames);
126                 AntlrASTProcessor treewalker = new SourceCodeTraversal(visitor);
127                 treewalker.process(ast);
128             } catch (FileNotFoundException e) {
129                 System.out.println("Cannot create " + sourceUnit.getName() + ".pretty.groovy");
130             }
131         }
132 
133         // output AST in format suitable for opening in http://freemind.sourceforge.net
134         // which is a really nice way of seeing the AST, folding nodes etc
135         if ("mindmap".equals(System.getProperty("antlr.ast"))) {
136             try {
137                 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".mm"));
138                 Visitor visitor = new MindMapPrinter(out,tokenNames);
139                 AntlrASTProcessor treewalker = new PreOrderTraversal(visitor);
140                 treewalker.process(ast);
141             } catch (FileNotFoundException e) {
142                 System.out.println("Cannot create " + sourceUnit.getName() + ".mm");
143             }
144         }
145 
146         // html output of AST
147         if ("html".equals(System.getProperty("antlr.ast"))) {
148             try {
149                 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".html"));
150                 List v = new ArrayList();
151                 v.add(new NodeAsHTMLPrinter(out,tokenNames));
152                 v.add(new SourcePrinter(out,tokenNames));
153                 Visitor visitors = new CompositeVisitor(v);
154                 AntlrASTProcessor treewalker = new SourceCodeTraversal(visitors);
155                 treewalker.process(ast);
156             } catch (FileNotFoundException e) {
157                 System.out.println("Cannot create " + sourceUnit.getName() + ".html");
158             }
159         }
160 
161 
162     }
163 
164     private void saveAsXML(String name, AST ast) {
165         XStream xstream = new XStream();
166         try {
167             xstream.toXML(ast, new FileWriter(name + ".antlr.xml"));
168             System.out.println("Written AST to " + name + ".antlr.xml");
169         }
170         catch (Exception e) {
171             System.out.println("Couldn't write to " + name + ".antlr.xml");
172             e.printStackTrace();
173         }
174     }
175 
176     public ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException {
177         setClassLoader(classLoader);
178         makeModule();
179         try {
180             convertGroovy(ast);
181         }
182         catch (ASTRuntimeException e) {
183             throw new ASTParserException(e.getMessage() + ". File: " + sourceUnit.getName(), e);
184         }
185         return output;
186     }
187 
188     /***
189      * Converts the Antlr AST to the Groovy AST
190      */
191     protected void convertGroovy(AST node) {
192         while (node != null) {
193             int type = node.getType();
194             switch (type) {
195                 case PACKAGE_DEF:
196                     packageDef(node);
197                     break;
198 
199                 case IMPORT:
200                     importDef(node);
201                     break;
202 
203                 case CLASS_DEF:
204                     classDef(node);
205                     break;
206 
207                 case INTERFACE_DEF:
208                     interfaceDef(node);
209                     break;
210 
211                 case METHOD_DEF:
212                     methodDef(node);
213                     break;
214 
215                 default:
216                     {
217                         Statement statement = statement(node);
218                         output.addStatement(statement);
219                     }
220             }
221             node = node.getNextSibling();
222         }
223     }
224 
225     // Top level control structures
226     //-------------------------------------------------------------------------
227 
228     protectedong> void packageDef(AST packageDef) {
229         AST node = packageDef.getFirstChild();
230         if (isType(ANNOTATIONS, node)) {
231             node = node.getNextSibling();
232         }
233         String name = qualifiedName(node);
234         setPackageName(name);
235     }
236     
237     protected void importDef(AST importNode) {
238         // TODO handle static imports
239 
240         AST node = importNode.getFirstChild();
241 
242         String alias = null;
243         if (isType(LITERAL_as, node)) {
244             //import is like "import Foo as Bar"
245             node = node.getFirstChild();
246             AST aliasNode = node.getNextSibling();
247             alias = identifier(aliasNode);
248         }
249 
250         if (node.getNumberOfChildren()==0) {
251             // import is like  "import Foo"
252             String name = identifier(node);
253             ClassNode type = ClassHelper.make(name);
254             configureAST(type,importNode);
255             importClass(type,name,alias);
256             return;
257         }
258 
259         AST packageNode = node.getFirstChild();
260         String packageName = qualifiedName(packageNode);
261         AST nameNode = packageNode.getNextSibling();
262         if (isType(STAR, nameNode)) {
263             // import is like "import foo.*"
264             importPackageWithStar(packageName);
265             if (alias!=null) throw new GroovyBugError(
266                     "imports like 'import foo.* as Bar' are not "+
267                     "supported and should be catched by the grammar");
268         } else {
269             // import is like "import foo.Bar"
270             String name = identifier(nameNode);
271             ClassNode type = ClassHelper/make(packageName+/package-summary.html">ClassNode type = ClassHelper.make(packageName+"."+name);
272             configureAST(type,importNode);
273             importClass(type,name,alias);
274         }
275     }
276 
277     protected void interfaceDef(AST classDef) {
278         List annotations = new ArrayList();
279         AST node = classDef.getFirstChild();
280         int modifiers = Opcodes.ACC_PUBLIC;
281         if (isType(MODIFIERS, node)) {
282             modifiers = modifiers(node, annotations, modifiers);
283             node = node.getNextSibling();
284         }
285         modifiers |= Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE;
286 
287         String name = identifier(node);
288         node = node.getNextSibling();
289         ClassNode superClass = ClassHelper.OBJECT_TYPE;
290 
291         ClassNode[] interfaces = {};
292         if (isType(EXTENDS_CLAUSE, node)) {
293             interfaces = interfaces(node);
294             node = node.getNextSibling();
295         }
296 
297         addNewClassName(name);
298         classNode = new ClassNode(dot(getPackageName(), name), modifiers, superClass, interfaces, null);
299         classNode.addAnnotations(annotations);
300         configureAST(classNode, classDef);
301 
302         assertNodeType(OBJBLOCK, node);
303         objectBlock(node);
304         output.addClass(classNode);
305         classNode = null;
306     }
307 
308     protected void classDef(AST classDef) {
309         List annotations = new ArrayList();
310         AST node = classDef.getFirstChild();
311         int modifiers = Opcodes.ACC_PUBLIC;
312         if (isType(MODIFIERS, node)) {
313             modifiers = modifiers(node, annotations, modifiers);
314             node = node.getNextSibling();
315         }
316 
317         String name = identifier(node);
318         node = node.getNextSibling();
319 
320         ClassNode superClass = null;
321         if (isType(EXTENDS_CLAUSE, node)) {
322             superClass = makeType(node);
323             node = node.getNextSibling();
324         }
325 
326         ClassNode[] interfaces = {};
327         if (isType(IMPLEMENTS_CLAUSE, node)) {
328             interfaces = interfaces(node);
329             node = node.getNextSibling();
330         }
331 
332         // TODO read mixins
333         MixinNode[] mixins = {};
334 
335         addNewClassName(name);
336         classNode = new ClassNode(dot(getPackageName(), name), modifiers, superClass, interfaces, mixins);
337         classNode.addAnnotations(annotations);
338         configureAST(classNode, classDef);
339 
340         assertNodeType(OBJBLOCK, node);
341         objectBlock(node);
342         output.addClass(classNode);
343         classNode = null;
344     }
345 
346     protected void objectBlock(AST objectBlock) {
347         for (AST node = objectBlock.getFirstChild(); node != null; node = node.getNextSibling()) {
348             int type = node.getType();
349             switch (type) {
350                 case OBJBLOCK:
351                     objectBlock(node);
352                     break;
353 
354                 case METHOD_DEF:
355                     methodDef(node);
356                     break;
357 
358                 case CTOR_IDENT:
359                     constructorDef(node);
360                     break;
361 
362                 case VARIABLE_DEF:
363                     fieldDef(node);
364                     break;
365 
366                 case STATIC_INIT:
367                     staticInit(node);
368                     break;
369                     
370                 case INSTANCE_INIT:
371                     objectInit(node);
372                     break;
373                     
374                 default:
375                     unknownAST(node);
376             }
377         }
378     }
379     
380     protected void throwsList(AST node,List list) {
381     	String clazz = identifier(node);
382     	ClassNode exception = ClassHelper.make(clazz);
383     	list.add(exception);
384     	AST next = node.getNextSibling();
385     	if (next!=null) throwsList(next, list);
386     	next = node.getFirstChild();
387     	if (next!=null) throwsList(next, list);
388     }
389 
390     protected void methodDef(AST methodDef) {
391         List annotations = new ArrayList();
392         AST node = methodDef.getFirstChild();
393         int modifiers = Opcodes.ACC_PUBLIC;
394         if (isType(MODIFIERS, node)) {
395             modifiers = modifiers(node, annotations, modifiers);
396             node = node.getNextSibling();
397         }
398 
399         if (classNode!=null && (classNode.getModifiers() & Opcodes.ACC_INTERFACE) >0) {
400             modifiers |= Opcodes.ACC_ABSTRACT;
401         }
402 
403         ClassNode returnType = null;
404         if (isType(TYPE, node)) {
405             returnType = makeType(node);
406             node = node.getNextSibling();
407         }
408 
409         String name = identifier(node);
410         if (classNode != null) {
411             if (classNode.getNameWithoutPackage().equals(name)) {
412                 throw new ASTRuntimeException(methodDef, "Invalid constructor format. Try remove the 'def' expression?");
413             }
414         }
415         node = node.getNextSibling();
416 
417         assertNodeType(PARAMETERS, node);
418         Parameter[] parameters = parameters(node);
419         if (parameters==null) parameters = Parameter.EMPTY_ARRAY;
420         node = node.getNextSibling();
421         
422         ClassNode[] exceptions=new ClassNode[0];
423         if (isType(LITERAL_throws, node)) {
424         	AST throwsNode = node.getFirstChild();
425         	List exceptionList = new ArrayList();
426         	throwsList(throwsNode, exceptionList);
427         	exceptions = (ClassNode[]) exceptionList.toArray(exceptions);
428         	node = node.getNextSibling();
429         }
430 
431         Statement code = null;
432         if ((modifiers & Opcodes.ACC_ABSTRACT) == 0) {
433             if (node==null) {
434                 throw new ASTRuntimeException(methodDef, "You defined a method without body. Try adding a body, or declare it abstract.");
435             }
436             assertNodeType(SLIST, node);
437             code = statementList(node);
438         }
439 
440         MethodNode methodNode = new MethodNode(name, modifiers, returnType, parameters, exceptions, code);
441         methodNode.addAnnotations(annotations);
442         configureAST(methodNode, methodDef);
443         if (classNode != null) {
444             classNode.addMethod(methodNode);
445         }
446         else {
447             output.addMethod(methodNode);
448         }
449     }
450     
451     protected void staticInit(AST staticInit) {        
452         BlockStatement code = (BlockStatement) statementList(staticInit);
453         classNode.addStaticInitializerStatements(code.getStatements(),false);
454     }
455     
456     protected void objectInit(AST init) {        
457         BlockStatement code = (BlockStatement) statementList(init);
458         classNode.addObjectInitializerStatements(code);
459     }
460     
461     protected void constructorDef(AST constructorDef) {
462         List annotations = new ArrayList();
463         AST node = constructorDef.getFirstChild();
464         int modifiers = Opcodes.ACC_PUBLIC;
465         if (isType(MODIFIERS, node)) {
466             modifiers = modifiers(node, annotations, modifiers);
467             node = node.getNextSibling();
468         }
469 
470         assertNodeType(PARAMETERS, node);
471         Parameter[] parameters = parameters(node);
472         if (parameters == null) parameters = Parameter.EMPTY_ARRAY;
473         node = node.getNextSibling();
474 
475         ClassNode[] exceptions=new ClassNode[0];
476         if (isType(LITERAL_throws, node)) {
477         	AST throwsNode = node.getFirstChild();
478         	List exceptionList = new ArrayList();
479         	throwsList(throwsNode, exceptionList);
480         	exceptions = (ClassNode[]) exceptionList.toArray(exceptions);
481         	node = node.getNextSibling();
482         }
483         
484         assertNodeType(SLIST, node);
485         Statement code = statementList(node);
486 
487         ConstructorNode constructorNode = classNode.addConstructor(modifiers, parameters, exceptions, code);
488         constructorNode.addAnnotations(annotations);
489         configureAST(constructorNode, constructorDef);
490     }
491 
492     protected void fieldDef(AST fieldDef) {
493         List annotations = new ArrayList();
494         AST node = fieldDef.getFirstChild();
495 
496         int modifiers = 0;
497         if (isType(MODIFIERS, node)) {
498             modifiers = modifiers(node, annotations, modifiers);
499             node = node.getNextSibling();
500         }
501         
502         if (classNode.isInterface()) {
503         	modifiers |= Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
504         	if ( (modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) == 0) {
505         		modifiers |= Opcodes.ACC_PUBLIC;
506         	}
507         }
508 
509         ClassNode type = null;
510         if (isType(TYPE, node)) {
511             type = makeType(node);
512             node = node.getNextSibling();
513         }
514 
515         String name = identifier(node);
516         node = node.getNextSibling();
517 
518         Expression initialValue = null;
519         if (node != null) {
520             assertNodeType(ASSIGN, node);
521             initialValue = expression(node);
522         }
523 
524         if (initialValue == null && type != null) {
525             if (type==ClassHelper.int_TYPE) {
526                 initialValue = new ConstantExpression(new Integer(0));
527             }
528             else if (type==ClassHelper.long_TYPE) {
529                 initialValue = new ConstantExpression(new Long(0L));
530             }
531             else if (type==ClassHelper.double_TYPE) {
532                 initialValue = new ConstantExpression(new Double(0.0));
533             }
534             else if (type==ClassHelper.float_TYPE) {
535                 initialValue = new ConstantExpression(new Float(0.0F));
536             }
537             else if (type==ClassHelper.boolean_TYPE) {
538                 initialValue = ConstantExpression.FALSE;
539             }
540             else if (type==ClassHelper.short_TYPE) {
541                 initialValue = new ConstantExpression(new Short((short) 0));
542             }
543             else if (type==ClassHelper.byte_TYPE) {
544                 initialValue = new ConstantExpression(new Byte((byte) 0));
545             }
546             else if (type==ClassHelper.char_TYPE) {
547                 initialValue = new ConstantExpression(new Character((char) 0));
548             }
549         }
550 
551 
552         FieldNode fieldNode = new FieldNode(name, modifiers, type, classNode, initialValue);
553         fieldNode.addAnnotations(annotations);
554         configureAST(fieldNode, fieldDef);
555 
556         if (!hasVisibility(modifiers)) {
557             // lets set the modifiers on the field
558             int fieldModifiers = 0;
559             int flags = Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_VOLATILE | Opcodes.ACC_FINAL;
560 
561             if (!hasVisibility(modifiers)) {
562                 modifiers |= Opcodes.ACC_PUBLIC;
563                 fieldModifiers |= Opcodes.ACC_PRIVATE;
564             }
565 
566             // lets pass along any other modifiers we need
567             fieldModifiers |= (modifiers & flags);
568             fieldNode.setModifiers(fieldModifiers);
569             
570             PropertyNode propertyNode = new PropertyNode(fieldNode, modifiers, null, null);
571             configureAST(propertyNode, fieldDef);
572             classNode.addProperty(propertyNode);
573         }
574         else {
575             fieldNode.setModifiers(modifiers);
576             classNode.addField(fieldNode);
577         }
578     }
579 
580     protected ClassNode[] interfaces(AST node) {
581         List interfaceList = new ArrayList();
582         for (AST implementNode = node.getFirstChild(); implementNode != null; implementNode = implementNode.getNextSibling()) {
583         	interfaceList.add(ClassHelper.make(qualifiedName(implementNode)));
584         }
585         ClassNode[] interfaces = {};
586         if (!interfaceList.isEmpty()) {
587             interfaces = new ClassNode[interfaceList.size()];
588             interfaceList.toArray(interfaces);
589 
590         }
591         return interfaces;
592     }
593 
594     protected Parameter[] parameters(AST parametersNode) {
595         AST node = parametersNode.getFirstChild();
596         if (node == null) {
597         	if (isType(IMPLICIT_PARAMETERS, parametersNode)) return Parameter.EMPTY_ARRAY;
598             return null;
599         }
600         else {
601             List parameters = new ArrayList();
602             do {
603                 parameters.add(parameter(node));
604                 node = node.getNextSibling();
605             }
606             while (node != null);
607             Parameter[] answer = new Parameter[parameters.size()];
608             parameters.toArray(answer);
609             return answer;
610         }
611     }
612 
613     protected Parameter parameter(AST paramNode) {
614         List annotations = new ArrayList();
615         AST node = paramNode.getFirstChild();
616 
617         int modifiers = 0;
618         if (isType(MODIFIERS, node)) {
619             modifiers = modifiers(node, annotations, modifiers);
620             node = node.getNextSibling();
621         }
622 
623         ClassNode type = ClassHelper.DYNAMIC_TYPE;
624         if (isType(TYPE, node)) {
625             type = makeType(node);
626             node = node.getNextSibling();
627         }
628 
629         String name = identifier(node);
630         node = node.getNextSibling();
631         VariableExpression leftExpression = new VariableExpression(name, type);
632         configureAST(leftExpression, paramNode);
633 
634         Parameter parameter = null;
635         if (node != null) {
636             assertNodeType(ASSIGN, node);
637             Expression rightExpression = expression(node.getFirstChild());
638             parameter = new Parameter(type, name, rightExpression);
639         }
640         else
641             parameter = new Parameter(type, name);
642 
643         // TODO
644         //configureAST(parameter,paramNode);
645         //parameter.addAnnotations(annotations);
646         return parameter;
647     }
648 
649     protected int modifiers(AST modifierNode, List annotations, int defaultModifiers) {
650         assertNodeType(MODIFIERS, modifierNode);
651 
652         boolean access = false;
653         int answer = 0;
654 
655         for (AST node = modifierNode.getFirstChild(); node != null; node = node.getNextSibling()) {
656             int type = node.getType();
657             switch (type) {
658                 // annotations
659                 case ANNOTATION:
660                     annotations.add(annotation(node));
661                     break;
662 
663 
664                     // core access scope modifiers
665                 case LITERAL_private:
666                     answer = setModifierBit(node, answer, Opcodes.ACC_PRIVATE);
667                     access = setAccessTrue(node, access);
668                     break;
669 
670                 case LITERAL_protected:
671                     answer = setModifierBit(node, answer, Opcodes.ACC_PROTECTED);
672                     access = setAccessTrue(node, access);
673                     break;
674 
675                 case LITERAL_public:
676                     answer = setModifierBit(node, answer, Opcodes.ACC_PUBLIC);
677                     access = setAccessTrue(node, access);
678                     break;
679 
680                     // other modifiers
681                 case ABSTRACT:
682                     answer = setModifierBit(node, answer, Opcodes.ACC_ABSTRACT);
683                     break;
684 
685                 case FINAL:
686                     answer = setModifierBit(node, answer, Opcodes.ACC_FINAL);
687                     break;
688 
689                 case LITERAL_native:
690                     answer = setModifierBit(node, answer, Opcodes.ACC_NATIVE);
691                     break;
692 
693                 case LITERAL_static:
694                     answer = setModifierBit(node, answer, Opcodes.ACC_STATIC);
695                     break;
696 
697                 case STRICTFP:
698                     answer = setModifierBit(node, answer, Opcodes.ACC_STRICT);
699                     break;
700 
701                 case LITERAL_synchronized:
702                     answer = setModifierBit(node, answer, Opcodes.ACC_SYNCHRONIZED);
703                     break;
704 
705                 case LITERAL_transient:
706                     answer = setModifierBit(node, answer, Opcodes.ACC_TRANSIENT);
707                     break;
708 
709                 case LITERAL_volatile:
710                     answer = setModifierBit(node, answer, Opcodes.ACC_VOLATILE);
711                     break;
712 
713                 default:
714                     unknownAST(node);
715             }
716         }
717         if (!access) {
718             answer |= defaultModifiers;
719         }
720         return answer;
721     }
722 
723     protected boolean setAccessTrue(AST node, boolean access) {
724         if (!access) {
725             return true;
726         }
727         else {
728             throw new ASTRuntimeException(node, "Cannot specify modifier: " + node.getText() + " when access scope has already been defined");
729         }
730     }
731 
732     protected int setModifierBit(AST node, int answer, int bit) {
733         if ((answer & bit) != 0) {
734             throw new ASTRuntimeException(node, "Cannot repeat modifier: " + node.getText());
735         }
736         return answer | bit;
737     }
738 
739     protected AnnotationNode annotation(AST annotationNode) {
740         AST node = annotationNode.getFirstChild();
741         String name = identifier(node);
742         AnnotationNode annotatedNode = new AnnotationNode(ClassHelper.make(name));
743         configureAST(annotatedNode, node);
744         while (true) {
745             node = node.getNextSibling();
746             if (isType(ANNOTATION_MEMBER_VALUE_PAIR, node)) {
747                 AST memberNode = node.getFirstChild();
748                 String param = identifier(memberNode);
749                 Expression expression = expression(memberNode.getNextSibling());
750                 annotatedNode.addMember(param, expression);
751             }
752             else {
753                 break;
754             }
755         }
756         return annotatedNode;
757     }
758 
759 
760 
761     // Statements
762     //-------------------------------------------------------------------------
763 
764     protected Statement statement(AST node) {
765         Statement statement = null;
766         int type = node.getType();
767         switch (type) {
768             case SLIST:
769             case LITERAL_finally:
770                 statement = statementList(node);
771                 break;
772 
773             case METHOD_CALL:
774                 statement = methodCall(node);
775                 break;
776 
777             case VARIABLE_DEF:
778                 statement = variableDef(node);
779                 break;
780 
781 
782             case LABELED_STAT:
783                 statement = labelledStatement(node);
784                 break;
785 
786             case LITERAL_assert:
787                 statement = assertStatement(node);
788                 break;
789 
790             case LITERAL_break:
791                 statement = breakStatement(node);
792                 break;
793 
794             case LITERAL_continue:
795                 statement = continueStatement(node);
796                 break;
797 
798             case LITERAL_if:
799                 statement = ifStatement(node);
800                 break;
801 
802             case LITERAL_for:
803                 statement = forStatement(node);
804                 break;
805 
806             case LITERAL_return:
807                 statement = returnStatement(node);
808                 break;
809 
810             case LITERAL_synchronized:
811                 statement = synchronizedStatement(node);
812                 break;
813 
814             case LITERAL_switch:
815                 statement = switchStatement(node);
816                 break;
817 
818             case LITERAL_with:
819                 statement = withStatement(node);
820                 break;
821 
822             case LITERAL_try:
823                 statement = tryStatement(node);
824                 break;
825 
826             case LITERAL_throw:
827                 statement = throwStatement(node);
828                 break;
829 
830             case LITERAL_while:
831                 statement = whileStatement(node);
832                 break;
833 
834             default:
835                 statement = new ExpressionStatement(expression(node));
836         }
837         if (statement != null) {
838             configureAST(statement, node);
839         }
840         return statement;
841     }
842 
843     protected Statement statementList(AST code) {
844         return statementListNoChild(code.getFirstChild());
845     }
846 
847     protected Statement statementListNoChild(AST node) {
848         BlockStatement block = new BlockStatement();
849         // no need to configureAST(block,node); as node is probably null
850         for (; node != null; node = node.getNextSibling()) {
851             block.addStatement(statement(node));
852         }
853         return block;
854     }
855 
856     protected Statement assertStatement(AST assertNode) {
857         AST node = assertNode.getFirstChild();
858         BooleanExpression booleanExpression = booleanExpression(node);
859         Expression messageExpression = null;
860 
861         node = node.getNextSibling();
862         if (node != null) {
863             messageExpression = expression(node);
864         }
865         else {
866             messageExpression = ConstantExpression.NULL;
867         }
868         AssertStatement assertStatement = new AssertStatement(booleanExpression, messageExpression);
869         configureAST(assertStatement, assertNode);
870         return assertStatement;
871     }
872 
873     protected Statement breakStatement(AST node) {
874         BreakStatement breakStatement = new BreakStatement(label(node));
875         configureAST(breakStatement, node);
876         return breakStatement;
877     }
878 
879     protected Statement continueStatement(AST node) {
880         ContinueStatement continueStatement = new ContinueStatement(label(node));
881         configureAST(continueStatement, node);
882         return continueStatement;
883     }
884 
885     protected Statement forStatement(AST forNode) {
886         AST inNode = forNode.getFirstChild();
887         AST variableNode = inNode.getFirstChild();
888         AST collectionNode = variableNode.getNextSibling();
889 
890         ClassNode type = ClassHelper.OBJECT_TYPE;
891         if (isType(VARIABLE_DEF, variableNode)) {
892             AST typeNode = variableNode.getFirstChild();
893             assertNodeType(TYPE, typeNode);
894 
895             type = type(typeNode);
896             variableNode = typeNode.getNextSibling();
897         }
898         String variable = identifier(variableNode);
899 
900         Expression collectionExpression = expression(collectionNode);
901         Statement block = statement(inNode.getNextSibling());
902         Parameter forParameter = new Parameter(type,variable);
903 
904         ForStatement forStatement = new ForStatement(forParameter, collectionExpression, block);
905         configureAST(forStatement, forNode);
906         return forStatement;
907     }
908 
909     protected Statement ifStatement(AST ifNode) {
910         AST node = ifNode.getFirstChild();
911         assertNodeType(EXPR, node);
912         BooleanExpression booleanExpression = booleanExpression(node);
913 
914         node = node.getNextSibling();
915         Statement ifBlock = statement(node);
916 
917         Statement elseBlock = EmptyStatement.INSTANCE;
918         node = node.getNextSibling();
919         if (node != null) {
920             elseBlock = statement(node);
921         }
922         IfStatement ifStatement = new IfStatement(booleanExpression, ifBlock, elseBlock);
923         configureAST(ifStatement, ifNode);
924         return ifStatement;
925     }
926 
927     protected Statement labelledStatement(AST labelNode) {
928         AST node = labelNode.getFirstChild();
929         String label = identifier(node);
930         Statement statement = statement(node.getNextSibling());
931         statement.setStatementLabel(label);
932         return statement;
933     }
934 
935     protected Statement methodCall(AST code) {
936         Expression expression = methodCallExpression(code);
937         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
938         configureAST(expressionStatement, code);
939         return expressionStatement;
940     }
941 
942     protected Statement variableDef(AST variableDef) {
943         AST node = variableDef.getFirstChild();
944         ClassNode type = null;
945         if (isType(MODIFIERS, node)) {
946             node = node.getNextSibling();
947         }
948         if (isType(TYPE, node)) {
949             type = makeType(node);
950             node = node.getNextSibling();
951         }
952 
953         String name = identifier(node);
954         node = node.getNextSibling();
955 
956         VariableExpression leftExpression = new VariableExpression(name, type);
957         configureAST(leftExpression, variableDef);
958 
959         Expression rightExpression = ConstantExpression.NULL;
960         if (node != null) {
961             assertNodeType(ASSIGN, node);
962 
963             rightExpression = expression(node.getFirstChild());
964         }
965         Token token = makeToken(Types.ASSIGN, variableDef);
966 
967         // TODO should we have a variable declaration statement?
968         DeclarationExpression expression = new DeclarationExpression(leftExpression, token, rightExpression);
969         configureAST(expression, variableDef);
970         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
971         configureAST(expressionStatement, variableDef);
972         return expressionStatement;
973     }
974 
975     protected Statement returnStatement(AST node) {
976         AST exprNode = node.getFirstChild();
977 
978         // This will pick up incorrect sibling node if 'node' is a plain 'return'
979 		//
980 		//if (exprNode == null) {
981         //    exprNode = node.getNextSibling();
982         //}
983         if (exprNode != null) {
984             Expression expression = expression(exprNode);
985             if (expression instanceof ConstantExpression) {
986                 ConstantExpression constantExpr = (ConstantExpression) expression;
987                 if (constantExpr.getValue() == null) {
988                     return ReturnStatement.RETURN_NULL_OR_VOID;
989                 }
990             }
991             ReturnStatement returnStatement = new ReturnStatement(expression);
992             configureAST(returnStatement, node);
993             return returnStatement;
994         }
995         else {
996             return ReturnStatement.RETURN_NULL_OR_VOID;
997         }
998     }
999 
1000     protected Statement switchStatement(AST switchNode) {
1001         AST node = switchNode.getFirstChild();
1002         Expression expression = expression(node);
1003         Statement defaultStatement = EmptyStatement.INSTANCE;
1004 
1005         List list = new ArrayList();
1006         for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node.getNextSibling()) {
1007             AST child = node.getFirstChild();
1008             if (isType(LITERAL_case, child)) {
1009                 list.add(caseStatement(child));
1010             }
1011             else {
1012                 defaultStatement = statement(child.getNextSibling());
1013             }
1014         }
1015         if (node != null) {
1016             unknownAST(node);
1017         }
1018         SwitchStatement switchStatement = new SwitchStatement(expression, list, defaultStatement);
1019         configureAST(switchStatement, switchNode);
1020         return switchStatement;
1021     }
1022 
1023     protected CaseStatement caseStatement(AST node) {
1024         Expression expression = expression(node.getFirstChild());
1025         AST nextSibling = node.getNextSibling();
1026         Statement statement = EmptyStatement.INSTANCE;
1027         if (!isType(LITERAL_default, nextSibling)) {
1028              statement = statement(nextSibling);
1029         }
1030         CaseStatement answer = new CaseStatement(expression, statement);
1031         configureAST(answer, node);
1032         return answer;
1033     }
1034 
1035     protected Statement synchronizedStatement(AST syncNode) {
1036         AST node = syncNode.getFirstChild();
1037         Expression expression = expression(node);
1038         Statement code = statement(node.getNextSibling());
1039         SynchronizedStatement synchronizedStatement = new SynchronizedStatement(expression, code);
1040         configureAST(synchronizedStatement, syncNode);
1041         return synchronizedStatement;
1042     }
1043 
1044     protected Statement throwStatement(AST node) {
1045         AST expressionNode = node.getFirstChild();
1046         if (expressionNode == null) {
1047             expressionNode = node.getNextSibling();
1048         }
1049         if (expressionNode == null) {
1050             throw new ASTRuntimeException(node, "No expression available");
1051         }
1052         ThrowStatement throwStatement = new ThrowStatement(expression(expressionNode));
1053         configureAST(throwStatement, node);
1054         return throwStatement;
1055     }
1056 
1057     protected Statement tryStatement(AST tryStatementNode) {
1058         AST tryNode = tryStatementNode.getFirstChild();
1059         Statement tryStatement = statement(tryNode);
1060         Statement finallyStatement = EmptyStatement.INSTANCE;
1061         AST node = tryNode.getNextSibling();
1062 
1063         // lets do the catch nodes
1064         List catches = new ArrayList();
1065         for (; node != null && isType(LITERAL_catch, node); node = node.getNextSibling()) {
1066             catches.add(catchStatement(node));
1067         }
1068 
1069         if (isType(LITERAL_finally, node)) {
1070             finallyStatement = statement(node);
1071             node = node.getNextSibling();
1072         }
1073 
1074         TryCatchStatement tryCatchStatement = new TryCatchStatement(tryStatement, finallyStatement);
1075         configureAST(tryCatchStatement, tryStatementNode);
1076         for (Iterator iter = catches.iterator(); iter.hasNext();) {
1077             CatchStatement statement = (CatchStatement) iter.next();
1078             tryCatchStatement.addCatch(statement);
1079         }
1080         return tryCatchStatement;
1081     }
1082 
1083     protected CatchStatement catchStatement(AST catchNode) {
1084         AST node = catchNode.getFirstChild();
1085         Parameter parameter = parameter(node);
1086         ClassNode exceptionType = parameter.getType();
1087         String variable = parameter.getName();
1088         node = node.getNextSibling();
1089         Statement code = statement(node);
1090         Parameter catchParameter = new Parameter(exceptionType,variable);
1091         CatchStatement answer = new CatchStatement(catchParameter, code);
1092         configureAST(answer, catchNode);
1093         return answer;
1094     }
1095 
1096     protected Statement whileStatement(AST whileNode) {
1097         AST node = whileNode.getFirstChild();
1098         assertNodeType(EXPR, node);
1099         BooleanExpression booleanExpression = booleanExpression(node);
1100 
1101         node = node.getNextSibling();
1102         Statement block = statement(node);
1103         WhileStatement whileStatement = new WhileStatement(booleanExpression, block);
1104         configureAST(whileStatement, whileNode);
1105         return whileStatement;
1106     }
1107 
1108     protected Statement withStatement(AST node) {
1109         notImplementedYet(node);
1110         return null; /*** TODO */
1111     }
1112 
1113 
1114 
1115     // Expressions
1116     //-------------------------------------------------------------------------
1117 
1118     protected Expression expression(AST node) {
1119         Expression expression = expressionSwitch(node);
1120         configureAST(expression, node);
1121         return expression;
1122     }
1123 
1124     protected Expression expressionSwitch(AST node) {
1125         int type = node.getType();
1126         switch (type) {
1127             case EXPR:
1128                 return expression(node.getFirstChild());
1129 
1130             case ELIST:
1131                 return expressionList(node);
1132 
1133             case SLIST:
1134                 return blockExpression(node);
1135 
1136             case CLOSED_BLOCK:
1137                 return closureExpression(node);
1138 
1139             case SUPER_CTOR_CALL:
1140                 return specialConstructorCallExpression(node,ClassNode.SUPER);
1141 
1142             case METHOD_CALL:
1143                 return methodCallExpression(node);
1144 
1145             case LITERAL_new:
1146                 return constructorCallExpression(node.getFirstChild());
1147 
1148             case CTOR_CALL:
1149                 return specialConstructorCallExpression(node,ClassNode.THIS);
1150 
1151             case QUESTION:
1152                 return ternaryExpression(node);
1153 
1154             case OPTIONAL_DOT:
1155             case SPREAD_DOT:
1156             case DOT:
1157                 return dotExpression(node);
1158 
1159             case IDENT:
1160             case LITERAL_boolean:
1161             case LITERAL_byte:
1162             case LITERAL_char:
1163             case LITERAL_double:
1164             case LITERAL_float:
1165             case LITERAL_int:
1166             case LITERAL_long:
1167             case LITERAL_short:
1168             case LITERAL_void:
1169                 return variableExpression(node);
1170 
1171             case LIST_CONSTRUCTOR:
1172                 return listExpression(node);
1173 
1174             case MAP_CONSTRUCTOR:
1175                 return mapExpression(node);
1176 
1177             case LABELED_ARG:
1178                 return mapEntryExpression(node);
1179 
1180             case SPREAD_ARG:
1181                 return spreadExpression(node);
1182 
1183             case SPREAD_MAP_ARG:
1184                 return spreadMapExpression(node);
1185 
1186             // commented out of groovy.g due to non determinisms
1187             //case MEMBER_POINTER_DEFAULT:
1188             //    return defaultMethodPointerExpression(node);
1189 
1190             case MEMBER_POINTER:
1191                 return methodPointerExpression(node);
1192 
1193             case INDEX_OP:
1194                 return indexExpression(node);
1195 
1196             case LITERAL_instanceof:
1197                 return instanceofExpression(node);
1198 
1199             case LITERAL_as:
1200                 return asExpression(node);
1201 
1202             case TYPECAST:
1203                 return castExpression(node);
1204 
1205                 // literals
1206 
1207             case LITERAL_true:
1208                 return ConstantExpression.TRUE;
1209 
1210             case LITERAL_false:
1211                 return ConstantExpression.FALSE;
1212 
1213             case LITERAL_null:
1214                 return ConstantExpression.NULL;
1215 
1216             case STRING_LITERAL:
1217                 ConstantExpression constantExpression = new ConstantExpression(node.getText());
1218                 configureAST(constantExpression, node);
1219                 return constantExpression;
1220 
1221             case STRING_CONSTRUCTOR:
1222                 return gstring(node);
1223 
1224             case NUM_DOUBLE:
1225             case NUM_FLOAT:
1226             case NUM_BIG_DECIMAL:
1227                 return decimalExpression(node);
1228 
1229             case NUM_BIG_INT:
1230             case NUM_INT:
1231             case NUM_LONG:
1232                 return integerExpression(node);
1233 
1234             case LITERAL_this:
1235                 return VariableExpression.THIS_EXPRESSION;
1236 
1237             case LITERAL_super:
1238                 return VariableExpression.SUPER_EXPRESSION;
1239 
1240 
1241                 // Unary expressions
1242             case LNOT:
1243                 NotExpression notExpression = new NotExpression(expression(node.getFirstChild()));
1244                 configureAST(notExpression, node);
1245                 return notExpression;
1246 
1247             case UNARY_MINUS:
1248                 return negateExpression(node);
1249 
1250             case BNOT:
1251                 BitwiseNegExpression bitwiseNegExpression = new BitwiseNegExpression(expression(node.getFirstChild()));
1252                 configureAST(bitwiseNegExpression, node);
1253                 return bitwiseNegExpression;
1254 
1255             case UNARY_PLUS:
1256                 return expression(node.getFirstChild());
1257 
1258 
1259                 // Prefix expressions
1260             case INC:
1261                 return prefixExpression(node, Types.PLUS_PLUS);
1262 
1263             case DEC:
1264                 return prefixExpression(node, Types.MINUS_MINUS);
1265 
1266                 // Postfix expressions
1267             case POST_INC:
1268                 return postfixExpression(node, Types.PLUS_PLUS);
1269 
1270             case POST_DEC:
1271                 return postfixExpression(node, Types.MINUS_MINUS);
1272 
1273 
1274                 // Binary expressions
1275 
1276             case ASSIGN:
1277                 return binaryExpression(Types.ASSIGN, node);
1278 
1279             case EQUAL:
1280                 return binaryExpression(Types.COMPARE_EQUAL, node);
1281 
1282             case NOT_EQUAL:
1283                 return binaryExpression(Types.COMPARE_NOT_EQUAL, node);
1284 
1285             case COMPARE_TO:
1286                 return binaryExpression(Types.COMPARE_TO, node);
1287 
1288             case LE:
1289                 return binaryExpression(Types.COMPARE_LESS_THAN_EQUAL, node);
1290 
1291             case LT:
1292                 return binaryExpression(Types.COMPARE_LESS_THAN, node);
1293 
1294             case GT:
1295                 return binaryExpression(Types.COMPARE_GREATER_THAN, node);
1296 
1297             case GE:
1298                 return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL, node);
1299 
1300                 /***
1301                  * TODO treble equal?
1302                  return binaryExpression(Types.COMPARE_IDENTICAL, node);
1303 
1304                  case ???:
1305                  return binaryExpression(Types.LOGICAL_AND_EQUAL, node);
1306 
1307                  case ???:
1308                  return binaryExpression(Types.LOGICAL_OR_EQUAL, node);
1309 
1310                  */
1311 
1312             case LAND:
1313                 return binaryExpression(Types.LOGICAL_AND, node);
1314 
1315             case LOR:
1316                 return binaryExpression(Types.LOGICAL_OR, node);
1317 
1318             case BAND:
1319                 return binaryExpression(Types.BITWISE_AND, node);
1320 
1321             case BAND_ASSIGN:
1322                 return binaryExpression(Types.BITWISE_AND_EQUAL, node);
1323 
1324             case BOR:
1325                 return binaryExpression(Types.BITWISE_OR, node);
1326 
1327             case BOR_ASSIGN:
1328                 return binaryExpression(Types.BITWISE_OR_EQUAL, node);
1329 
1330             case BXOR:
1331                 return binaryExpression(Types.BITWISE_XOR, node);
1332 
1333             case BXOR_ASSIGN:
1334                 return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
1335 
1336 
1337             case PLUS:
1338                 return binaryExpression(Types.PLUS, node);
1339 
1340             case PLUS_ASSIGN:
1341                 return binaryExpression(Types.PLUS_EQUAL, node);
1342 
1343 
1344             case MINUS:
1345                 return binaryExpression(Types.MINUS, node);
1346 
1347             case MINUS_ASSIGN:
1348                 return binaryExpression(Types.MINUS_EQUAL, node);
1349 
1350 
1351             case STAR:
1352                 return binaryExpression(Types.MULTIPLY, node);
1353 
1354             case STAR_ASSIGN:
1355                 return binaryExpression(Types.MULTIPLY_EQUAL, node);
1356 
1357 
1358             case STAR_STAR:
1359                 return binaryExpression(Types.POWER, node);
1360 
1361             case STAR_STAR_ASSIGN:
1362                 return binaryExpression(Types.POWER_EQUAL, node);
1363 
1364 
1365             case DIV:
1366                 return binaryExpression(Types.DIVIDE, node);
1367 
1368             case DIV_ASSIGN:
1369                 return binaryExpression(Types.DIVIDE_EQUAL, node);
1370 
1371 
1372             case MOD:
1373                 return binaryExpression(Types.MOD, node);
1374 
1375             case MOD_ASSIGN:
1376                 return binaryExpression(Types.MOD_EQUAL, node);
1377 
1378             case SL:
1379                 return binaryExpression(Types.LEFT_SHIFT, node);
1380 
1381             case SL_ASSIGN:
1382                 return binaryExpression(Types.LEFT_SHIFT_EQUAL, node);
1383 
1384             case SR:
1385                 return binaryExpression(Types.RIGHT_SHIFT, node);
1386 
1387             case SR_ASSIGN:
1388                 return binaryExpression(Types.RIGHT_SHIFT_EQUAL, node);
1389 
1390             case BSR:
1391                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED, node);
1392 
1393             case BSR_ASSIGN:
1394                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED_EQUAL, node);
1395 
1396                 // Regex
1397             case REGEX_FIND:
1398                 return binaryExpression(Types.FIND_REGEX, node);
1399 
1400             case REGEX_MATCH:
1401                 return binaryExpression(Types.MATCH_REGEX, node);
1402 
1403 
1404                 // Ranges
1405             case RANGE_INCLUSIVE:
1406                 return rangeExpression(node, true);
1407 
1408             case RANGE_EXCLUSIVE:
1409                 return rangeExpression(node, false);
1410 
1411             default:
1412                 unknownAST(node);
1413         }
1414         return null;
1415     }
1416 
1417     protected Expression ternaryExpression(AST ternaryNode) {
1418         AST node = ternaryNode.getFirstChild();
1419         BooleanExpression booleanExpression = booleanExpression(node);
1420         node = node.getNextSibling();
1421         Expression left = expression(node);
1422         Expression right = expression(node.getNextSibling());
1423         TernaryExpression ternaryExpression = new TernaryExpression(booleanExpression, left, right);
1424         configureAST(ternaryExpression, ternaryNode);
1425         return ternaryExpression;
1426     }
1427 
1428     protected Expression variableExpression(AST node) {
1429         String text = node.getText();
1430 
1431         // TODO we might wanna only try to resolve the name if we are
1432         // on the left hand side of an expression or before a dot?
1433         VariableExpression variableExpression = new VariableExpression(text);
1434         configureAST(variableExpression, node);
1435         return variableExpression;
1436     }
1437 
1438     protected Expression rangeExpression(AST rangeNode, boolean inclusive) {
1439         AST node = rangeNode.getFirstChild();
1440         Expression left = expression(node);
1441         Expression right = expression(node.getNextSibling());
1442         RangeExpression rangeExpression = new RangeExpression(left, right, inclusive);
1443         configureAST(rangeExpression, rangeNode);
1444         return rangeExpression;
1445     }
1446 
1447     protected Expression spreadExpression(AST node) {
1448         AST exprNode = node.getFirstChild();
1449         AST listNode = exprNode.getFirstChild();
1450         Expression right = expression(listNode);
1451         SpreadExpression spreadExpression = new SpreadExpression(right);
1452         configureAST(spreadExpression, node);
1453         return spreadExpression;
1454     }
1455 
1456     protected Expression spreadMapExpression(AST node) {
1457         AST exprNode = node.getFirstChild();
1458         Expression expr = expression(exprNode);
1459         SpreadMapExpression spreadMapExpression = new SpreadMapExpression(expr);
1460         configureAST(spreadMapExpression, node);
1461         return spreadMapExpression;
1462     }
1463 
1464     protected Expression methodPointerExpression(AST node) {
1465         AST exprNode = node.getFirstChild();
1466         String methodName = identifier(exprNode.getNextSibling());
1467         Expression expression = expression(exprNode);
1468         MethodPointerExpression methodPointerExpression = new MethodPointerExpression(expression, methodName);
1469         configureAST(methodPointerExpression, node);
1470         return methodPointerExpression;
1471     }
1472 
1473 /*  commented out due to groovy.g non-determinisms
1474   protected Expression defaultMethodPointerExpression(AST node) {
1475         AST exprNode = node.getFirstChild();
1476         String methodName = exprNode.toString();
1477         MethodPointerExpression methodPointerExpression = new MethodPointerExpression(null, methodName);
1478         configureAST(methodPointerExpression, node);
1479         return methodPointerExpression;
1480     }
1481 */
1482 
1483     protected Expression listExpression(AST listNode) {
1484         List expressions = new ArrayList();
1485         AST elist = listNode.getFirstChild();
1486         assertNodeType(ELIST, elist);
1487 
1488         for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1489             // check for stray labeled arguments:
1490             switch (node.getType()) {
1491             case LABELED_ARG:       assertNodeType(COMMA, node);       break;  // helpful error?
1492             case SPREAD_MAP_ARG:    assertNodeType(SPREAD_ARG, node);  break;  // helpful error
1493             }
1494             expressions.add(expression(node));
1495         }
1496         ListExpression listExpression = new ListExpression(expressions);
1497         configureAST(listExpression, listNode);
1498         return listExpression;
1499     }
1500 
1501     /***
1502      * Typically only used for map constructors I think?
1503      */
1504     protected Expression mapExpression(AST mapNode) {
1505         List expressions = new ArrayList();
1506         AST elist = mapNode.getFirstChild();
1507         if (elist != null) {  // totally empty in the case of [:]
1508             assertNodeType(ELIST, elist);
1509             for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1510                 switch (node.getType()) {
1511                 case LABELED_ARG:
1512                 case SPREAD_MAP_ARG:
1513                     break;  // legal cases
1514                 case SPREAD_ARG:
1515                     assertNodeType(SPREAD_MAP_ARG, node);  break;  // helpful error
1516                 default:
1517                     assertNodeType(LABELED_ARG, node);  break;  // helpful error
1518                 }
1519                 expressions.add(mapEntryExpression(node));
1520             }
1521         }
1522         MapExpression mapExpression = new MapExpression(expressions);
1523         configureAST(mapExpression, mapNode);
1524         return mapExpression;
1525     }
1526 
1527     protected MapEntryExpression mapEntryExpression(AST node) {
1528         if (node.getType() == SPREAD_MAP_ARG) {
1529             AST rightNode = node.getFirstChild();
1530             Expression keyExpression = spreadMapExpression(node);
1531             Expression rightExpression = expression(rightNode);
1532             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
1533             configureAST(mapEntryExpression, node);
1534             return mapEntryExpression;
1535         }
1536         else {
1537             AST keyNode = node.getFirstChild();
1538             Expression keyExpression = expression(keyNode);
1539             AST valueNode = keyNode.getNextSibling();
1540             Expression valueExpression = expression(valueNode);
1541             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, valueExpression);
1542             configureAST(mapEntryExpression, node);
1543             return mapEntryExpression;
1544         }
1545     }
1546 
1547 
1548     protected Expression instanceofExpression(AST node) {
1549         AST leftNode = node.getFirstChild();
1550         Expression leftExpression = expression(leftNode);
1551 
1552         AST rightNode = leftNode.getNextSibling();
1553         ClassNode type = buildName(rightNode);
1554         assertTypeNotNull(type, rightNode);
1555 
1556         Expression rightExpression = new ClassExpression(type);
1557         configureAST(rightExpression, rightNode);
1558         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.KEYWORD_INSTANCEOF, node), rightExpression);
1559         configureAST(binaryExpression, node);
1560         return binaryExpression;
1561     }
1562 
1563     protected void assertTypeNotNull(ClassNode type, AST rightNode) {
1564         if (type == null) {
1565             throw new ASTRuntimeException(rightNode, "No type available for: " + qualifiedName(rightNode));
1566         }
1567     }
1568 
1569     protected Expression asExpression(AST node) {
1570         AST leftNode = node.getFirstChild();
1571         Expression leftExpression = expression(leftNode);
1572 
1573         AST rightNode = leftNode.getNextSibling();
1574         ClassNode type = buildName(rightNode);
1575 
1576         return CastExpression.asExpression(type, leftExpression);
1577     }
1578 
1579     protected Expression castExpression(AST castNode) {
1580         AST node = castNode.getFirstChild();
1581         ClassNode type = buildName(node);
1582         assertTypeNotNull(type, node);
1583 
1584         AST expressionNode = node.getNextSibling();
1585         Expression expression = expression(expressionNode);
1586 
1587         CastExpression castExpression = new CastExpression(type, expression);
1588         configureAST(castExpression, castNode);
1589         return castExpression;
1590     }
1591 
1592 
1593     protected Expression indexExpression(AST indexNode) {
1594         AST leftNode = indexNode.getFirstChild();
1595         Expression leftExpression = expression(leftNode);
1596 
1597         AST rightNode = leftNode.getNextSibling();
1598         Expression rightExpression = expression(rightNode);
1599 
1600         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.LEFT_SQUARE_BRACKET, indexNode), rightExpression);
1601         configureAST(binaryExpression, indexNode);
1602         return binaryExpression;
1603     }
1604 
1605     protected Expression binaryExpression(int type, AST node) {
1606         Token token = makeToken(type, node);
1607 
1608         AST leftNode = node.getFirstChild();
1609         Expression leftExpression = expression(leftNode);
1610 
1611         AST rightNode = leftNode.getNextSibling();
1612         if (rightNode == null) {
1613             return leftExpression;
1614         }
1615 
1616         if (Types.ofType(type, Types.ASSIGNMENT_OPERATOR)) {
1617             if (leftExpression instanceof VariableExpression || leftExpression instanceof PropertyExpression
1618                                                              || leftExpression instanceof FieldExpression
1619                                                              || leftExpression instanceof AttributeExpression
1620                                                              || leftExpression instanceof DeclarationExpression) {
1621                 // Do nothing.
1622             }
1623             else if (leftExpression instanceof ConstantExpression) {
1624                 throw new ASTRuntimeException(node, "\n[" + ((ConstantExpression) leftExpression).getValue() + "] is a constant expression, but it should be a variable expression");
1625             }
1626             else if (leftExpression instanceof BinaryExpression) {
1627                 Expression leftexp = ((BinaryExpression) leftExpression).getLeftExpression();
1628                 int lefttype = ((BinaryExpression) leftExpression).getOperation().getType();
1629                 if (!Types.ofType(lefttype, Types.ASSIGNMENT_OPERATOR) && lefttype != Types.LEFT_SQUARE_BRACKET) {
1630                     throw new ASTRuntimeException(node, "\n" + ((BinaryExpression) leftExpression).getText() + " is a binary expression, but it should be a variable expression");
1631                 }
1632             }
1633             else if (leftExpression instanceof GStringExpression) {
1634                 throw new ASTRuntimeException(node, "\n\"" + ((GStringExpression) leftExpression).getText() + "\" is a GString expression, but it should be a variable expression");
1635             }
1636             else if (leftExpression instanceof MethodCallExpression) {
1637                 throw new ASTRuntimeException(node, "\n\"" + ((MethodCallExpression) leftExpression).getText() + "\" is a method call expression, but it should be a variable expression");
1638             }
1639             else if (leftExpression instanceof MapExpression) {
1640                 throw new ASTRuntimeException(node, "\n'" + ((MapExpression) leftExpression).getText() + "' is a map expression, but it should be a variable expression");
1641             }
1642             else {
1643                 throw new ASTRuntimeException(node, "\n" + leftExpression.getClass() + ", with its value '" + leftExpression.getText() + "', is a bad expression as the LSH of an assignment operator");
1644             }
1645         }
1646         /*if (rightNode == null) {
1647             throw new NullPointerException("No rightNode associated with binary expression");
1648         }*/
1649         Expression rightExpression = expression(rightNode);
1650         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, token, rightExpression);
1651         configureAST(binaryExpression, node);
1652         return binaryExpression;
1653     }
1654 
1655     protected Expression prefixExpression(AST node, int token) {
1656         Expression expression = expression(node.getFirstChild());
1657         PrefixExpression prefixExpression = new PrefixExpression(makeToken(token, node), expression);
1658         configureAST(prefixExpression, node);
1659         return prefixExpression;
1660     }
1661 
1662     protected Expression postfixExpression(AST node, int token) {
1663         Expression expression = expression(node.getFirstChild());
1664         PostfixExpression postfixExpression = new PostfixExpression(expression, makeToken(token, node));
1665         configureAST(postfixExpression, node);
1666         return postfixExpression;
1667     }
1668 
1669     protected BooleanExpression booleanExpression(AST node) {
1670         BooleanExpression booleanExpression = new BooleanExpression(expression(node));
1671         configureAST(booleanExpression, node);
1672         return booleanExpression;
1673     }
1674 
1675     protected Expression dotExpression(AST node) {
1676         // lets decide if this is a propery invocation or a method call
1677         AST leftNode = node.getFirstChild();
1678         if (leftNode != null) {
1679             AST identifierNode = leftNode.getNextSibling();
1680             if (identifierNode != null) {
1681                 Expression leftExpression = expression(leftNode);
1682                 if (isType(SELECT_SLOT, identifierNode)) {
1683                     String field = identifier(identifierNode.getFirstChild());
1684                     AttributeExpression attributeExpression = new AttributeExpression(leftExpression, field, node.getType() != DOT);
1685                     if (node.getType() == SPREAD_DOT) {
1686                         attributeExpression.setSpreadSafe(true);
1687                     }
1688                     configureAST(attributeExpression, node);
1689                     return attributeExpression;
1690                 }
1691                 String property = identifier(identifierNode);
1692                 PropertyExpression propertyExpression = new PropertyExpression(leftExpression, property, node.getType() != DOT);
1693                 if (node.getType() == SPREAD_DOT) {
1694                     propertyExpression.setSpreadSafe(true);
1695                 } 
1696                 configureAST(propertyExpression, node);
1697                 return propertyExpression;
1698             }
1699         }
1700         return methodCallExpression(node);
1701     }
1702     
1703     protected Expression specialConstructorCallExpression(AST methodCallNode, ClassNode special) {
1704         AST node = methodCallNode.getFirstChild();
1705         Expression arguments = arguments(node);
1706         
1707         ConstructorCallExpression expression = new ConstructorCallExpression(special, arguments);
1708         configureAST(expression, methodCallNode);
1709         return expression;
1710     }
1711 
1712 
1713     protected Expression methodCallExpression(AST methodCallNode) {
1714         AST node = methodCallNode.getFirstChild();
1715         /* // Bad idea, since foo(1)(2) is valid Groovy for foo(1).call(2).
1716         if (isType(METHOD_CALL, node)) {
1717             // sometimes method calls get wrapped in method calls for some wierd reason
1718             return methodCallExpression(node);
1719         }
1720         */
1721 
1722         Expression objectExpression;
1723         AST selector;
1724         AST elist = node.getNextSibling();
1725         boolean safe = isType(OPTIONAL_DOT, node);
1726         boolean spreadSafe = isType(SPREAD_DOT, node);
1727         if (isType(DOT, node) || safe || spreadSafe) {
1728             AST objectNode = node.getFirstChild();
1729             objectExpression = expression(objectNode);
1730             selector = objectNode.getNextSibling();
1731         } else if (isType(IDENT, node)) {
1732             objectExpression = VariableExpression.THIS_EXPRESSION;
1733             selector = node;
1734         } else {
1735             objectExpression = expression(node);
1736             selector = null;  // implicit "call"
1737         }
1738 
1739         String name = null;
1740         if (selector == null) {
1741             name = "call";
1742         }  else if (isType(LITERAL_super, selector)) {
1743             name = "super";
1744             if (objectExpression == VariableExpression.THIS_EXPRESSION) {
1745                 objectExpression = VariableExpression.SUPER_EXPRESSION;
1746             }
1747         }
1748         else if (isPrimitiveTypeLiteral(selector)) {
1749             throw new ASTRuntimeException(selector, "Primitive type literal: " + selector.getText()
1750                     + " cannot be used as a method name");
1751         }
1752         else if (isType(SELECT_SLOT, selector)) {
1753             String field = identifier(selector.getFirstChild());
1754             AttributeExpression attributeExpression = new AttributeExpression(objectExpression, field, node.getType() != DOT);
1755             configureAST(attributeExpression, node);
1756             Expression arguments = arguments(elist);
1757             MethodCallExpression expression = new MethodCallExpression(attributeExpression, "call", arguments);
1758             configureAST(expression, methodCallNode);
1759             return expression;
1760         }
1761         else {
1762             name = identifier(selector);
1763         }
1764 
1765         Expression arguments = arguments(elist);
1766         MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
1767         boolean implicitThis = (objectExpression == VariableExpression.THIS_EXPRESSION);
1768         implicitThis = implicitThis || (objectExpression == VariableExpression.SUPER_EXPRESSION);
1769         expression.setSafe(safe);
1770         expression.setSpreadSafe(spreadSafe);
1771         expression.setImplicitThis(implicitThis);
1772         configureAST(expression, methodCallNode);
1773         return expression;
1774     }
1775     
1776     protected Expression constructorCallExpression(AST node) {
1777         AST constructorCallNode = node;
1778         ClassNode type = buildName(constructorCallNode);
1779 
1780         if (isType(CTOR_CALL, node) || isType(LITERAL_new, node)) {
1781             node = node.getFirstChild();
1782         }
1783 
1784         AST elist = node.getNextSibling();
1785 
1786         if (elist == null && isType(ELIST, node)) {
1787             elist = node;
1788             if ("(".equals(type.getName())) {
1789                 type = classNode;
1790             }
1791         }
1792 
1793         if (isType(ARRAY_DECLARATOR, elist)) {
1794             AST expressionNode = elist.getFirstChild();
1795             if (expressionNode == null) {
1796                 throw new ASTRuntimeException(elist, "No expression for the array constructor call");
1797             }
1798             List size = arraySizeExpression(expressionNode);
1799             ArrayExpression arrayExpression = new ArrayExpression(type, null, size);
1800             configureAST(arrayExpression, constructorCallNode);
1801             return arrayExpression;
1802         }
1803         Expression arguments = arguments(elist);
1804         ConstructorCallExpression expression = new ConstructorCallExpression(type, arguments);
1805         configureAST(expression, constructorCallNode);
1806         return expression;
1807     }
1808     
1809     protected List arraySizeExpression(AST node) {
1810         List list;
1811         Expression size = null;
1812     	if (isType(ARRAY_DECLARATOR,node)) {
1813     		AST right = node.getNextSibling();
1814         	if (right!=null) {
1815         		size = expression(right);
1816         	} else {
1817         		size = ConstantExpression.EMTPY_EXPRESSION;
1818         	}
1819         	list = arraySizeExpression(node.getFirstChild());
1820         } else {
1821         	size = expression(node);
1822         	list = new ArrayList();
1823         }
1824     	list.add(size);
1825     	return list;
1826     }
1827 
1828     protected Expression arguments(AST elist) {
1829         List expressionList = new ArrayList();
1830         // FIXME: all labeled arguments should follow any unlabeled arguments
1831         boolean namedArguments = false;
1832         for (AST node = elist; node != null; node = node.getNextSibling()) {
1833             if (isType(ELIST, node)) {
1834                 for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1835                     namedArguments |= addArgumentExpression(child, expressionList);
1836                 }
1837             }
1838             else {
1839                 namedArguments |= addArgumentExpression(node, expressionList);
1840             }
1841         }
1842         if (namedArguments) {
1843             if (!expressionList.isEmpty()) {
1844                 // lets remove any non-MapEntryExpression instances
1845                 // such as if the last expression is a ClosureExpression
1846                 // so lets wrap the named method calls in a Map expression
1847                 List argumentList = new ArrayList();
1848                 for (Iterator iter = expressionList.iterator(); iter.hasNext();) {
1849                     Expression expression = (Expression) iter.next();
1850                     if (!(expression instanceof MapEntryExpression)) {
1851                         argumentList.add(expression);
1852                     }
1853                 }
1854                 if (!argumentList.isEmpty()) {
1855                     expressionList.removeAll(argumentList);
1856                     MapExpression mapExpression = new MapExpression(expressionList);
1857                     configureAST(mapExpression, elist);
1858                     argumentList.add(0, mapExpression);
1859                     ArgumentListExpression argumentListExpression = new ArgumentListExpression(argumentList);
1860                     configureAST(argumentListExpression, elist);
1861                     return argumentListExpression;
1862                 }
1863             }
1864             NamedArgumentListExpression namedArgumentListExpression = new NamedArgumentListExpression(expressionList);
1865             configureAST(namedArgumentListExpression, elist);
1866             return namedArgumentListExpression;
1867         }
1868         else {
1869             ArgumentListExpression argumentListExpression = new ArgumentListExpression(expressionList);
1870             configureAST(argumentListExpression, elist);
1871             return argumentListExpression;
1872         }
1873     }
1874 
1875     protected boolean addArgumentExpression(AST node, List expressionList) {
1876         if (node.getType() == SPREAD_MAP_ARG) {
1877             AST rightNode = node.getFirstChild();
1878             Expression keyExpression = spreadMapExpression(node);
1879             Expression rightExpression = expression(rightNode);
1880             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
1881             expressionList.add(mapEntryExpression);
1882             return true;
1883         }
1884         else {
1885             Expression expression = expression(node);
1886             expressionList.add(expression);
1887             return expression instanceof MapEntryExpression;
1888         }
1889     }
1890 
1891     protected Expression expressionList(AST node) {
1892         List expressionList = new ArrayList();
1893         for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1894             expressionList.add(expression(child));
1895         }
1896         if (expressionList.size() == 1) {
1897             return (Expression) expressionList.get(0);
1898         }
1899         else {
1900             ListExpression listExpression = new ListExpression(expressionList);
1901             configureAST(listExpression, node);
1902             return listExpression;
1903         }
1904     }
1905 
1906     protected ClosureExpression closureExpression(AST node) {
1907         AST paramNode = node.getFirstChild();
1908         Parameter[] parameters = null;
1909         AST codeNode = paramNode;
1910         if (isType(PARAMETERS, paramNode) || isType(IMPLICIT_PARAMETERS, paramNode)) {
1911             parameters = parameters(paramNode);
1912             codeNode = paramNode.getNextSibling();
1913         }
1914         Statement code = statementListNoChild(codeNode);
1915         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
1916         configureAST(closureExpression, node);
1917         return closureExpression;
1918     }
1919 
1920     protected Expression blockExpression(AST node) {
1921         AST codeNode = node.getFirstChild();
1922         if (codeNode == null)  return ConstantExpression.NULL;
1923         if (codeNode.getType() == EXPR && codeNode.getNextSibling() == null) {
1924             // Simplify common case of {expr} to expr.
1925             return expression(codeNode);
1926         }
1927         Parameter[] parameters = Parameter.EMPTY_ARRAY;
1928         Statement code = statementListNoChild(codeNode);
1929         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
1930         configureAST(closureExpression, node);
1931         // Call it immediately.
1932         String callName = "call";
1933         Expression noArguments = new ArgumentListExpression();
1934         MethodCallExpression call = new MethodCallExpression(closureExpression, callName, noArguments);
1935         configureAST(call, node);
1936         return call;
1937     }
1938 
1939     protected Expression negateExpression(AST negateExpr) {
1940         AST node = negateExpr.getFirstChild();
1941 
1942         // if we are a number literal then lets just parse it
1943         // as the negation operator on MIN_INT causes rounding to a long
1944         String text = node.getText();
1945         switch (node.getType()) {
1946             case NUM_DOUBLE:
1947             case NUM_FLOAT:
1948             case NUM_BIG_DECIMAL:
1949                 ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal("-" + text));
1950                 configureAST(constantExpression, negateExpr);
1951                 return constantExpression;
1952 
1953             case NUM_BIG_INT:
1954             case NUM_INT:
1955             case NUM_LONG:
1956                 ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger("-" + text));
1957                 configureAST(constantLongExpression, negateExpr);
1958                 return constantLongExpression;
1959 
1960             default:
1961                 NegationExpression negationExpression = new NegationExpression(expression(node));
1962                 configureAST(negationExpression, negateExpr);
1963                 return negationExpression;
1964         }
1965     }
1966 
1967     protected ConstantExpression decimalExpression(AST node) {
1968         String text = node.getText();
1969         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal(text));
1970         configureAST(constantExpression, node);
1971         return constantExpression;
1972     }
1973 
1974     protected ConstantExpression integerExpression(AST node) {
1975         String text = node.getText();
1976         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseInteger(text));
1977         configureAST(constantExpression, node);
1978         return constantExpression;
1979     }
1980 
1981     protected Expression gstring(AST gstringNode) {
1982         List strings = new ArrayList();
1983         List values = new ArrayList();
1984 
1985         StringBuffer buffer = new StringBuffer();
1986 
1987         boolean isPrevString = false;
1988 
1989         for (AST node = gstringNode.getFirstChild(); node != null; node = node.getNextSibling()) {
1990             int type = node.getType();
1991             String text = null;
1992             switch (type) {
1993 
1994                 case STRING_LITERAL:
1995                     if (isPrevString)  assertNodeType(IDENT, node);  // parser bug
1996                     isPrevString = true;
1997                     text = node.getText();
1998                     ConstantExpression constantExpression = new ConstantExpression(text);
1999                     configureAST(constantExpression, node);
2000                     strings.add(constantExpression);
2001                     buffer.append(text);
2002                     break;
2003 
2004                 default:
2005                     {
2006                         if (!isPrevString)  assertNodeType(IDENT, node);  // parser bug
2007                         isPrevString = false;
2008                         Expression expression = expression(node);
2009                         values.add(expression);
2010                         buffer.append("$");
2011                         buffer.append(expression.getText());
2012                     }
2013                     break;
2014             }
2015         }
2016         GStringExpression gStringExpression = new GStringExpression(buffer.toString(), strings, values);
2017         configureAST(gStringExpression, gstringNode);
2018         return gStringExpression;
2019     }
2020 
2021     protected ClassNode type(AST typeNode) {
2022         // TODO intern types?
2023         // TODO configureAST(...)
2024         return buildName(typeNode.getFirstChild());
2025     }
2026 
2027     public static String qualifiedName(AST qualifiedNameNode) {
2028         if (isType(IDENT, qualifiedNameNode)) {
2029             return qualifiedNameNode.getText();
2030         }
2031         if (isType(DOT, qualifiedNameNode)) {
2032             AST node = qualifiedNameNode.getFirstChild();
2033             StringBuffer buffer = new StringBuffer();
2034             boolean first = true;
2035 
2036             for (; node != null; node = node.getNextSibling()) {
2037                 if (first) {
2038                     first = false;
2039                 }
2040                 else {
2041                     buffer.append(".");
2042                 }
2043                 buffer.append(qualifiedName(node));
2044             }
2045             return buffer.toString();
2046         }
2047         else {
2048             return qualifiedNameNode.getText();
2049         }
2050     }
2051 
2052     protected ClassNode makeType(AST typeNode) {
2053         ClassNode answer = ClassHelper.DYNAMIC_TYPE;
2054         AST node = typeNode.getFirstChild();
2055         if (node != null) {
2056             if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
2057                 return makeType(node).makeArray();
2058              }
2059             return ClassHelper.make(qualifiedName(node));
2060         }
2061         return answer;
2062     }
2063 
2064     /***
2065      * Performs a name resolution to see if the given name is a type from imports,
2066      * aliases or newly created classes
2067      */
2068     /*protected String resolveTypeName(String name, boolean safe) {
2069         if (name == null) {
2070             return null;
2071         }
2072         return resolveNewClassOrName(name, safe);
2073     }*/
2074 
2075     /***
2076      * Extracts an identifier from the Antlr AST and then performs a name resolution
2077      * to see if the given name is a type from imports, aliases or newly created classes
2078      */
2079     protected ClassNode buildName(AST node) {
2080         if (isType(TYPE, node)) {
2081             node = node.getFirstChild();
2082         }
2083         ClassNode answer = null;
2084         if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
2085             answer = ClassHelper.make(qualifiedName(node));
2086         }
2087         else if (isPrimitiveTypeLiteral(node)) {
2088             answer = ClassHelper.make(node.getText());
2089         }
2090         else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
2091             AST child = node.getFirstChild();
2092             return buildName(child).makeArray();
2093         }
2094         else {
2095             String identifier = node.getText();
2096             answer = ClassHelper.make(identifier);
2097         }
2098         AST nextSibling = node.getNextSibling();
2099         if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) {
2100             return answer.makeArray();
2101         }
2102         else {
2103             return answer;
2104         }
2105     }
2106 
2107     protected boolean isPrimitiveTypeLiteral(AST node) {
2108         int type = node.getType();
2109         switch (type) {
2110             case LITERAL_boolean:
2111             case LITERAL_byte:
2112             case LITERAL_char:
2113             case LITERAL_double:
2114             case LITERAL_float:
2115             case LITERAL_int:
2116             case LITERAL_long:
2117             case LITERAL_short:
2118                 return true;
2119 
2120             default:
2121                 return false;
2122         }
2123     }
2124 
2125     /***
2126      * Extracts an identifier from the Antlr AST
2127      */
2128     protected String identifier(AST node) {
2129         assertNodeType(IDENT, node);
2130         return node.getText();
2131     }
2132 
2133     protected String label(AST labelNode) {
2134         AST node = labelNode.getFirstChild();
2135         if (node == null) {
2136             return null;
2137         }
2138         return identifier(node);
2139     }
2140 
2141 
2142 
2143     // Helper methods
2144     //-------------------------------------------------------------------------
2145 
2146 
2147     /***
2148      * Returns true if the modifiers flags contain a visibility modifier
2149      */
2150     protected boolean hasVisibility(int modifiers) {
2151         return (modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) != 0;
2152     }
2153 
2154     protected void configureAST(ASTNode node, AST ast) {
2155         if (ast==null) throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure "+node.getClass().getName()+" with null Node");
2156         node.setColumnNumber(ast.getColumn());
2157         node.setLineNumber(ast.getLine());
2158         if (ast instanceof GroovySourceAST) {
2159             node.setLastColumnNumber(((GroovySourceAST)ast).getColumnLast());
2160             node.setLastLineNumber(((GroovySourceAST)ast).getLineLast());
2161         }
2162 
2163         // TODO we could one day store the Antlr AST on the Groovy AST
2164         // node.setCSTNode(ast);
2165     }
2166 
2167     protected static Token makeToken(int typeCode, AST node) {
2168         return Token.newSymbol(typeCode, node.getLine(), node.getColumn());
2169     }
2170 
2171     protected String getFirstChildText(AST node) {
2172         AST child = node.getFirstChild();
2173         return child != null ? child.getText() : null;
2174     }
2175 
2176 
2177     public static boolean isType(int typeCode, AST node) {
2178         return node != null && node.getType() == typeCode;
2179     }
2180 
2181     private String getTokenName(int token) {
2182         if (tokenNames==null) return ""+token;
2183         return tokenNames[token];
2184     }
2185     
2186     private String getTokenName(AST node) {
2187         if (node==null) return "null";
2188         return getTokenName(node.getType());
2189     }
2190 
2191     protected void assertNodeType(int type, AST node) {
2192         if (node == null) {
2193             throw new ASTRuntimeException(node, "No child node available in AST when expecting type: " + getTokenName(type));
2194         }
2195         if (node.getType() != type) {            
2196             throw new ASTRuntimeException(node, "Unexpected node type: " + getTokenName(node) + " found when expecting type: " + getTokenName(type));
2197         }
2198     }
2199 
2200     protected void notImplementedYet(AST node) {
2201         throw new ASTRuntimeException(node, "AST node not implemented yet for type: " + getTokenName(node));
2202     }
2203 
2204     protected void unknownAST(AST node) {
2205         throw new ASTRuntimeException(node, "Unknown type: " + getTokenName(node));
2206     }
2207 
2208     protected void dumpTree(AST ast) {
2209         for (AST node = ast.getFirstChild(); node != null; node = node.getNextSibling()) {
2210             dump(node);
2211         }
2212     }
2213 
2214     protected void dump(AST node) {
2215         System.out.println("Type: " + getTokenName(node) + " text: " + node.getText());
2216     }
2217 }