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: 4526 $
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 caught 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         assertNotLegacyFor(forNode);
887         AST inNode = forNode.getFirstChild();
888         AST variableNode = inNode.getFirstChild();
889         AST collectionNode = variableNode.getNextSibling();
890 
891         ClassNode type = ClassHelper.OBJECT_TYPE;
892         if (isType(VARIABLE_DEF, variableNode)) {
893             AST typeNode = variableNode.getFirstChild();
894             assertNodeType(TYPE, typeNode);
895 
896             type = type(typeNode);
897             variableNode = typeNode.getNextSibling();
898         }
899         String variable = identifier(variableNode);
900 
901         Expression collectionExpression = expression(collectionNode);
902         Statement block = statement(inNode.getNextSibling());
903         Parameter forParameter = new Parameter(type,variable);
904 
905         ForStatement forStatement = new ForStatement(forParameter, collectionExpression, block);
906         configureAST(forStatement, forNode);
907         return forStatement;
908     }
909 
910     private void assertNotLegacyFor(AST forNode) {
911         AST childNode = forNode.getFirstChild();
912         boolean legacy = false;
913         while (childNode != null) {
914             int type = childNode.getType();
915             if (type == FOR_INIT || type == FOR_CONDITION || type == FOR_ITERATOR) {
916                 legacy = true;
917                 break;
918             }
919             childNode = childNode.getNextSibling();
920         }
921         if (legacy) {
922             throw new ASTRuntimeException(forNode, "For statement contains unexpected tokens. Possible attempt to use unsupported Java-style for loop.");
923         }
924     }
925 
926     protected Statement ifStatement(AST ifNode) {
927         AST node = ifNode.getFirstChild();
928         assertNodeType(EXPR, node);
929         BooleanExpression booleanExpression = booleanExpression(node);
930 
931         node = node.getNextSibling();
932         Statement ifBlock = statement(node);
933 
934         Statement elseBlock = EmptyStatement.INSTANCE;
935         node = node.getNextSibling();
936         if (node != null) {
937             elseBlock = statement(node);
938         }
939         IfStatement ifStatement = new IfStatement(booleanExpression, ifBlock, elseBlock);
940         configureAST(ifStatement, ifNode);
941         return ifStatement;
942     }
943 
944     protected Statement labelledStatement(AST labelNode) {
945         AST node = labelNode.getFirstChild();
946         String label = identifier(node);
947         Statement statement = statement(node.getNextSibling());
948         statement.setStatementLabel(label);
949         return statement;
950     }
951 
952     protected Statement methodCall(AST code) {
953         Expression expression = methodCallExpression(code);
954         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
955         configureAST(expressionStatement, code);
956         return expressionStatement;
957     }
958 
959     protected Statement variableDef(AST variableDef) {
960         AST node = variableDef.getFirstChild();
961         ClassNode type = null;
962         if (isType(MODIFIERS, node)) {
963             node = node.getNextSibling();
964         }
965         if (isType(TYPE, node)) {
966             type = makeType(node);
967             node = node.getNextSibling();
968         }
969 
970         String name = identifier(node);
971         node = node.getNextSibling();
972 
973         VariableExpression leftExpression = new VariableExpression(name, type);
974         configureAST(leftExpression, variableDef);
975 
976         Expression rightExpression = ConstantExpression.NULL;
977         if (node != null) {
978             assertNodeType(ASSIGN, node);
979 
980             rightExpression = expression(node.getFirstChild());
981         }
982         Token token = makeToken(Types.ASSIGN, variableDef);
983 
984         // TODO should we have a variable declaration statement?
985         DeclarationExpression expression = new DeclarationExpression(leftExpression, token, rightExpression);
986         configureAST(expression, variableDef);
987         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
988         configureAST(expressionStatement, variableDef);
989         return expressionStatement;
990     }
991 
992     protected Statement returnStatement(AST node) {
993         AST exprNode = node.getFirstChild();
994 
995         // This will pick up incorrect sibling node if 'node' is a plain 'return'
996 		//
997 		//if (exprNode == null) {
998         //    exprNode = node.getNextSibling();
999         //}
1000         if (exprNode != null) {
1001             Expression expression = expression(exprNode);
1002             if (expression instanceof ConstantExpression) {
1003                 ConstantExpression constantExpr = (ConstantExpression) expression;
1004                 if (constantExpr.getValue() == null) {
1005                     return ReturnStatement.RETURN_NULL_OR_VOID;
1006                 }
1007             }
1008             ReturnStatement returnStatement = new ReturnStatement(expression);
1009             configureAST(returnStatement, node);
1010             return returnStatement;
1011         }
1012         else {
1013             return ReturnStatement.RETURN_NULL_OR_VOID;
1014         }
1015     }
1016 
1017     protected Statement switchStatement(AST switchNode) {
1018         AST node = switchNode.getFirstChild();
1019         Expression expression = expression(node);
1020         Statement defaultStatement = EmptyStatement.INSTANCE;
1021 
1022         List list = new ArrayList();
1023         for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node.getNextSibling()) {
1024             AST child = node.getFirstChild();
1025             if (isType(LITERAL_case, child)) {
1026                 list.add(caseStatement(child));
1027             } else {
1028                 defaultStatement = statement(child.getNextSibling());
1029             }
1030         }
1031         if (node != null) {
1032             unknownAST(node);
1033         }
1034         SwitchStatement switchStatement = new SwitchStatement(expression, list, defaultStatement);
1035         configureAST(switchStatement, switchNode);
1036         return switchStatement;
1037     }
1038 
1039     protected CaseStatement caseStatement(AST node) {
1040         List expressions = new ArrayList();
1041         Statement statement = EmptyStatement.INSTANCE;
1042         AST nextSibling = node;
1043         do {
1044             Expression expression = expression(nextSibling.getFirstChild());
1045             expressions.add(expression);
1046             nextSibling = nextSibling.getNextSibling();
1047         } while (isType(LITERAL_case, nextSibling));
1048         if (!isType(LITERAL_default, nextSibling) && nextSibling != null) {
1049              statement = statement(nextSibling);
1050         }
1051         CaseStatement answer;
1052         if (expressions.size() == 1) {
1053             // single case uses original code for effiiency
1054             answer = new CaseStatement((Expression) expressions.get(0), statement);
1055         } else {
1056             // multiple cases in casegroup are grouped as an expression
1057             // doesn't seem to mix well with certain case expressions, e.g. regex
1058             ListExpression listExpression = new ListExpression(expressions);
1059             answer = new CaseStatement(listExpression, statement);
1060         }
1061         configureAST(answer, node);
1062         return answer;
1063     }
1064 
1065     protected Statement synchronizedStatement(AST syncNode) {
1066         AST node = syncNode.getFirstChild();
1067         Expression expression = expression(node);
1068         Statement code = statement(node.getNextSibling());
1069         SynchronizedStatement synchronizedStatement = new SynchronizedStatement(expression, code);
1070         configureAST(synchronizedStatement, syncNode);
1071         return synchronizedStatement;
1072     }
1073 
1074     protected Statement throwStatement(AST node) {
1075         AST expressionNode = node.getFirstChild();
1076         if (expressionNode == null) {
1077             expressionNode = node.getNextSibling();
1078         }
1079         if (expressionNode == null) {
1080             throw new ASTRuntimeException(node, "No expression available");
1081         }
1082         ThrowStatement throwStatement = new ThrowStatement(expression(expressionNode));
1083         configureAST(throwStatement, node);
1084         return throwStatement;
1085     }
1086 
1087     protected Statement tryStatement(AST tryStatementNode) {
1088         AST tryNode = tryStatementNode.getFirstChild();
1089         Statement tryStatement = statement(tryNode);
1090         Statement finallyStatement = EmptyStatement.INSTANCE;
1091         AST node = tryNode.getNextSibling();
1092 
1093         // lets do the catch nodes
1094         List catches = new ArrayList();
1095         for (; node != null && isType(LITERAL_catch, node); node = node.getNextSibling()) {
1096             catches.add(catchStatement(node));
1097         }
1098 
1099         if (isType(LITERAL_finally, node)) {
1100             finallyStatement = statement(node);
1101             node = node.getNextSibling();
1102         }
1103 
1104         TryCatchStatement tryCatchStatement = new TryCatchStatement(tryStatement, finallyStatement);
1105         configureAST(tryCatchStatement, tryStatementNode);
1106         for (Iterator iter = catches.iterator(); iter.hasNext();) {
1107             CatchStatement statement = (CatchStatement) iter.next();
1108             tryCatchStatement.addCatch(statement);
1109         }
1110         return tryCatchStatement;
1111     }
1112 
1113     protected CatchStatement catchStatement(AST catchNode) {
1114         AST node = catchNode.getFirstChild();
1115         Parameter parameter = parameter(node);
1116         ClassNode exceptionType = parameter.getType();
1117         String variable = parameter.getName();
1118         node = node.getNextSibling();
1119         Statement code = statement(node);
1120         Parameter catchParameter = new Parameter(exceptionType,variable);
1121         CatchStatement answer = new CatchStatement(catchParameter, code);
1122         configureAST(answer, catchNode);
1123         return answer;
1124     }
1125 
1126     protected Statement whileStatement(AST whileNode) {
1127         AST node = whileNode.getFirstChild();
1128         assertNodeType(EXPR, node);
1129         BooleanExpression booleanExpression = booleanExpression(node);
1130 
1131         node = node.getNextSibling();
1132         Statement block = statement(node);
1133         WhileStatement whileStatement = new WhileStatement(booleanExpression, block);
1134         configureAST(whileStatement, whileNode);
1135         return whileStatement;
1136     }
1137 
1138     protected Statement withStatement(AST node) {
1139         notImplementedYet(node);
1140         return null; /*** TODO */
1141     }
1142 
1143 
1144 
1145     // Expressions
1146     //-------------------------------------------------------------------------
1147 
1148     protected Expression expression(AST node) {
1149         return expression(node,false);
1150     }
1151     
1152     protected Expression expression(AST node, boolean convertToConstant) {
1153         Expression expression = expressionSwitch(node);
1154         if (convertToConstant) {
1155             // a method name can never be a VariableExprssion, so it must converted
1156             // to a ConstantExpression then. This is needed as the expression
1157             // method doesn't know we want a ConstantExpression instead of a
1158             // VariableExpression
1159             if ( expression != VariableExpression.THIS_EXPRESSION &&
1160                  expression != VariableExpression.SUPER_EXPRESSION &&
1161                  expression instanceof VariableExpression) 
1162             {
1163                 VariableExpression ve = (VariableExpression) expression;
1164                 expression = new ConstantExpression(ve.getName());
1165             }
1166         }
1167         configureAST(expression, node);
1168         return expression;       
1169     }
1170 
1171     protected Expression expressionSwitch(AST node) {
1172         int type = node.getType();
1173         switch (type) {
1174             case EXPR:
1175                 return expression(node.getFirstChild());
1176 
1177             case ELIST:
1178                 return expressionList(node);
1179 
1180             case SLIST:
1181                 return blockExpression(node);
1182 
1183             case CLOSABLE_BLOCK:
1184                 return closureExpression(node);
1185 
1186             case SUPER_CTOR_CALL:
1187                 return specialConstructorCallExpression(node,ClassNode.SUPER);
1188 
1189             case METHOD_CALL:
1190                 return methodCallExpression(node);
1191 
1192             case LITERAL_new:
1193                 return constructorCallExpression(node.getFirstChild());
1194 
1195             case CTOR_CALL:
1196                 return specialConstructorCallExpression(node,ClassNode.THIS);
1197 
1198             case QUESTION:
1199                 return ternaryExpression(node);
1200 
1201             case OPTIONAL_DOT:
1202             case SPREAD_DOT:
1203             case DOT:
1204                 return dotExpression(node);
1205 
1206             case IDENT:
1207             case LITERAL_boolean:
1208             case LITERAL_byte:
1209             case LITERAL_char:
1210             case LITERAL_double:
1211             case LITERAL_float:
1212             case LITERAL_int:
1213             case LITERAL_long:
1214             case LITERAL_short:
1215             case LITERAL_void:
1216                 return variableExpression(node);
1217 
1218             case LIST_CONSTRUCTOR:
1219                 return listExpression(node);
1220 
1221             case MAP_CONSTRUCTOR:
1222                 return mapExpression(node);
1223 
1224             case LABELED_ARG:
1225                 return mapEntryExpression(node);
1226 
1227             case SPREAD_ARG:
1228                 return spreadExpression(node);
1229 
1230             case SPREAD_MAP_ARG:
1231                 return spreadMapExpression(node);
1232 
1233             // commented out of groovy.g due to non determinisms
1234             //case MEMBER_POINTER_DEFAULT:
1235             //    return defaultMethodPointerExpression(node);
1236 
1237             case MEMBER_POINTER:
1238                 return methodPointerExpression(node);
1239 
1240             case INDEX_OP:
1241                 return indexExpression(node);
1242 
1243             case LITERAL_instanceof:
1244                 return instanceofExpression(node);
1245 
1246             case LITERAL_as:
1247                 return asExpression(node);
1248 
1249             case TYPECAST:
1250                 return castExpression(node);
1251 
1252                 // literals
1253 
1254             case LITERAL_true:
1255                 return ConstantExpression.TRUE;
1256 
1257             case LITERAL_false:
1258                 return ConstantExpression.FALSE;
1259 
1260             case LITERAL_null:
1261                 return ConstantExpression.NULL;
1262 
1263             case STRING_LITERAL:
1264                 ConstantExpression constantExpression = new ConstantExpression(node.getText());
1265                 configureAST(constantExpression, node);
1266                 return constantExpression;
1267 
1268             case STRING_CONSTRUCTOR:
1269                 return gstring(node);
1270 
1271             case NUM_DOUBLE:
1272             case NUM_FLOAT:
1273             case NUM_BIG_DECIMAL:
1274                 return decimalExpression(node);
1275 
1276             case NUM_BIG_INT:
1277             case NUM_INT:
1278             case NUM_LONG:
1279                 return integerExpression(node);
1280 
1281             case LITERAL_this:
1282                 return VariableExpression.THIS_EXPRESSION;
1283 
1284             case LITERAL_super:
1285                 return VariableExpression.SUPER_EXPRESSION;
1286 
1287 
1288                 // Unary expressions
1289             case LNOT:
1290                 NotExpression notExpression = new NotExpression(expression(node.getFirstChild()));
1291                 configureAST(notExpression, node);
1292                 return notExpression;
1293 
1294             case UNARY_MINUS:
1295                 return negateExpression(node);
1296 
1297             case BNOT:
1298                 BitwiseNegExpression bitwiseNegExpression = new BitwiseNegExpression(expression(node.getFirstChild()));
1299                 configureAST(bitwiseNegExpression, node);
1300                 return bitwiseNegExpression;
1301 
1302             case UNARY_PLUS:
1303                 return expression(node.getFirstChild());
1304 
1305 
1306                 // Prefix expressions
1307             case INC:
1308                 return prefixExpression(node, Types.PLUS_PLUS);
1309 
1310             case DEC:
1311                 return prefixExpression(node, Types.MINUS_MINUS);
1312 
1313                 // Postfix expressions
1314             case POST_INC:
1315                 return postfixExpression(node, Types.PLUS_PLUS);
1316 
1317             case POST_DEC:
1318                 return postfixExpression(node, Types.MINUS_MINUS);
1319 
1320 
1321                 // Binary expressions
1322 
1323             case ASSIGN:
1324                 return binaryExpression(Types.ASSIGN, node);
1325 
1326             case EQUAL:
1327                 return binaryExpression(Types.COMPARE_EQUAL, node);
1328 
1329             case NOT_EQUAL:
1330                 return binaryExpression(Types.COMPARE_NOT_EQUAL, node);
1331 
1332             case COMPARE_TO:
1333                 return binaryExpression(Types.COMPARE_TO, node);
1334 
1335             case LE:
1336                 return binaryExpression(Types.COMPARE_LESS_THAN_EQUAL, node);
1337 
1338             case LT:
1339                 return binaryExpression(Types.COMPARE_LESS_THAN, node);
1340 
1341             case GT:
1342                 return binaryExpression(Types.COMPARE_GREATER_THAN, node);
1343 
1344             case GE:
1345                 return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL, node);
1346 
1347                 /***
1348                  * TODO treble equal?
1349                  return binaryExpression(Types.COMPARE_IDENTICAL, node);
1350 
1351                  case ???:
1352                  return binaryExpression(Types.LOGICAL_AND_EQUAL, node);
1353 
1354                  case ???:
1355                  return binaryExpression(Types.LOGICAL_OR_EQUAL, node);
1356 
1357                  */
1358 
1359             case LAND:
1360                 return binaryExpression(Types.LOGICAL_AND, node);
1361 
1362             case LOR:
1363                 return binaryExpression(Types.LOGICAL_OR, node);
1364 
1365             case BAND:
1366                 return binaryExpression(Types.BITWISE_AND, node);
1367 
1368             case BAND_ASSIGN:
1369                 return binaryExpression(Types.BITWISE_AND_EQUAL, node);
1370 
1371             case BOR:
1372                 return binaryExpression(Types.BITWISE_OR, node);
1373 
1374             case BOR_ASSIGN:
1375                 return binaryExpression(Types.BITWISE_OR_EQUAL, node);
1376 
1377             case BXOR:
1378                 return binaryExpression(Types.BITWISE_XOR, node);
1379 
1380             case BXOR_ASSIGN:
1381                 return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
1382 
1383 
1384             case PLUS:
1385                 return binaryExpression(Types.PLUS, node);
1386 
1387             case PLUS_ASSIGN:
1388                 return binaryExpression(Types.PLUS_EQUAL, node);
1389 
1390 
1391             case MINUS:
1392                 return binaryExpression(Types.MINUS, node);
1393 
1394             case MINUS_ASSIGN:
1395                 return binaryExpression(Types.MINUS_EQUAL, node);
1396 
1397 
1398             case STAR:
1399                 return binaryExpression(Types.MULTIPLY, node);
1400 
1401             case STAR_ASSIGN:
1402                 return binaryExpression(Types.MULTIPLY_EQUAL, node);
1403 
1404 
1405             case STAR_STAR:
1406                 return binaryExpression(Types.POWER, node);
1407 
1408             case STAR_STAR_ASSIGN:
1409                 return binaryExpression(Types.POWER_EQUAL, node);
1410 
1411 
1412             case DIV:
1413                 return binaryExpression(Types.DIVIDE, node);
1414 
1415             case DIV_ASSIGN:
1416                 return binaryExpression(Types.DIVIDE_EQUAL, node);
1417 
1418 
1419             case MOD:
1420                 return binaryExpression(Types.MOD, node);
1421 
1422             case MOD_ASSIGN:
1423                 return binaryExpression(Types.MOD_EQUAL, node);
1424 
1425             case SL:
1426                 return binaryExpression(Types.LEFT_SHIFT, node);
1427 
1428             case SL_ASSIGN:
1429                 return binaryExpression(Types.LEFT_SHIFT_EQUAL, node);
1430 
1431             case SR:
1432                 return binaryExpression(Types.RIGHT_SHIFT, node);
1433 
1434             case SR_ASSIGN:
1435                 return binaryExpression(Types.RIGHT_SHIFT_EQUAL, node);
1436 
1437             case BSR:
1438                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED, node);
1439 
1440             case BSR_ASSIGN:
1441                 return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED_EQUAL, node);
1442 
1443                 // Regex
1444             case REGEX_FIND:
1445                 return binaryExpression(Types.FIND_REGEX, node);
1446 
1447             case REGEX_MATCH:
1448                 return binaryExpression(Types.MATCH_REGEX, node);
1449 
1450 
1451                 // Ranges
1452             case RANGE_INCLUSIVE:
1453                 return rangeExpression(node, true);
1454 
1455             case RANGE_EXCLUSIVE:
1456                 return rangeExpression(node, false);
1457 
1458             case DYNAMIC_MEMBER:
1459                 return dynamicMemberExpression(node);
1460                 
1461             case LITERAL_in:
1462                 return binaryExpression(Types.KEYWORD_IN,node);
1463                 
1464             default:
1465                 unknownAST(node);
1466         }
1467         return null;
1468     }
1469 
1470     protected Expression dynamicMemberExpression(AST dynamicMemberNode) {
1471         AST node = dynamicMemberNode.getFirstChild();
1472         return expression(node);
1473     }
1474 
1475     protected Expression ternaryExpression(AST ternaryNode) {
1476         AST node = ternaryNode.getFirstChild();
1477         BooleanExpression booleanExpression = booleanExpression(node);
1478         node = node.getNextSibling();
1479         Expression left = expression(node);
1480         Expression right = expression(node.getNextSibling());
1481         TernaryExpression ternaryExpression = new TernaryExpression(booleanExpression, left, right);
1482         configureAST(ternaryExpression, ternaryNode);
1483         return ternaryExpression;
1484     }
1485 
1486     protected Expression variableExpression(AST node) {
1487         String text = node.getText();
1488 
1489         // TODO we might wanna only try to resolve the name if we are
1490         // on the left hand side of an expression or before a dot?
1491         VariableExpression variableExpression = new VariableExpression(text);
1492         configureAST(variableExpression, node);
1493         return variableExpression;
1494     }
1495 
1496     protected Expression rangeExpression(AST rangeNode, boolean inclusive) {
1497         AST node = rangeNode.getFirstChild();
1498         Expression left = expression(node);
1499         Expression right = expression(node.getNextSibling());
1500         RangeExpression rangeExpression = new RangeExpression(left, right, inclusive);
1501         configureAST(rangeExpression, rangeNode);
1502         return rangeExpression;
1503     }
1504 
1505     protected Expression spreadExpression(AST node) {
1506         AST exprNode = node.getFirstChild();
1507         AST listNode = exprNode.getFirstChild();
1508         Expression right = expression(listNode);
1509         SpreadExpression spreadExpression = new SpreadExpression(right);
1510         configureAST(spreadExpression, node);
1511         return spreadExpression;
1512     }
1513 
1514     protected Expression spreadMapExpression(AST node) {
1515         AST exprNode = node.getFirstChild();
1516         Expression expr = expression(exprNode);
1517         SpreadMapExpression spreadMapExpression = new SpreadMapExpression(expr);
1518         configureAST(spreadMapExpression, node);
1519         return spreadMapExpression;
1520     }
1521 
1522     protected Expression methodPointerExpression(AST node) {
1523         AST exprNode = node.getFirstChild();
1524         String methodName = identifier(exprNode.getNextSibling());
1525         Expression expression = expression(exprNode);
1526         MethodPointerExpression methodPointerExpression = new MethodPointerExpression(expression, methodName);
1527         configureAST(methodPointerExpression, node);
1528         return methodPointerExpression;
1529     }
1530 
1531 /*  commented out due to groovy.g non-determinisms
1532   protected Expression defaultMethodPointerExpression(AST node) {
1533         AST exprNode = node.getFirstChild();
1534         String methodName = exprNode.toString();
1535         MethodPointerExpression methodPointerExpression = new MethodPointerExpression(null, methodName);
1536         configureAST(methodPointerExpression, node);
1537         return methodPointerExpression;
1538     }
1539 */
1540 
1541     protected Expression listExpression(AST listNode) {
1542         List expressions = new ArrayList();
1543         AST elist = listNode.getFirstChild();
1544         assertNodeType(ELIST, elist);
1545 
1546         for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1547             // check for stray labeled arguments:
1548             switch (node.getType()) {
1549             case LABELED_ARG:       assertNodeType(COMMA, node);       break;  // helpful error?
1550             case SPREAD_MAP_ARG:    assertNodeType(SPREAD_ARG, node);  break;  // helpful error
1551             }
1552             expressions.add(expression(node));
1553         }
1554         ListExpression listExpression = new ListExpression(expressions);
1555         configureAST(listExpression, listNode);
1556         return listExpression;
1557     }
1558 
1559     /***
1560      * Typically only used for map constructors I think?
1561      */
1562     protected Expression mapExpression(AST mapNode) {
1563         List expressions = new ArrayList();
1564         AST elist = mapNode.getFirstChild();
1565         if (elist != null) {  // totally empty in the case of [:]
1566             assertNodeType(ELIST, elist);
1567             for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1568                 switch (node.getType()) {
1569                 case LABELED_ARG:
1570                 case SPREAD_MAP_ARG:
1571                     break;  // legal cases
1572                 case SPREAD_ARG:
1573                     assertNodeType(SPREAD_MAP_ARG, node);  break;  // helpful error
1574                 default:
1575                     assertNodeType(LABELED_ARG, node);  break;  // helpful error
1576                 }
1577                 expressions.add(mapEntryExpression(node));
1578             }
1579         }
1580         MapExpression mapExpression = new MapExpression(expressions);
1581         configureAST(mapExpression, mapNode);
1582         return mapExpression;
1583     }
1584 
1585     protected MapEntryExpression mapEntryExpression(AST node) {
1586         if (node.getType() == SPREAD_MAP_ARG) {
1587             AST rightNode = node.getFirstChild();
1588             Expression keyExpression = spreadMapExpression(node);
1589             Expression rightExpression = expression(rightNode);
1590             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
1591             configureAST(mapEntryExpression, node);
1592             return mapEntryExpression;
1593         }
1594         else {
1595             AST keyNode = node.getFirstChild();
1596             Expression keyExpression = expression(keyNode);
1597             AST valueNode = keyNode.getNextSibling();
1598             Expression valueExpression = expression(valueNode);
1599             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, valueExpression);
1600             configureAST(mapEntryExpression, node);
1601             return mapEntryExpression;
1602         }
1603     }
1604 
1605 
1606     protected Expression instanceofExpression(AST node) {
1607         AST leftNode = node.getFirstChild();
1608         Expression leftExpression = expression(leftNode);
1609 
1610         AST rightNode = leftNode.getNextSibling();
1611         ClassNode type = buildName(rightNode);
1612         assertTypeNotNull(type, rightNode);
1613 
1614         Expression rightExpression = new ClassExpression(type);
1615         configureAST(rightExpression, rightNode);
1616         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.KEYWORD_INSTANCEOF, node), rightExpression);
1617         configureAST(binaryExpression, node);
1618         return binaryExpression;
1619     }
1620 
1621     protected void assertTypeNotNull(ClassNode type, AST rightNode) {
1622         if (type == null) {
1623             throw new ASTRuntimeException(rightNode, "No type available for: " + qualifiedName(rightNode));
1624         }
1625     }
1626 
1627     protected Expression asExpression(AST node) {
1628         AST leftNode = node.getFirstChild();
1629         Expression leftExpression = expression(leftNode);
1630 
1631         AST rightNode = leftNode.getNextSibling();
1632         ClassNode type = buildName(rightNode);
1633 
1634         return CastExpression.asExpression(type, leftExpression);
1635     }
1636 
1637     protected Expression castExpression(AST castNode) {
1638         AST node = castNode.getFirstChild();
1639         ClassNode type = buildName(node);
1640         assertTypeNotNull(type, node);
1641 
1642         AST expressionNode = node.getNextSibling();
1643         Expression expression = expression(expressionNode);
1644 
1645         CastExpression castExpression = new CastExpression(type, expression);
1646         configureAST(castExpression, castNode);
1647         return castExpression;
1648     }
1649 
1650 
1651     protected Expression indexExpression(AST indexNode) {
1652         AST leftNode = indexNode.getFirstChild();
1653         Expression leftExpression = expression(leftNode);
1654 
1655         AST rightNode = leftNode.getNextSibling();
1656         Expression rightExpression = expression(rightNode);
1657 
1658         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.LEFT_SQUARE_BRACKET, indexNode), rightExpression);
1659         configureAST(binaryExpression, indexNode);
1660         return binaryExpression;
1661     }
1662 
1663     protected Expression binaryExpression(int type, AST node) {
1664         Token token = makeToken(type, node);
1665 
1666         AST leftNode = node.getFirstChild();
1667         Expression leftExpression = expression(leftNode);
1668 
1669         AST rightNode = leftNode.getNextSibling();
1670         if (rightNode == null) {
1671             return leftExpression;
1672         }
1673 
1674         if (Types.ofType(type, Types.ASSIGNMENT_OPERATOR)) {
1675             if (leftExpression instanceof VariableExpression || leftExpression.getClass() == PropertyExpression.class
1676                                                              || leftExpression instanceof FieldExpression
1677                                                              || leftExpression instanceof AttributeExpression
1678                                                              || leftExpression instanceof DeclarationExpression) {
1679                 // Do nothing.
1680             }
1681             else if (leftExpression instanceof ConstantExpression) {
1682                 throw new ASTRuntimeException(node, "\n[" + ((ConstantExpression) leftExpression).getValue() + "] is a constant expression, but it should be a variable expression");
1683             }
1684             else if (leftExpression instanceof BinaryExpression) {
1685                 Expression leftexp = ((BinaryExpression) leftExpression).getLeftExpression();
1686                 int lefttype = ((BinaryExpression) leftExpression).getOperation().getType();
1687                 if (!Types.ofType(lefttype, Types.ASSIGNMENT_OPERATOR) && lefttype != Types.LEFT_SQUARE_BRACKET) {
1688                     throw new ASTRuntimeException(node, "\n" + ((BinaryExpression) leftExpression).getText() + " is a binary expression, but it should be a variable expression");
1689                 }
1690             }
1691             else if (leftExpression instanceof GStringExpression) {
1692                 throw new ASTRuntimeException(node, "\n\"" + ((GStringExpression) leftExpression).getText() + "\" is a GString expression, but it should be a variable expression");
1693             }
1694             else if (leftExpression instanceof MethodCallExpression) {
1695                 throw new ASTRuntimeException(node, "\n\"" + ((MethodCallExpression) leftExpression).getText() + "\" is a method call expression, but it should be a variable expression");
1696             }
1697             else if (leftExpression instanceof MapExpression) {
1698                 throw new ASTRuntimeException(node, "\n'" + ((MapExpression) leftExpression).getText() + "' is a map expression, but it should be a variable expression");
1699             }
1700             else {
1701                 throw new ASTRuntimeException(node, "\n" + leftExpression.getClass() + ", with its value '" + leftExpression.getText() + "', is a bad expression as the LSH of an assignment operator");
1702             }
1703         }
1704         /*if (rightNode == null) {
1705             throw new NullPointerException("No rightNode associated with binary expression");
1706         }*/
1707         Expression rightExpression = expression(rightNode);
1708         BinaryExpression binaryExpression = new BinaryExpression(leftExpression, token, rightExpression);
1709         configureAST(binaryExpression, node);
1710         return binaryExpression;
1711     }
1712 
1713     protected Expression prefixExpression(AST node, int token) {
1714         Expression expression = expression(node.getFirstChild());
1715         PrefixExpression prefixExpression = new PrefixExpression(makeToken(token, node), expression);
1716         configureAST(prefixExpression, node);
1717         return prefixExpression;
1718     }
1719 
1720     protected Expression postfixExpression(AST node, int token) {
1721         Expression expression = expression(node.getFirstChild());
1722         PostfixExpression postfixExpression = new PostfixExpression(expression, makeToken(token, node));
1723         configureAST(postfixExpression, node);
1724         return postfixExpression;
1725     }
1726 
1727     protected BooleanExpression booleanExpression(AST node) {
1728         BooleanExpression booleanExpression = new BooleanExpression(expression(node));
1729         configureAST(booleanExpression, node);
1730         return booleanExpression;
1731     }
1732 
1733     protected Expression dotExpression(AST node) {
1734         // lets decide if this is a propery invocation or a method call
1735         AST leftNode = node.getFirstChild();
1736         if (leftNode != null) {
1737             AST identifierNode = leftNode.getNextSibling();
1738             if (identifierNode != null) {
1739                 Expression leftExpression = expression(leftNode);
1740                 if (isType(SELECT_SLOT, identifierNode)) {
1741                     Expression field = expression(identifierNode.getFirstChild(),true);
1742                     AttributeExpression attributeExpression = new AttributeExpression(leftExpression, field, node.getType() != DOT);
1743                     if (node.getType() == SPREAD_DOT) {
1744                         attributeExpression.setSpreadSafe(true);
1745                     }
1746                     configureAST(attributeExpression, node);
1747                     return attributeExpression;
1748                 }
1749                 Expression property = expression(identifierNode,true);
1750                 
1751                 PropertyExpression propertyExpression = new PropertyExpression(leftExpression, property, node.getType() != DOT);
1752                 if (node.getType() == SPREAD_DOT) {
1753                     propertyExpression.setSpreadSafe(true);
1754                 } 
1755                 configureAST(propertyExpression, node);
1756                 return propertyExpression;
1757             }
1758         }
1759         return methodCallExpression(node);
1760     }
1761     
1762     protected Expression specialConstructorCallExpression(AST methodCallNode, ClassNode special) {
1763         AST node = methodCallNode.getFirstChild();
1764         Expression arguments = arguments(node);
1765         
1766         ConstructorCallExpression expression = new ConstructorCallExpression(special, arguments);
1767         configureAST(expression, methodCallNode);
1768         return expression;
1769     }
1770 
1771     private int getTypeInParenthesis(AST node) {
1772         if (! isType(EXPR,node) ) node = node.getFirstChild();
1773         while (node!=null &&isType(EXPR,node) && node.getNextSibling()==null) {
1774             node = node.getFirstChild();
1775         }
1776         if (node==null) return -1;
1777         return node.getType();
1778     }
1779 
1780     protected Expression methodCallExpression(AST methodCallNode) {
1781         AST node = methodCallNode.getFirstChild();
1782         /* // Bad idea, since foo(1)(2) is valid Groovy for foo(1).call(2).
1783         if (isType(METHOD_CALL, node)) {
1784             // sometimes method calls get wrapped in method calls for some wierd reason
1785             return methodCallExpression(node);
1786         }
1787         */
1788 
1789         Expression objectExpression;
1790         AST selector;
1791         AST elist = node.getNextSibling();
1792         
1793         boolean implicitThis = false;
1794         boolean safe = isType(OPTIONAL_DOT, node);
1795         boolean spreadSafe = isType(SPREAD_DOT, node);
1796         if (isType(DOT, node) || safe || spreadSafe) {
1797             AST objectNode = node.getFirstChild();
1798             objectExpression = expression(objectNode);
1799             selector = objectNode.getNextSibling();
1800         } else {
1801             implicitThis = true;
1802             objectExpression = VariableExpression.THIS_EXPRESSION;
1803             selector = node;
1804         } 
1805 
1806         Expression name = null;
1807         if (isType(LITERAL_super, selector)) {
1808             implicitThis = true;
1809             name = new ConstantExpression("super");
1810             if (objectExpression == VariableExpression.THIS_EXPRESSION) {
1811                 objectExpression = VariableExpression.SUPER_EXPRESSION;
1812             }
1813         } else if (isPrimitiveTypeLiteral(selector)) {
1814             throw new ASTRuntimeException(selector, "Primitive type literal: " + selector.getText()
1815                     + " cannot be used as a method name");
1816         } else if (isType(SELECT_SLOT, selector)) {
1817             Expression field = expression(selector.getFirstChild(),true);
1818             AttributeExpression attributeExpression = new AttributeExpression(objectExpression, field, node.getType() != DOT);
1819             configureAST(attributeExpression, node);
1820             Expression arguments = arguments(elist);
1821             MethodCallExpression expression = new MethodCallExpression(attributeExpression, "call", arguments);
1822             configureAST(expression, methodCallNode);
1823             return expression;
1824         } else if  
1825                (isType(DYNAMIC_MEMBER, selector) || isType(IDENT,selector) || 
1826                 isType(STRING_CONSTRUCTOR,selector) || isType (STRING_LITERAL,selector)) 
1827         { 
1828             name = expression(selector,true);
1829         } else {
1830             implicitThis = false;
1831             name = new ConstantExpression("call");
1832             objectExpression = expression(selector,true);
1833         } 
1834 
1835         Expression arguments = arguments(elist);
1836         MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
1837         expression.setSafe(safe);
1838         expression.setSpreadSafe(spreadSafe);
1839         expression.setImplicitThis(implicitThis);
1840         Expression ret = expression;
1841         //FIXME: do we really want this() to create a new object regardless
1842         // the position.. for example not as first statement in a constructor
1843         // this=first statement in contructor is handled by specialConstructorCallExpression
1844         // we may have to add a check and remove this part of the code
1845         if (implicitThis && "this".equals(expression.getMethodAsString())) {
1846             ret = new ConstructorCallExpression(this.classNode, arguments);
1847         }
1848         configureAST(ret, methodCallNode);
1849         return ret;
1850     }
1851     
1852     protected Expression constructorCallExpression(AST node) {
1853         AST constructorCallNode = node;
1854         ClassNode type = buildName(constructorCallNode);
1855 
1856         if (isType(CTOR_CALL, node) || isType(LITERAL_new, node)) {
1857             node = node.getFirstChild();
1858         }
1859 
1860         AST elist = node.getNextSibling();
1861 
1862         if (elist == null && isType(ELIST, node)) {
1863             elist = node;
1864             if ("(".equals(type.getName())) {
1865                 type = classNode;
1866             }
1867         }
1868 
1869         if (isType(ARRAY_DECLARATOR, elist)) {
1870             AST expressionNode = elist.getFirstChild();
1871             if (expressionNode == null) {
1872                 throw new ASTRuntimeException(elist, "No expression for the array constructor call");
1873             }
1874             List size = arraySizeExpression(expressionNode);
1875             ArrayExpression arrayExpression = new ArrayExpression(type, null, size);
1876             configureAST(arrayExpression, constructorCallNode);
1877             return arrayExpression;
1878         }
1879         Expression arguments = arguments(elist);
1880         ConstructorCallExpression expression = new ConstructorCallExpression(type, arguments);
1881         configureAST(expression, constructorCallNode);
1882         return expression;
1883     }
1884     
1885     protected List arraySizeExpression(AST node) {
1886         List list;
1887         Expression size = null;
1888     	if (isType(ARRAY_DECLARATOR,node)) {
1889     		AST right = node.getNextSibling();
1890         	if (right!=null) {
1891         		size = expression(right);
1892         	} else {
1893         		size = ConstantExpression.EMTPY_EXPRESSION;
1894         	}
1895         	list = arraySizeExpression(node.getFirstChild());
1896         } else {
1897         	size = expression(node);
1898         	list = new ArrayList();
1899         }
1900     	list.add(size);
1901     	return list;
1902     }
1903 
1904     protected Expression arguments(AST elist) {
1905         List expressionList = new ArrayList();
1906         // FIXME: all labeled arguments should follow any unlabeled arguments
1907         boolean namedArguments = false;
1908         for (AST node = elist; node != null; node = node.getNextSibling()) {
1909             if (isType(ELIST, node)) {
1910                 for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1911                     namedArguments |= addArgumentExpression(child, expressionList);
1912                 }
1913             }
1914             else {
1915                 namedArguments |= addArgumentExpression(node, expressionList);
1916             }
1917         }
1918         if (namedArguments) {
1919             if (!expressionList.isEmpty()) {
1920                 // lets remove any non-MapEntryExpression instances
1921                 // such as if the last expression is a ClosureExpression
1922                 // so lets wrap the named method calls in a Map expression
1923                 List argumentList = new ArrayList();
1924                 for (Iterator iter = expressionList.iterator(); iter.hasNext();) {
1925                     Expression expression = (Expression) iter.next();
1926                     if (!(expression instanceof MapEntryExpression)) {
1927                         argumentList.add(expression);
1928                     }
1929                 }
1930                 if (!argumentList.isEmpty()) {
1931                     expressionList.removeAll(argumentList);
1932                     MapExpression mapExpression = new MapExpression(expressionList);
1933                     configureAST(mapExpression, elist);
1934                     argumentList.add(0, mapExpression);
1935                     ArgumentListExpression argumentListExpression = new ArgumentListExpression(argumentList);
1936                     configureAST(argumentListExpression, elist);
1937                     return argumentListExpression;
1938                 }
1939             }
1940             NamedArgumentListExpression namedArgumentListExpression = new NamedArgumentListExpression(expressionList);
1941             configureAST(namedArgumentListExpression, elist);
1942             return namedArgumentListExpression;
1943         }
1944         else {
1945             ArgumentListExpression argumentListExpression = new ArgumentListExpression(expressionList);
1946             configureAST(argumentListExpression, elist);
1947             return argumentListExpression;
1948         }
1949     }
1950 
1951     protected boolean addArgumentExpression(AST node, List expressionList) {
1952         if (node.getType() == SPREAD_MAP_ARG) {
1953             AST rightNode = node.getFirstChild();
1954             Expression keyExpression = spreadMapExpression(node);
1955             Expression rightExpression = expression(rightNode);
1956             MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
1957             expressionList.add(mapEntryExpression);
1958             return true;
1959         }
1960         else {
1961             Expression expression = expression(node);
1962             expressionList.add(expression);
1963             return expression instanceof MapEntryExpression;
1964         }
1965     }
1966 
1967     protected Expression expressionList(AST node) {
1968         List expressionList = new ArrayList();
1969         for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1970             expressionList.add(expression(child));
1971         }
1972         if (expressionList.size() == 1) {
1973             return (Expression) expressionList.get(0);
1974         }
1975         else {
1976             ListExpression listExpression = new ListExpression(expressionList);
1977             configureAST(listExpression, node);
1978             return listExpression;
1979         }
1980     }
1981 
1982     protected ClosureExpression closureExpression(AST node) {
1983         AST paramNode = node.getFirstChild();
1984         Parameter[] parameters = null;
1985         AST codeNode = paramNode;
1986         if (isType(PARAMETERS, paramNode) || isType(IMPLICIT_PARAMETERS, paramNode)) {
1987             parameters = parameters(paramNode);
1988             codeNode = paramNode.getNextSibling();
1989         }
1990         Statement code = statementListNoChild(codeNode);
1991         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
1992         configureAST(closureExpression, node);
1993         return closureExpression;
1994     }
1995 
1996     protected Expression blockExpression(AST node) {
1997         AST codeNode = node.getFirstChild();
1998         if (codeNode == null)  return ConstantExpression.NULL;
1999         if (codeNode.getType() == EXPR && codeNode.getNextSibling() == null) {
2000             // Simplify common case of {expr} to expr.
2001             return expression(codeNode);
2002         }
2003         Parameter[] parameters = Parameter.EMPTY_ARRAY;
2004         Statement code = statementListNoChild(codeNode);
2005         ClosureExpression closureExpression = new ClosureExpression(parameters, code);
2006         configureAST(closureExpression, node);
2007         // Call it immediately.
2008         String callName = "call";
2009         Expression noArguments = new ArgumentListExpression();
2010         MethodCallExpression call = new MethodCallExpression(closureExpression, callName, noArguments);
2011         configureAST(call, node);
2012         return call;
2013     }
2014 
2015     protected Expression negateExpression(AST negateExpr) {
2016         AST node = negateExpr.getFirstChild();
2017 
2018         // if we are a number literal then lets just parse it
2019         // as the negation operator on MIN_INT causes rounding to a long
2020         String text = node.getText();
2021         switch (node.getType()) {
2022             case NUM_DOUBLE:
2023             case NUM_FLOAT:
2024             case NUM_BIG_DECIMAL:
2025                 ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal("-" + text));
2026                 configureAST(constantExpression, negateExpr);
2027                 return constantExpression;
2028 
2029             case NUM_BIG_INT:
2030             case NUM_INT:
2031             case NUM_LONG:
2032                 ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger("-" + text));
2033                 configureAST(constantLongExpression, negateExpr);
2034                 return constantLongExpression;
2035 
2036             default:
2037                 NegationExpression negationExpression = new NegationExpression(expression(node));
2038                 configureAST(negationExpression, negateExpr);
2039                 return negationExpression;
2040         }
2041     }
2042 
2043     protected ConstantExpression decimalExpression(AST node) {
2044         String text = node.getText();
2045         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal(text));
2046         configureAST(constantExpression, node);
2047         return constantExpression;
2048     }
2049 
2050     protected ConstantExpression integerExpression(AST node) {
2051         String text = node.getText();
2052         ConstantExpression constantExpression = new ConstantExpression(Numbers.parseInteger(text));
2053         configureAST(constantExpression, node);
2054         return constantExpression;
2055     }
2056 
2057     protected Expression gstring(AST gstringNode) {
2058         List strings = new ArrayList();
2059         List values = new ArrayList();
2060 
2061         StringBuffer buffer = new StringBuffer();
2062 
2063         boolean isPrevString = false;
2064 
2065         for (AST node = gstringNode.getFirstChild(); node != null; node = node.getNextSibling()) {
2066             int type = node.getType();
2067             String text = null;
2068             switch (type) {
2069 
2070                 case STRING_LITERAL:
2071                     if (isPrevString)  assertNodeType(IDENT, node);  // parser bug
2072                     isPrevString = true;
2073                     text = node.getText();
2074                     ConstantExpression constantExpression = new ConstantExpression(text);
2075                     configureAST(constantExpression, node);
2076                     strings.add(constantExpression);
2077                     buffer.append(text);
2078                     break;
2079 
2080                 default:
2081                     {
2082                         if (!isPrevString)  assertNodeType(IDENT, node);  // parser bug
2083                         isPrevString = false;
2084                         Expression expression = expression(node);
2085                         values.add(expression);
2086                         buffer.append("$");
2087                         buffer.append(expression.getText());
2088                     }
2089                     break;
2090             }
2091         }
2092         GStringExpression gStringExpression = new GStringExpression(buffer.toString(), strings, values);
2093         configureAST(gStringExpression, gstringNode);
2094         return gStringExpression;
2095     }
2096 
2097     protected ClassNode type(AST typeNode) {
2098         // TODO intern types?
2099         // TODO configureAST(...)
2100         return buildName(typeNode.getFirstChild());
2101     }
2102 
2103     public static String qualifiedName(AST qualifiedNameNode) {
2104         if (isType(IDENT, qualifiedNameNode)) {
2105             return qualifiedNameNode.getText();
2106         }
2107         if (isType(DOT, qualifiedNameNode)) {
2108             AST node = qualifiedNameNode.getFirstChild();
2109             StringBuffer buffer = new StringBuffer();
2110             boolean first = true;
2111 
2112             for (; node != null; node = node.getNextSibling()) {
2113                 if (first) {
2114                     first = false;
2115                 }
2116                 else {
2117                     buffer.append(".");
2118                 }
2119                 buffer.append(qualifiedName(node));
2120             }
2121             return buffer.toString();
2122         }
2123         else {
2124             return qualifiedNameNode.getText();
2125         }
2126     }
2127 
2128     protected ClassNode makeType(AST typeNode) {
2129         ClassNode answer = ClassHelper.DYNAMIC_TYPE;
2130         AST node = typeNode.getFirstChild();
2131         if (node != null) {
2132             if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
2133                 return makeType(node).makeArray();
2134              }
2135             return ClassHelper.make(qualifiedName(node));
2136         }
2137         return answer;
2138     }
2139 
2140     /***
2141      * Performs a name resolution to see if the given name is a type from imports,
2142      * aliases or newly created classes
2143      */
2144     /*protected String resolveTypeName(String name, boolean safe) {
2145         if (name == null) {
2146             return null;
2147         }
2148         return resolveNewClassOrName(name, safe);
2149     }*/
2150 
2151     /***
2152      * Extracts an identifier from the Antlr AST and then performs a name resolution
2153      * to see if the given name is a type from imports, aliases or newly created classes
2154      */
2155     protected ClassNode buildName(AST node) {
2156         if (isType(TYPE, node)) {
2157             node = node.getFirstChild();
2158         }
2159         ClassNode answer = null;
2160         if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
2161             answer = ClassHelper.make(qualifiedName(node));
2162         }
2163         else if (isPrimitiveTypeLiteral(node)) {
2164             answer = ClassHelper.make(node.getText());
2165         }
2166         else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
2167             AST child = node.getFirstChild();
2168             return buildName(child).makeArray();
2169         }
2170         else {
2171             String identifier = node.getText();
2172             answer = ClassHelper.make(identifier);
2173         }
2174         AST nextSibling = node.getNextSibling();
2175         if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) {
2176             return answer.makeArray();
2177         }
2178         else {
2179             return answer;
2180         }
2181     }
2182 
2183     protected boolean isPrimitiveTypeLiteral(AST node) {
2184         int type = node.getType();
2185         switch (type) {
2186             case LITERAL_boolean:
2187             case LITERAL_byte:
2188             case LITERAL_char:
2189             case LITERAL_double:
2190             case LITERAL_float:
2191             case LITERAL_int:
2192             case LITERAL_long:
2193             case LITERAL_short:
2194                 return true;
2195 
2196             default:
2197                 return false;
2198         }
2199     }
2200 
2201     /***
2202      * Extracts an identifier from the Antlr AST
2203      */
2204     protected String identifier(AST node) {
2205         assertNodeType(IDENT, node);
2206         return node.getText();
2207     }
2208 
2209     protected String label(AST labelNode) {
2210         AST node = labelNode.getFirstChild();
2211         if (node == null) {
2212             return null;
2213         }
2214         return identifier(node);
2215     }
2216 
2217 
2218 
2219     // Helper methods
2220     //-------------------------------------------------------------------------
2221 
2222 
2223     /***
2224      * Returns true if the modifiers flags contain a visibility modifier
2225      */
2226     protected boolean hasVisibility(int modifiers) {
2227         return (modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) != 0;
2228     }
2229 
2230     protected void configureAST(ASTNode node, AST ast) {
2231         if (ast==null) throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure "+node.getClass().getName()+" with null Node");
2232         node.setColumnNumber(ast.getColumn());
2233         node.setLineNumber(ast.getLine());
2234         if (ast instanceof GroovySourceAST) {
2235             node.setLastColumnNumber(((GroovySourceAST)ast).getColumnLast());
2236             node.setLastLineNumber(((GroovySourceAST)ast).getLineLast());
2237         }
2238 
2239         // TODO we could one day store the Antlr AST on the Groovy AST
2240         // node.setCSTNode(ast);
2241     }
2242 
2243     protected static Token makeToken(int typeCode, AST node) {
2244         return Token.newSymbol(typeCode, node.getLine(), node.getColumn());
2245     }
2246 
2247     protected String getFirstChildText(AST node) {
2248         AST child = node.getFirstChild();
2249         return child != null ? child.getText() : null;
2250     }
2251 
2252 
2253     public static boolean isType(int typeCode, AST node) {
2254         return node != null && node.getType() == typeCode;
2255     }
2256 
2257     private String getTokenName(int token) {
2258         if (tokenNames==null) return ""+token;
2259         return tokenNames[token];
2260     }
2261     
2262     private String getTokenName(AST node) {
2263         if (node==null) return "null";
2264         return getTokenName(node.getType());
2265     }
2266 
2267     protected void assertNodeType(int type, AST node) {
2268         if (node == null) {
2269             throw new ASTRuntimeException(node, "No child node available in AST when expecting type: " + getTokenName(type));
2270         }
2271         if (node.getType() != type) {            
2272             throw new ASTRuntimeException(node, "Unexpected node type: " + getTokenName(node) + " found when expecting type: " + getTokenName(type));
2273         }
2274     }
2275 
2276     protected void notImplementedYet(AST node) {
2277         throw new ASTRuntimeException(node, "AST node not implemented yet for type: " + getTokenName(node));
2278     }
2279 
2280     protected void unknownAST(AST node) {
2281         if (node.getType() == CLASS_DEF) {
2282             throw new ASTRuntimeException(node,
2283                     "Class definition not expected here. Possible attempt to use inner class. " +
2284                             "Inner classes not supported, perhaps try using a closure instead.");
2285         }
2286         throw new ASTRuntimeException(node, "Unknown type: " + getTokenName(node));
2287     }
2288 
2289     protected void dumpTree(AST ast) {
2290         for (AST node = ast.getFirstChild(); node != null; node = node.getNextSibling()) {
2291             dump(node);
2292         }
2293     }
2294 
2295     protected void dump(AST node) {
2296         System.out.println("Type: " + getTokenName(node) + " text: " + node.getText());
2297     }
2298 }