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