KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > groovy > antlr > AntlrParserPlugin


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.ast.*;
31 import org.codehaus.groovy.ast.expr.*;
32 import org.codehaus.groovy.ast.stmt.*;
33 import org.codehaus.groovy.control.CompilationFailedException;
34 import org.codehaus.groovy.control.ParserPlugin;
35 import org.codehaus.groovy.control.SourceUnit;
36 import org.codehaus.groovy.syntax.Numbers;
37 import org.codehaus.groovy.syntax.Reduction;
38 import org.codehaus.groovy.syntax.SyntaxException;
39 import org.codehaus.groovy.syntax.Token;
40 import org.codehaus.groovy.syntax.Types;
41 import org.codehaus.groovy.syntax.ASTHelper;
42 import org.codehaus.groovy.syntax.ParserException;
43 import org.objectweb.asm.Opcodes;
44
45 import java.io.FileWriter JavaDoc;
46 import java.io.Reader JavaDoc;
47 import java.util.ArrayList JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.List JavaDoc;
50
51 /**
52  * A parser plugin which adapts the JSR Antlr Parser to the Groovy runtime
53  *
54  * @author <a HREF="mailto:jstrachan@protique.com">James Strachan</a>
55  * @version $Revision: 1.46 $
56  */

57 public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, GroovyTokenTypes {
58     private static final Type OBJECT_TYPE = new Type("java.lang.Object", true);
59
60     private AST ast;
61     private ClassNode classNode;
62     private String JavaDoc[] tokenNames;
63
64
65     public Reduction parseCST(SourceUnit sourceUnit, Reader JavaDoc reader) throws CompilationFailedException {
66         ast = null;
67
68         setController(sourceUnit);
69
70         SourceBuffer sourceBuffer = new SourceBuffer();
71         UnicodeEscapingReader unicodeReader = new UnicodeEscapingReader(reader,sourceBuffer);
72         GroovyLexer lexer = new GroovyLexer(unicodeReader);
73         unicodeReader.setLexer(lexer);
74         GroovyRecognizer parser = GroovyRecognizer.make(lexer);
75         parser.setSourceBuffer(sourceBuffer);
76         tokenNames = parser.getTokenNames();
77         parser.setFilename(sourceUnit.getName());
78
79         // start parsing at the compilationUnit rule
80
try {
81             parser.compilationUnit();
82         }
83         catch (TokenStreamRecognitionException tsre) {
84             RecognitionException e = tsre.recog;
85             SyntaxException se = new SyntaxException(e.getMessage(),e,e.getLine(),e.getColumn());
86             se.setFatal(true);
87             sourceUnit.addError(se);
88         }
89         catch (RecognitionException e) {
90             SyntaxException se = new SyntaxException(e.getMessage(),e,e.getLine(),e.getColumn());
91             se.setFatal(true);
92             sourceUnit.addError(se);
93         }
94         catch (TokenStreamException e) {
95             sourceUnit.addException(e);
96         }
97
98         ast = parser.getAST();
99
100         AntlrASTProcessor snippets = new AntlrASTProcessSnippets(sourceBuffer);
101         ast = snippets.process(ast);
102
103         if ("xml".equals(System.getProperty("antlr.ast"))) {
104             saveAsXML(sourceUnit.getName(), ast);
105         }
106
107         return null; //new Reduction(Tpken.EOF);
108
}
109
110     private void saveAsXML(String JavaDoc name, AST ast) {
111         XStream xstream = new XStream();
112         try {
113             xstream.toXML(ast, new FileWriter JavaDoc(name + ".antlr.xml"));
114             System.out.println("Written AST to " + name + ".antlr.xml");
115         }
116         catch (Exception JavaDoc e) {
117             System.out.println("Couldn't write to " + name + ".antlr.xml");
118             e.printStackTrace();
119         }
120     }
121
122     public ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader JavaDoc classLoader, Reduction cst) throws ParserException {
123         setClassLoader(classLoader);
124         makeModule();
125         try {
126             convertGroovy(ast);
127         }
128         catch (ASTRuntimeException e) {
129             throw new ASTParserException(e.getMessage() + ". File: " + sourceUnit.getName(), e);
130         }
131         return output;
132     }
133
134     /**
135      * Converts the Antlr AST to the Groovy AST
136      */

137     protected void convertGroovy(AST node) {
138         while (node != null) {
139             int type = node.getType();
140             switch (type) {
141                 case PACKAGE_DEF:
142                     packageDef(node);
143                     break;
144
145                 case IMPORT:
146                     importDef(node);
147                     break;
148
149                 case CLASS_DEF:
150                     classDef(node);
151                     break;
152
153                 case INTERFACE_DEF:
154                     interfaceDef(node);
155                     break;
156
157                 case METHOD_DEF:
158                     methodDef(node);
159                     break;
160
161                 default:
162                     {
163                         Statement statement = statement(node);
164                         output.addStatement(statement);
165                     }
166             }
167             node = node.getNextSibling();
168         }
169     }
170
171     // Top level control structures
172
//-------------------------------------------------------------------------
173

174     protected void packageDef(AST packageDef) {
175         AST node = packageDef.getFirstChild();
176         if (isType(ANNOTATIONS, node)) {
177             node = node.getNextSibling();
178         }
179         String JavaDoc name = qualifiedName(node);
180         setPackageName(name);
181     }
182
183     protected void importDef(AST importNode) {
184         // TODO handle static imports
185

186         AST node = importNode.getFirstChild();
187
188         String JavaDoc alias = null;
189         if (isType(LITERAL_as, node)) {
190             //import is like "import Foo as Bar"
191
node = node.getFirstChild();
192             AST aliasNode = node.getNextSibling();
193             alias = identifier(aliasNode);
194         }
195
196         if (node.getNumberOfChildren()==0) {
197             // import is like "import Foo"
198
String JavaDoc name = identifier(node);
199             importClass(null, name, alias);
200             return;
201         }
202
203         AST packageNode = node.getFirstChild();
204         String JavaDoc packageName = qualifiedName(packageNode);
205         AST nameNode = packageNode.getNextSibling();
206         if (isType(STAR, nameNode)) {
207             // import is like "import foo.*"
208
importPackageWithStar(packageName);
209             if (alias!=null) throw new GroovyBugError(
210                     "imports like 'import foo.* as Bar' are not "+
211                     "supported and should be catched by the grammar");
212         } else {
213             // import is like "import foo.Bar"
214
String JavaDoc name = identifier(nameNode);
215             importClass(packageName, name, alias);
216         }
217     }
218
219     protected void interfaceDef(AST classDef) {
220         List JavaDoc annotations = new ArrayList JavaDoc();
221         AST node = classDef.getFirstChild();
222         int modifiers = Opcodes.ACC_PUBLIC;
223         if (isType(MODIFIERS, node)) {
224             modifiers = modifiers(node, annotations, modifiers);
225             node = node.getNextSibling();
226         }
227         modifiers |= Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE;
228
229         String JavaDoc name = identifier(node);
230         node = node.getNextSibling();
231         String JavaDoc superClass = "java.lang.Object";
232
233         String JavaDoc[] interfaces = {};
234         if (isType(EXTENDS_CLAUSE, node)) {
235             interfaces = interfaces(node);
236             node = node.getNextSibling();
237         }
238
239         addNewClassName(name);
240         String JavaDoc fullClassName = dot(getPackageName(), name);
241         classNode = new ClassNode(fullClassName, modifiers, superClass, interfaces, null);
242         classNode.addAnnotations(annotations);
243         configureAST(classNode, classDef);
244
245         assertNodeType(OBJBLOCK, node);
246         objectBlock(node);
247         output.addClass(classNode);
248         classNode = null;
249     }
250
251     protected void classDef(AST classDef) {
252         List JavaDoc annotations = new ArrayList JavaDoc();
253         AST node = classDef.getFirstChild();
254         int modifiers = Opcodes.ACC_PUBLIC;
255         if (isType(MODIFIERS, node)) {
256             modifiers = modifiers(node, annotations, modifiers);
257             node = node.getNextSibling();
258         }
259
260         String JavaDoc name = identifier(node);
261         node = node.getNextSibling();
262
263         String JavaDoc superClass = null;
264         if (isType(EXTENDS_CLAUSE, node)) {
265             superClass = typeName(node);
266             node = node.getNextSibling();
267         }
268         if (superClass == null) {
269             superClass = "java.lang.Object";
270         }
271
272         String JavaDoc[] interfaces = {};
273         if (isType(IMPLEMENTS_CLAUSE, node)) {
274             interfaces = interfaces(node);
275             node = node.getNextSibling();
276         }
277
278         // TODO read mixins
279
MixinNode[] mixins = {};
280
281         addNewClassName(name);
282         String JavaDoc fullClassName = dot(getPackageName(), name);
283         classNode = new ClassNode(fullClassName, modifiers, superClass, interfaces, mixins);
284         classNode.addAnnotations(annotations);
285         configureAST(classNode, classDef);
286
287         assertNodeType(OBJBLOCK, node);
288         objectBlock(node);
289         output.addClass(classNode);
290         classNode = null;
291     }
292
293     protected void objectBlock(AST objectBlock) {
294         for (AST node = objectBlock.getFirstChild(); node != null; node = node.getNextSibling()) {
295             int type = node.getType();
296             switch (type) {
297                 case OBJBLOCK:
298                     objectBlock(node);
299                     break;
300
301                 case METHOD_DEF:
302                     methodDef(node);
303                     break;
304
305                 case CTOR_IDENT:
306                     constructorDef(node);
307                     break;
308
309                 case VARIABLE_DEF:
310                     fieldDef(node);
311                     break;
312
313                 default:
314                     unknownAST(node);
315             }
316         }
317     }
318
319     protected void methodDef(AST methodDef) {
320         List JavaDoc annotations = new ArrayList JavaDoc();
321         AST node = methodDef.getFirstChild();
322         int modifiers = Opcodes.ACC_PUBLIC;
323         if (isType(MODIFIERS, node)) {
324             modifiers = modifiers(node, annotations, modifiers);
325             node = node.getNextSibling();
326         }
327
328         if (classNode!=null && (classNode.getModifiers() & Opcodes.ACC_INTERFACE) >0) {
329             modifiers |= Opcodes.ACC_ABSTRACT;
330         }
331
332         String JavaDoc returnType = null;
333
334         if (isType(TYPE, node)) {
335             returnType = typeName(node);
336             node = node.getNextSibling();
337         }
338
339         String JavaDoc name = identifier(node);
340         if (classNode != null) {
341             if (classNode.getNameWithoutPackage().equals(name)) {
342                 throw new ASTRuntimeException(methodDef, "Invalid constructor format. Try remove the 'def' expression?");
343             }
344         }
345         node = node.getNextSibling();
346
347         assertNodeType(PARAMETERS, node);
348         Parameter[] parameters = parameters(node);
349         node = node.getNextSibling();
350
351         Statement code = null;
352         if ((modifiers & Opcodes.ACC_ABSTRACT) == 0) {
353             if (node==null) {
354                 throw new ASTRuntimeException(methodDef, "You defined a method without body. Try adding a body, or declare it abstract.");
355             }
356             assertNodeType(SLIST, node);
357             code = statementList(node);
358         }
359
360         MethodNode methodNode = new MethodNode(name, modifiers, returnType, parameters, code);
361         methodNode.addAnnotations(annotations);
362         configureAST(methodNode, methodDef);
363         if (classNode != null) {
364             classNode.addMethod(methodNode);
365         }
366         else {
367             output.addMethod(methodNode);
368         }
369     }
370
371     protected void constructorDef(AST constructorDef) {
372         List JavaDoc annotations = new ArrayList JavaDoc();
373         AST node = constructorDef.getFirstChild();
374         int modifiers = Opcodes.ACC_PUBLIC;
375         if (isType(MODIFIERS, node)) {
376             modifiers = modifiers(node, annotations, modifiers);
377             node = node.getNextSibling();
378         }
379
380         assertNodeType(PARAMETERS, node);
381         Parameter[] parameters = parameters(node);
382         node = node.getNextSibling();
383
384         assertNodeType(SLIST, node);
385         Statement code = statementList(node);
386
387         ConstructorNode constructorNode = classNode.addConstructor(modifiers, parameters, code);
388         constructorNode.addAnnotations(annotations);
389         configureAST(constructorNode, constructorDef);
390     }
391
392     protected void fieldDef(AST fieldDef) {
393         List JavaDoc annotations = new ArrayList JavaDoc();
394         AST node = fieldDef.getFirstChild();
395
396         int modifiers = 0;
397         if (isType(MODIFIERS, node)) {
398             modifiers = modifiers(node, annotations, modifiers);
399             node = node.getNextSibling();
400         }
401
402         String JavaDoc type = null;
403         if (isType(TYPE, node)) {
404             type = typeName(node);
405             node = node.getNextSibling();
406         }
407
408         String JavaDoc name = identifier(node);
409         node = node.getNextSibling();
410
411         Expression initialValue = null;
412         if (node != null) {
413             assertNodeType(ASSIGN, node);
414             initialValue = expression(node);
415         }
416
417
418         FieldNode fieldNode = new FieldNode(name, modifiers, type, classNode, initialValue);
419         fieldNode.addAnnotations(annotations);
420         configureAST(fieldNode, fieldDef);
421
422         // lets check for a property annotation first
423
if (fieldNode.getAnnotations("Property") != null) {
424             // lets set the modifiers on the field
425
int fieldModifiers = 0;
426             int flags = Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_VOLATILE | Opcodes.ACC_FINAL;
427
428             // lets pass along any other modifiers we need
429
fieldModifiers |= (modifiers & flags);
430             fieldNode.setModifiers(fieldModifiers);
431
432             if (!hasVisibility(modifiers)) {
433                 modifiers |= Opcodes.ACC_PUBLIC;
434             }
435             PropertyNode propertyNode = new PropertyNode(fieldNode, modifiers, null, null);
436             configureAST(propertyNode, fieldDef);
437             classNode.addProperty(propertyNode);
438         }
439         else {
440             /*
441             if (!hasVisibility(modifiers)) {
442                 modifiers |= Opcodes.ACC_PRIVATE;
443                 fieldNode.setModifiers(modifiers);
444             }
445             */

446             fieldNode.setModifiers(modifiers);
447
448             classNode.addField(fieldNode);
449         }
450     }
451
452     protected String JavaDoc[] interfaces(AST node) {
453         List JavaDoc interfaceList = new ArrayList JavaDoc();
454         for (AST implementNode = node.getFirstChild(); implementNode != null; implementNode = implementNode.getNextSibling()) {
455             interfaceList.add(resolveTypeName(qualifiedName(implementNode)));
456         }
457         String JavaDoc[] interfaces = {};
458         if (!interfaceList.isEmpty()) {
459             interfaces = new String JavaDoc[interfaceList.size()];
460             interfaceList.toArray(interfaces);
461
462         }
463         return interfaces;
464     }
465
466     protected Parameter[] parameters(AST parametersNode) {
467         AST node = parametersNode.getFirstChild();
468         if (node == null) {
469             return Parameter.EMPTY_ARRAY;
470         }
471         else {
472             List JavaDoc parameters = new ArrayList JavaDoc();
473             do {
474                 parameters.add(parameter(node));
475                 node = node.getNextSibling();
476             }
477             while (node != null);
478             Parameter[] answer = new Parameter[parameters.size()];
479             parameters.toArray(answer);
480             return answer;
481         }
482     }
483
484     protected Parameter parameter(AST paramNode) {
485         List JavaDoc annotations = new ArrayList JavaDoc();
486         AST node = paramNode.getFirstChild();
487
488         int modifiers = 0;
489         if (isType(MODIFIERS, node)) {
490             modifiers = modifiers(node, annotations, modifiers);
491             node = node.getNextSibling();
492         }
493
494         String JavaDoc type = null;
495         if (isType(TYPE, node)) {
496             type = typeName(node);
497             node = node.getNextSibling();
498         }
499
500         String JavaDoc name = identifier(node);
501         node = node.getNextSibling();
502         VariableExpression leftExpression = new VariableExpression(name, type);
503         configureAST(leftExpression, paramNode);
504
505         Expression rightExpression = ConstantExpression.NULL;
506         if (node != null) {
507             assertNodeType(ASSIGN, node);
508
509             rightExpression = expression(node.getFirstChild());
510         }
511
512         Parameter parameter = new Parameter(type, name, rightExpression);
513         // TODO
514
//configureAST(parameter,paramNode);
515
//parameter.addAnnotations(annotations);
516
return parameter;
517     }
518
519     protected int modifiers(AST modifierNode, List JavaDoc annotations, int defaultModifiers) {
520         assertNodeType(MODIFIERS, modifierNode);
521
522         boolean access = false;
523         int answer = 0;
524
525         for (AST node = modifierNode.getFirstChild(); node != null; node = node.getNextSibling()) {
526             int type = node.getType();
527             switch (type) {
528                 // annotations
529
case ANNOTATION:
530                     annotations.add(annotation(node));
531                     break;
532
533
534                     // core access scope modifiers
535
case LITERAL_private:
536                     answer = setModifierBit(node, answer, Opcodes.ACC_PRIVATE);
537                     access = setAccessTrue(node, access);
538                     break;
539
540                 case LITERAL_protected:
541                     answer = setModifierBit(node, answer, Opcodes.ACC_PROTECTED);
542                     access = setAccessTrue(node, access);
543                     break;
544
545                 case LITERAL_public:
546                     answer = setModifierBit(node, answer, Opcodes.ACC_PUBLIC);
547                     access = setAccessTrue(node, access);
548                     break;
549
550                     // other modifiers
551
case ABSTRACT:
552                     answer = setModifierBit(node, answer, Opcodes.ACC_ABSTRACT);
553                     break;
554
555                 case FINAL:
556                     answer = setModifierBit(node, answer, Opcodes.ACC_FINAL);
557                     break;
558
559                 case LITERAL_native:
560                     answer = setModifierBit(node, answer, Opcodes.ACC_NATIVE);
561                     break;
562
563                 case LITERAL_static:
564                     answer = setModifierBit(node, answer, Opcodes.ACC_STATIC);
565                     break;
566
567                 case STRICTFP:
568                     answer = setModifierBit(node, answer, Opcodes.ACC_STRICT);
569                     break;
570
571                 case LITERAL_synchronized:
572                     answer = setModifierBit(node, answer, Opcodes.ACC_SYNCHRONIZED);
573                     break;
574
575                 case LITERAL_transient:
576                     answer = setModifierBit(node, answer, Opcodes.ACC_TRANSIENT);
577                     break;
578
579                 case LITERAL_volatile:
580                     answer = setModifierBit(node, answer, Opcodes.ACC_VOLATILE);
581                     break;
582
583                 default:
584                     unknownAST(node);
585             }
586         }
587         if (!access) {
588             answer |= defaultModifiers;
589         }
590         return answer;
591     }
592
593     protected boolean setAccessTrue(AST node, boolean access) {
594         if (!access) {
595             return true;
596         }
597         else {
598             throw new ASTRuntimeException(node, "Cannot specify modifier: " + node.getText() + " when access scope has already been defined");
599         }
600     }
601
602     protected int setModifierBit(AST node, int answer, int bit) {
603         if ((answer & bit) != 0) {
604             throw new ASTRuntimeException(node, "Cannot repeat modifier: " + node.getText());
605         }
606         return answer | bit;
607     }
608
609     protected AnnotationNode annotation(AST annotationNode) {
610         AST node = annotationNode.getFirstChild();
611         String JavaDoc name = identifier(node);
612         AnnotationNode annotatedNode = new AnnotationNode(name);
613         configureAST(annotatedNode, node);
614         while (true) {
615             node = node.getNextSibling();
616             if (isType(ANNOTATION_MEMBER_VALUE_PAIR, node)) {
617                 AST memberNode = node.getFirstChild();
618                 String JavaDoc param = identifier(memberNode);
619                 Expression expression = expression(memberNode.getNextSibling());
620                 annotatedNode.addMember(param, expression);
621             }
622             else {
623                 break;
624             }
625         }
626         return annotatedNode;
627     }
628
629
630
631     // Statements
632
//-------------------------------------------------------------------------
633

634     protected Statement statement(AST node) {
635         Statement statement = null;
636         int type = node.getType();
637         switch (type) {
638             case SLIST:
639             case LITERAL_finally:
640                 statement = statementList(node);
641                 break;
642
643             case METHOD_CALL:
644                 statement = methodCall(node);
645                 break;
646
647             case VARIABLE_DEF:
648                 statement = variableDef(node);
649                 break;
650
651
652             case LABELED_STAT:
653                 statement = labelledStatement(node);
654                 break;
655
656             case LITERAL_assert:
657                 statement = assertStatement(node);
658                 break;
659
660             case LITERAL_break:
661                 statement = breakStatement(node);
662                 break;
663
664             case LITERAL_continue:
665                 statement = continueStatement(node);
666                 break;
667
668             case LITERAL_if:
669                 statement = ifStatement(node);
670                 break;
671
672             case LITERAL_for:
673                 statement = forStatement(node);
674                 break;
675
676             case LITERAL_return:
677                 statement = returnStatement(node);
678                 break;
679
680             case LITERAL_synchronized:
681                 statement = synchronizedStatement(node);
682                 break;
683
684             case LITERAL_switch:
685                 statement = switchStatement(node);
686                 break;
687
688             case LITERAL_with:
689                 statement = withStatement(node);
690                 break;
691
692             case LITERAL_try:
693                 statement = tryStatement(node);
694                 break;
695
696             case LITERAL_throw:
697                 statement = throwStatement(node);
698                 break;
699
700             case LITERAL_while:
701                 statement = whileStatement(node);
702                 break;
703
704             default:
705                 statement = new ExpressionStatement(expression(node));
706         }
707         if (statement != null) {
708             configureAST(statement, node);
709         }
710         return statement;
711     }
712
713     protected Statement statementList(AST code) {
714         return statementListNoChild(code.getFirstChild());
715     }
716
717     protected Statement statementListNoChild(AST node) {
718         BlockStatement block = new BlockStatement();
719         // no need to configureAST(block,node); as node is probably null
720
for (; node != null; node = node.getNextSibling()) {
721             block.addStatement(statement(node));
722         }
723         return block;
724     }
725
726     protected Statement assertStatement(AST assertNode) {
727         AST node = assertNode.getFirstChild();
728         BooleanExpression booleanExpression = booleanExpression(node);
729         Expression messageExpression = null;
730
731         node = node.getNextSibling();
732         if (node != null) {
733             messageExpression = expression(node);
734         }
735         else {
736             messageExpression = ConstantExpression.NULL;
737         }
738         AssertStatement assertStatement = new AssertStatement(booleanExpression, messageExpression);
739         configureAST(assertStatement, assertNode);
740         return assertStatement;
741     }
742
743     protected Statement breakStatement(AST node) {
744         BreakStatement breakStatement = new BreakStatement(label(node));
745         configureAST(breakStatement, node);
746         return breakStatement;
747     }
748
749     protected Statement continueStatement(AST node) {
750         ContinueStatement continueStatement = new ContinueStatement(label(node));
751         configureAST(continueStatement, node);
752         return continueStatement;
753     }
754
755     protected Statement forStatement(AST forNode) {
756         AST inNode = forNode.getFirstChild();
757         AST variableNode = inNode.getFirstChild();
758         AST collectionNode = variableNode.getNextSibling();
759
760         Type type = OBJECT_TYPE;
761         if (isType(VARIABLE_DEF, variableNode)) {
762             AST typeNode = variableNode.getFirstChild();
763             assertNodeType(TYPE, typeNode);
764
765             type = type(typeNode);
766             variableNode = typeNode.getNextSibling();
767         }
768         String JavaDoc variable = identifier(variableNode);
769
770         Expression collectionExpression = expression(collectionNode);
771         Statement block = statement(inNode.getNextSibling());
772
773         ForStatement forStatement = new ForStatement(variable, type, collectionExpression, block);
774         configureAST(forStatement, forNode);
775         return forStatement;
776     }
777
778     protected Statement ifStatement(AST ifNode) {
779         AST node = ifNode.getFirstChild();
780         assertNodeType(EXPR, node);
781         BooleanExpression booleanExpression = booleanExpression(node);
782
783         node = node.getNextSibling();
784         Statement ifBlock = statement(node);
785
786         Statement elseBlock = EmptyStatement.INSTANCE;
787         node = node.getNextSibling();
788         if (node != null) {
789             elseBlock = statement(node);
790         }
791         IfStatement ifStatement = new IfStatement(booleanExpression, ifBlock, elseBlock);
792         configureAST(ifStatement, ifNode);
793         return ifStatement;
794     }
795
796     protected Statement labelledStatement(AST labelNode) {
797         AST node = labelNode.getFirstChild();
798         String JavaDoc label = identifier(node);
799         Statement statement = statement(node.getNextSibling());
800         statement.setStatementLabel(label);
801         return statement;
802     }
803
804     protected Statement methodCall(AST code) {
805         Expression expression = methodCallExpression(code);
806         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
807         configureAST(expressionStatement, code);
808         return expressionStatement;
809     }
810
811     protected Statement variableDef(AST variableDef) {
812         AST node = variableDef.getFirstChild();
813         String JavaDoc type = null;
814         if (isType(MODIFIERS, node)) {
815             node = node.getNextSibling();
816         }
817         if (isType(TYPE, node)) {
818             type = typeName(node);
819             node = node.getNextSibling();
820         }
821
822         String JavaDoc name = identifier(node);
823         node = node.getNextSibling();
824
825         VariableExpression leftExpression = new VariableExpression(name, type);
826         configureAST(leftExpression, variableDef);
827
828         Expression rightExpression = ConstantExpression.NULL;
829         if (node != null) {
830             assertNodeType(ASSIGN, node);
831
832             rightExpression = expression(node.getFirstChild());
833         }
834         Token token = makeToken(Types.ASSIGN, variableDef);
835
836         // TODO should we have a variable declaration statement?
837
DeclarationExpression expression = new DeclarationExpression(leftExpression, token, rightExpression);
838         configureAST(expression, variableDef);
839         ExpressionStatement expressionStatement = new ExpressionStatement(expression);
840         configureAST(expressionStatement, variableDef);
841         return expressionStatement;
842     }
843
844     protected Statement returnStatement(AST node) {
845         AST exprNode = node.getFirstChild();
846
847         // This will pick up incorrect sibling node if 'node' is a plain 'return'
848
//
849
//if (exprNode == null) {
850
// exprNode = node.getNextSibling();
851
//}
852
if (exprNode != null) {
853             Expression expression = expression(exprNode);
854             if (expression instanceof ConstantExpression) {
855                 ConstantExpression constantExpr = (ConstantExpression) expression;
856                 if (constantExpr.getValue() == null) {
857                     return ReturnStatement.RETURN_NULL_OR_VOID;
858                 }
859             }
860             ReturnStatement returnStatement = new ReturnStatement(expression);
861             configureAST(returnStatement, node);
862             return returnStatement;
863         }
864         else {
865             return ReturnStatement.RETURN_NULL_OR_VOID;
866         }
867     }
868
869     protected Statement switchStatement(AST switchNode) {
870         AST node = switchNode.getFirstChild();
871         Expression expression = expression(node);
872         Statement defaultStatement = EmptyStatement.INSTANCE;
873
874         List JavaDoc list = new ArrayList JavaDoc();
875         for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node.getNextSibling()) {
876             AST child = node.getFirstChild();
877             if (isType(LITERAL_case, child)) {
878                 list.add(caseStatement(child));
879             }
880             else {
881                 defaultStatement = statement(child.getNextSibling());
882             }
883         }
884         if (node != null) {
885             unknownAST(node);
886         }
887         SwitchStatement switchStatement = new SwitchStatement(expression, list, defaultStatement);
888         configureAST(switchStatement, switchNode);
889         return switchStatement;
890     }
891
892     protected CaseStatement caseStatement(AST node) {
893         Expression expression = expression(node.getFirstChild());
894         AST nextSibling = node.getNextSibling();
895         Statement statement = EmptyStatement.INSTANCE;
896         if (!isType(LITERAL_default, nextSibling)) {
897              statement = statement(nextSibling);
898         }
899         CaseStatement answer = new CaseStatement(expression, statement);
900         configureAST(answer, node);
901         return answer;
902     }
903
904     protected Statement synchronizedStatement(AST syncNode) {
905         AST node = syncNode.getFirstChild();
906         Expression expression = expression(node);
907         Statement code = statement(node.getNextSibling());
908         SynchronizedStatement synchronizedStatement = new SynchronizedStatement(expression, code);
909         configureAST(synchronizedStatement, syncNode);
910         return synchronizedStatement;
911     }
912
913     protected Statement throwStatement(AST node) {
914         AST expressionNode = node.getFirstChild();
915         if (expressionNode == null) {
916             expressionNode = node.getNextSibling();
917         }
918         if (expressionNode == null) {
919             throw new ASTRuntimeException(node, "No expression available");
920         }
921         ThrowStatement throwStatement = new ThrowStatement(expression(expressionNode));
922         configureAST(throwStatement, node);
923         return throwStatement;
924     }
925
926     protected Statement tryStatement(AST tryStatementNode) {
927         AST tryNode = tryStatementNode.getFirstChild();
928         Statement tryStatement = statement(tryNode);
929         Statement finallyStatement = EmptyStatement.INSTANCE;
930         AST node = tryNode.getNextSibling();
931
932         // lets do the catch nodes
933
List JavaDoc catches = new ArrayList JavaDoc();
934         for (; node != null && isType(LITERAL_catch, node); node = node.getNextSibling()) {
935             catches.add(catchStatement(node));
936         }
937
938         if (isType(LITERAL_finally, node)) {
939             finallyStatement = statement(node);
940             node = node.getNextSibling();
941         }
942
943         TryCatchStatement tryCatchStatement = new TryCatchStatement(tryStatement, finallyStatement);
944         configureAST(tryCatchStatement, tryStatementNode);
945         for (Iterator JavaDoc iter = catches.iterator(); iter.hasNext();) {
946             CatchStatement statement = (CatchStatement) iter.next();
947             tryCatchStatement.addCatch(statement);
948         }
949         return tryCatchStatement;
950     }
951
952     protected CatchStatement catchStatement(AST catchNode) {
953         AST node = catchNode.getFirstChild();
954         Parameter parameter = parameter(node);
955         String JavaDoc exceptionType = parameter.getType();
956         String JavaDoc variable = parameter.getName();
957         node = node.getNextSibling();
958         Statement code = statement(node);
959         CatchStatement answer = new CatchStatement(exceptionType, variable, code);
960         configureAST(answer, catchNode);
961         return answer;
962     }
963
964     protected Statement whileStatement(AST whileNode) {
965         AST node = whileNode.getFirstChild();
966         assertNodeType(EXPR, node);
967         BooleanExpression booleanExpression = booleanExpression(node);
968
969         node = node.getNextSibling();
970         Statement block = statement(node);
971         WhileStatement whileStatement = new WhileStatement(booleanExpression, block);
972         configureAST(whileStatement, whileNode);
973         return whileStatement;
974     }
975
976     protected Statement withStatement(AST node) {
977         notImplementedYet(node);
978         return null; /** TODO */
979     }
980
981
982
983     // Expressions
984
//-------------------------------------------------------------------------
985

986     protected Expression expression(AST node) {
987         Expression expression = expressionSwitch(node);
988         configureAST(expression, node);
989         return expression;
990     }
991
992     protected Expression expressionSwitch(AST node) {
993         int type = node.getType();
994         switch (type) {
995             case EXPR:
996                 return expression(node.getFirstChild());
997
998             case ELIST:
999                 return expressionList(node);
1000
1001            case SLIST:
1002                return blockExpression(node);
1003
1004            case CLOSED_BLOCK:
1005                return closureExpression(node);
1006
1007            case SUPER_CTOR_CALL:
1008                return superMethodCallExpression(node);
1009
1010            case METHOD_CALL:
1011                return methodCallExpression(node);
1012
1013            case LITERAL_new:
1014                return constructorCallExpression(node.getFirstChild());
1015
1016            case CTOR_CALL:
1017                return constructorCallExpression(node);
1018
1019            case QUESTION:
1020                return ternaryExpression(node);
1021
1022            case OPTIONAL_DOT:
1023            case SPREAD_DOT:
1024            case DOT:
1025                return dotExpression(node);
1026
1027            case IDENT:
1028            case LITERAL_boolean:
1029            case LITERAL_byte:
1030            case LITERAL_char:
1031            case LITERAL_double:
1032            case LITERAL_float:
1033            case LITERAL_int:
1034            case LITERAL_long:
1035            case LITERAL_short:
1036                return variableExpression(node);
1037
1038            case LIST_CONSTRUCTOR:
1039                return listExpression(node);
1040
1041            case MAP_CONSTRUCTOR:
1042                return mapExpression(node);
1043
1044            case LABELED_ARG:
1045                return mapEntryExpression(node);
1046
1047            case SPREAD_ARG:
1048                return spreadExpression(node);
1049
1050            case SPREAD_MAP_ARG:
1051                return spreadMapExpression(node);
1052
1053            // commented out of groovy.g due to non determinisms
1054
//case MEMBER_POINTER_DEFAULT:
1055
// return defaultMethodPointerExpression(node);
1056

1057            case MEMBER_POINTER:
1058                return methodPointerExpression(node);
1059
1060            case INDEX_OP:
1061                return indexExpression(node);
1062
1063            case LITERAL_instanceof:
1064                return instanceofExpression(node);
1065
1066            case LITERAL_as:
1067                return asExpression(node);
1068
1069            case TYPECAST:
1070                return castExpression(node);
1071
1072                // literals
1073

1074            case LITERAL_true:
1075                return ConstantExpression.TRUE;
1076
1077            case LITERAL_false:
1078                return ConstantExpression.FALSE;
1079
1080            case LITERAL_null:
1081                return ConstantExpression.NULL;
1082
1083            case STRING_LITERAL:
1084                ConstantExpression constantExpression = new ConstantExpression(node.getText());
1085                configureAST(constantExpression, node);
1086                return constantExpression;
1087
1088            case STRING_CONSTRUCTOR:
1089                return gstring(node);
1090
1091            case NUM_DOUBLE:
1092            case NUM_FLOAT:
1093            case NUM_BIG_DECIMAL:
1094                return decimalExpression(node);
1095
1096            case NUM_BIG_INT:
1097            case NUM_INT:
1098            case NUM_LONG:
1099                return integerExpression(node);
1100
1101            case LITERAL_this:
1102                return VariableExpression.THIS_EXPRESSION;
1103
1104            case LITERAL_super:
1105                return VariableExpression.SUPER_EXPRESSION;
1106
1107
1108                // Unary expressions
1109
case LNOT:
1110                NotExpression notExpression = new NotExpression(expression(node.getFirstChild()));
1111                configureAST(notExpression, node);
1112                return notExpression;
1113
1114            case UNARY_MINUS:
1115                return negateExpression(node);
1116
1117            case BNOT:
1118                BitwiseNegExpression bitwiseNegExpression = new BitwiseNegExpression(expression(node.getFirstChild()));
1119                configureAST(bitwiseNegExpression, node);
1120                return bitwiseNegExpression;
1121
1122            case UNARY_PLUS:
1123                return expression(node.getFirstChild());
1124
1125
1126                // Prefix expressions
1127
case INC:
1128                return prefixExpression(node, Types.PLUS_PLUS);
1129
1130            case DEC:
1131                return prefixExpression(node, Types.MINUS_MINUS);
1132
1133                // Postfix expressions
1134
case POST_INC:
1135                return postfixExpression(node, Types.PLUS_PLUS);
1136
1137            case POST_DEC:
1138                return postfixExpression(node, Types.MINUS_MINUS);
1139
1140
1141                // Binary expressions
1142

1143            case ASSIGN:
1144                return binaryExpression(Types.ASSIGN, node);
1145
1146            case EQUAL:
1147                return binaryExpression(Types.COMPARE_EQUAL, node);
1148
1149            case NOT_EQUAL:
1150                return binaryExpression(Types.COMPARE_NOT_EQUAL, node);
1151
1152            case COMPARE_TO:
1153                return binaryExpression(Types.COMPARE_TO, node);
1154
1155            case LE:
1156                return binaryExpression(Types.COMPARE_LESS_THAN_EQUAL, node);
1157
1158            case LT:
1159                return binaryExpression(Types.COMPARE_LESS_THAN, node);
1160
1161            case GT:
1162                return binaryExpression(Types.COMPARE_GREATER_THAN, node);
1163
1164            case GE:
1165                return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL, node);
1166
1167                /**
1168                 * TODO treble equal?
1169                 return binaryExpression(Types.COMPARE_IDENTICAL, node);
1170
1171                 case ???:
1172                 return binaryExpression(Types.LOGICAL_AND_EQUAL, node);
1173
1174                 case ???:
1175                 return binaryExpression(Types.LOGICAL_OR_EQUAL, node);
1176
1177                 */

1178
1179            case LAND:
1180                return binaryExpression(Types.LOGICAL_AND, node);
1181
1182            case LOR:
1183                return binaryExpression(Types.LOGICAL_OR, node);
1184
1185            case BAND:
1186                return binaryExpression(Types.BITWISE_AND, node);
1187
1188            case BAND_ASSIGN:
1189                return binaryExpression(Types.BITWISE_AND_EQUAL, node);
1190
1191            case BOR:
1192                return binaryExpression(Types.BITWISE_OR, node);
1193
1194            case BOR_ASSIGN:
1195                return binaryExpression(Types.BITWISE_OR_EQUAL, node);
1196
1197            case BXOR:
1198                return binaryExpression(Types.BITWISE_XOR, node);
1199
1200            case BXOR_ASSIGN:
1201                return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
1202
1203
1204            case PLUS:
1205                return binaryExpression(Types.PLUS, node);
1206
1207            case PLUS_ASSIGN:
1208                return binaryExpression(Types.PLUS_EQUAL, node);
1209
1210
1211            case MINUS:
1212                return binaryExpression(Types.MINUS, node);
1213
1214            case MINUS_ASSIGN:
1215                return binaryExpression(Types.MINUS_EQUAL, node);
1216
1217
1218            case STAR:
1219                return binaryExpression(Types.MULTIPLY, node);
1220
1221            case STAR_ASSIGN:
1222                return binaryExpression(Types.MULTIPLY_EQUAL, node);
1223
1224
1225            case STAR_STAR:
1226                return binaryExpression(Types.POWER, node);
1227
1228            case STAR_STAR_ASSIGN:
1229                return binaryExpression(Types.POWER_EQUAL, node);
1230
1231
1232            case DIV:
1233                return binaryExpression(Types.DIVIDE, node);
1234
1235            case DIV_ASSIGN:
1236                return binaryExpression(Types.DIVIDE_EQUAL, node);
1237
1238
1239            case MOD:
1240                return binaryExpression(Types.MOD, node);
1241
1242            case MOD_ASSIGN:
1243                return binaryExpression(Types.MOD_EQUAL, node);
1244
1245            case SL:
1246                return binaryExpression(Types.LEFT_SHIFT, node);
1247
1248            case SL_ASSIGN:
1249                return binaryExpression(Types.LEFT_SHIFT_EQUAL, node);
1250
1251            case SR:
1252                return binaryExpression(Types.RIGHT_SHIFT, node);
1253
1254            case SR_ASSIGN:
1255                return binaryExpression(Types.RIGHT_SHIFT_EQUAL, node);
1256
1257            case BSR:
1258                return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED, node);
1259
1260            case BSR_ASSIGN:
1261                return binaryExpression(Types.RIGHT_SHIFT_UNSIGNED_EQUAL, node);
1262
1263                // Regex
1264
case REGEX_FIND:
1265                return binaryExpression(Types.FIND_REGEX, node);
1266
1267            case REGEX_MATCH:
1268                return binaryExpression(Types.MATCH_REGEX, node);
1269
1270
1271                // Ranges
1272
case RANGE_INCLUSIVE:
1273                return rangeExpression(node, true);
1274
1275            case RANGE_EXCLUSIVE:
1276                return rangeExpression(node, false);
1277
1278            default:
1279                unknownAST(node);
1280        }
1281        return null;
1282    }
1283
1284    protected Expression ternaryExpression(AST ternaryNode) {
1285        AST node = ternaryNode.getFirstChild();
1286        BooleanExpression booleanExpression = booleanExpression(node);
1287        node = node.getNextSibling();
1288        Expression left = expression(node);
1289        Expression right = expression(node.getNextSibling());
1290        TernaryExpression ternaryExpression = new TernaryExpression(booleanExpression, left, right);
1291        configureAST(ternaryExpression, ternaryNode);
1292        return ternaryExpression;
1293    }
1294
1295    protected Expression variableExpression(AST node) {
1296        String JavaDoc text = node.getText();
1297
1298        // TODO we might wanna only try to resolve the name if we are
1299
// on the left hand side of an expression or before a dot?
1300
String JavaDoc newText = resolveTypeName(text, false);
1301        if (newText == null) {
1302            VariableExpression variableExpression = new VariableExpression(text);
1303            configureAST(variableExpression, node);
1304            return variableExpression;
1305        }
1306        else {
1307            ClassExpression classExpression = new ClassExpression(newText);
1308            configureAST(classExpression, node);
1309            return classExpression;
1310        }
1311    }
1312
1313    protected Expression rangeExpression(AST rangeNode, boolean inclusive) {
1314        AST node = rangeNode.getFirstChild();
1315        Expression left = expression(node);
1316        Expression right = expression(node.getNextSibling());
1317        RangeExpression rangeExpression = new RangeExpression(left, right, inclusive);
1318        configureAST(rangeExpression, rangeNode);
1319        return rangeExpression;
1320    }
1321
1322    protected Expression spreadExpression(AST node) {
1323        AST exprNode = node.getFirstChild();
1324        AST listNode = exprNode.getFirstChild();
1325        Expression right = expression(listNode);
1326        SpreadExpression spreadExpression = new SpreadExpression(right);
1327        configureAST(spreadExpression, node);
1328        return spreadExpression;
1329    }
1330
1331    protected Expression spreadMapExpression(AST node) {
1332        AST exprNode = node.getFirstChild();
1333        Expression expr = expression(exprNode);
1334        SpreadMapExpression spreadMapExpression = new SpreadMapExpression(expr);
1335        configureAST(spreadMapExpression, node);
1336        return spreadMapExpression;
1337    }
1338
1339    protected Expression methodPointerExpression(AST node) {
1340        AST exprNode = node.getFirstChild();
1341        String JavaDoc methodName = identifier(exprNode.getNextSibling());
1342        Expression expression = expression(exprNode);
1343        MethodPointerExpression methodPointerExpression = new MethodPointerExpression(expression, methodName);
1344        configureAST(methodPointerExpression, node);
1345        return methodPointerExpression;
1346    }
1347
1348/* commented out due to groovy.g non-determinisms
1349  protected Expression defaultMethodPointerExpression(AST node) {
1350        AST exprNode = node.getFirstChild();
1351        String methodName = exprNode.toString();
1352        MethodPointerExpression methodPointerExpression = new MethodPointerExpression(null, methodName);
1353        configureAST(methodPointerExpression, node);
1354        return methodPointerExpression;
1355    }
1356*/

1357
1358    protected Expression listExpression(AST listNode) {
1359        List JavaDoc expressions = new ArrayList JavaDoc();
1360        AST elist = listNode.getFirstChild();
1361        assertNodeType(ELIST, elist);
1362
1363        for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1364            // check for stray labeled arguments:
1365
switch (node.getType()) {
1366            case LABELED_ARG: assertNodeType(COMMA, node); break; // helpful error?
1367
case SPREAD_MAP_ARG: assertNodeType(SPREAD_ARG, node); break; // helpful error
1368
}
1369            expressions.add(expression(node));
1370        }
1371        ListExpression listExpression = new ListExpression(expressions);
1372        configureAST(listExpression, listNode);
1373        return listExpression;
1374    }
1375
1376    /**
1377     * Typically only used for map constructors I think?
1378     */

1379    protected Expression mapExpression(AST mapNode) {
1380        List JavaDoc expressions = new ArrayList JavaDoc();
1381        AST elist = mapNode.getFirstChild();
1382        if (elist != null) { // totally empty in the case of [:]
1383
assertNodeType(ELIST, elist);
1384            for (AST node = elist.getFirstChild(); node != null; node = node.getNextSibling()) {
1385                switch (node.getType()) {
1386                case LABELED_ARG:
1387                case SPREAD_MAP_ARG:
1388                    break; // legal cases
1389
case SPREAD_ARG:
1390                    assertNodeType(SPREAD_MAP_ARG, node); break; // helpful error
1391
default:
1392                    assertNodeType(LABELED_ARG, node); break; // helpful error
1393
}
1394                expressions.add(mapEntryExpression(node));
1395            }
1396        }
1397        MapExpression mapExpression = new MapExpression(expressions);
1398        configureAST(mapExpression, mapNode);
1399        return mapExpression;
1400    }
1401
1402    protected MapEntryExpression mapEntryExpression(AST node) {
1403        if (node.getType() == SPREAD_MAP_ARG) {
1404            AST rightNode = node.getFirstChild();
1405            Expression keyExpression = spreadMapExpression(node);
1406            Expression rightExpression = expression(rightNode);
1407            MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
1408            configureAST(mapEntryExpression, node);
1409            return mapEntryExpression;
1410        }
1411        else {
1412            AST keyNode = node.getFirstChild();
1413            Expression keyExpression = expression(keyNode);
1414            AST valueNode = keyNode.getNextSibling();
1415            Expression valueExpression = expression(valueNode);
1416            MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, valueExpression);
1417            configureAST(mapEntryExpression, node);
1418            return mapEntryExpression;
1419        }
1420    }
1421
1422
1423    protected Expression instanceofExpression(AST node) {
1424        AST leftNode = node.getFirstChild();
1425        Expression leftExpression = expression(leftNode);
1426
1427        AST rightNode = leftNode.getNextSibling();
1428        String JavaDoc typeName = resolvedName(rightNode);
1429        assertTypeNotNull(typeName, rightNode);
1430
1431        Expression rightExpression = new ClassExpression(typeName);
1432        configureAST(rightExpression, rightNode);
1433        BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.KEYWORD_INSTANCEOF, node), rightExpression);
1434        configureAST(binaryExpression, node);
1435        return binaryExpression;
1436    }
1437
1438    protected void assertTypeNotNull(String JavaDoc typeName, AST rightNode) {
1439        if (typeName == null) {
1440            throw new ASTRuntimeException(rightNode, "No type available for: " + qualifiedName(rightNode));
1441        }
1442    }
1443
1444    protected Expression asExpression(AST node) {
1445        AST leftNode = node.getFirstChild();
1446        Expression leftExpression = expression(leftNode);
1447
1448        AST rightNode = leftNode.getNextSibling();
1449        String JavaDoc typeName = resolvedName(rightNode);
1450
1451        return CastExpression.asExpression(typeName, leftExpression);
1452    }
1453
1454    protected Expression castExpression(AST castNode) {
1455        AST node = castNode.getFirstChild();
1456        String JavaDoc typeName = resolvedName(node);
1457        assertTypeNotNull(typeName, node);
1458
1459        AST expressionNode = node.getNextSibling();
1460        Expression expression = expression(expressionNode);
1461
1462        CastExpression castExpression = new CastExpression(typeName, expression);
1463        configureAST(castExpression, castNode);
1464        return castExpression;
1465    }
1466
1467
1468    protected Expression indexExpression(AST indexNode) {
1469        AST leftNode = indexNode.getFirstChild();
1470        Expression leftExpression = expression(leftNode);
1471
1472        AST rightNode = leftNode.getNextSibling();
1473        Expression rightExpression = expression(rightNode);
1474
1475        BinaryExpression binaryExpression = new BinaryExpression(leftExpression, makeToken(Types.LEFT_SQUARE_BRACKET, indexNode), rightExpression);
1476        configureAST(binaryExpression, indexNode);
1477        return binaryExpression;
1478    }
1479
1480    protected Expression binaryExpression(int type, AST node) {
1481        Token token = makeToken(type, node);
1482
1483        AST leftNode = node.getFirstChild();
1484        Expression leftExpression = expression(leftNode);
1485
1486        AST rightNode = leftNode.getNextSibling();
1487        if (rightNode == null) {
1488            return leftExpression;
1489        }
1490
1491        if (Types.ofType(type, Types.ASSIGNMENT_OPERATOR)) {
1492            if (leftExpression instanceof VariableExpression || leftExpression instanceof PropertyExpression
1493                                                             || leftExpression instanceof FieldExpression
1494                                                             || leftExpression instanceof DeclarationExpression) {
1495                // Do nothing.
1496
}
1497            else if (leftExpression instanceof ConstantExpression) {
1498                throw new ASTRuntimeException(node, "\n[" + ((ConstantExpression) leftExpression).getValue() + "] is a constant expression, but it should be a variable expression");
1499            }
1500            else if (leftExpression instanceof BinaryExpression) {
1501                Expression leftexp = ((BinaryExpression) leftExpression).getLeftExpression();
1502                int lefttype = ((BinaryExpression) leftExpression).getOperation().getType();
1503                if (!Types.ofType(lefttype, Types.ASSIGNMENT_OPERATOR) && lefttype != Types.LEFT_SQUARE_BRACKET) {
1504                    throw new ASTRuntimeException(node, "\n" + ((BinaryExpression) leftExpression).getText() + " is a binary expression, but it should be a variable expression");
1505                }
1506            }
1507            else if (leftExpression instanceof GStringExpression) {
1508                throw new ASTRuntimeException(node, "\n\"" + ((GStringExpression) leftExpression).getText() + "\" is a GString expression, but it should be a variable expression");
1509            }
1510            else if (leftExpression instanceof MethodCallExpression) {
1511                throw new ASTRuntimeException(node, "\n\"" + ((MethodCallExpression) leftExpression).getText() + "\" is a method call expression, but it should be a variable expression");
1512            }
1513            else if (leftExpression instanceof MapExpression) {
1514                throw new ASTRuntimeException(node, "\n'" + ((MapExpression) leftExpression).getText() + "' is a map expression, but it should be a variable expression");
1515            }
1516            else {
1517                throw new ASTRuntimeException(node, "\n" + leftExpression.getClass() + ", with its value '" + leftExpression.getText() + "', is a bad expression as the LSH of an assignment operator");
1518            }
1519        }
1520        /*if (rightNode == null) {
1521            throw new NullPointerException("No rightNode associated with binary expression");
1522        }*/

1523        Expression rightExpression = expression(rightNode);
1524        BinaryExpression binaryExpression = new BinaryExpression(leftExpression, token, rightExpression);
1525        configureAST(binaryExpression, node);
1526        return binaryExpression;
1527    }
1528
1529    protected Expression prefixExpression(AST node, int token) {
1530        Expression expression = expression(node.getFirstChild());
1531        PrefixExpression prefixExpression = new PrefixExpression(makeToken(token, node), expression);
1532        configureAST(prefixExpression, node);
1533        return prefixExpression;
1534    }
1535
1536    protected Expression postfixExpression(AST node, int token) {
1537        Expression expression = expression(node.getFirstChild());
1538        PostfixExpression postfixExpression = new PostfixExpression(expression, makeToken(token, node));
1539        configureAST(postfixExpression, node);
1540        return postfixExpression;
1541    }
1542
1543    protected BooleanExpression booleanExpression(AST node) {
1544        BooleanExpression booleanExpression = new BooleanExpression(expression(node));
1545        configureAST(booleanExpression, node);
1546        return booleanExpression;
1547    }
1548
1549    protected Expression dotExpression(AST node) {
1550        // lets decide if this is a propery invocation or a method call
1551
AST leftNode = node.getFirstChild();
1552        if (leftNode != null) {
1553            AST identifierNode = leftNode.getNextSibling();
1554            if (identifierNode != null) {
1555                Expression leftExpression = expression(leftNode);
1556                if (isType(SELECT_SLOT, identifierNode)) {
1557                    String JavaDoc field = identifier(identifierNode.getFirstChild());
1558                    AttributeExpression attributeExpression = new AttributeExpression(leftExpression, field, node.getType() != DOT);
1559                    if (node.getType() == SPREAD_DOT) {
1560                        attributeExpression.setSpreadSafe(true);
1561                    }
1562                    configureAST(attributeExpression, node);
1563                    return attributeExpression;
1564                }
1565                String JavaDoc property = identifier(identifierNode);
1566                PropertyExpression propertyExpression = new PropertyExpression(leftExpression, property, node.getType() != DOT);
1567                if (node.getType() == SPREAD_DOT) {
1568                    propertyExpression.setSpreadSafe(true);
1569                }
1570                configureAST(propertyExpression, node);
1571                return propertyExpression;
1572            }
1573        }
1574        return methodCallExpression(node);
1575    }
1576
1577    protected Expression superMethodCallExpression(AST methodCallNode) {
1578        AST node = methodCallNode.getFirstChild();
1579
1580        String JavaDoc name = "super";
1581        Expression objectExpression = VariableExpression.SUPER_EXPRESSION;
1582
1583        Expression arguments = arguments(node);
1584        MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
1585        configureAST(expression, methodCallNode);
1586        return expression;
1587    }
1588
1589
1590    protected Expression methodCallExpression(AST methodCallNode) {
1591        AST node = methodCallNode.getFirstChild();
1592        /* // Bad idea, since foo(1)(2) is valid Groovy for foo(1).call(2).
1593        if (isType(METHOD_CALL, node)) {
1594            // sometimes method calls get wrapped in method calls for some wierd reason
1595            return methodCallExpression(node);
1596        }
1597        */

1598
1599        Expression objectExpression;
1600        AST selector;
1601        AST elist = node.getNextSibling();
1602        boolean safe = isType(OPTIONAL_DOT, node);
1603        boolean spreadSafe = isType(SPREAD_DOT, node);
1604        if (isType(DOT, node) || safe || spreadSafe) {
1605            AST objectNode = node.getFirstChild();
1606            objectExpression = expression(objectNode);
1607            selector = objectNode.getNextSibling();
1608        } else if (isType(IDENT, node)) {
1609            objectExpression = VariableExpression.THIS_EXPRESSION;
1610            selector = node;
1611
1612        } else {
1613            objectExpression = expression(node);
1614            selector = null; // implicit "call"
1615
}
1616
1617        String JavaDoc name = null;
1618        if (selector == null) {
1619            name = "call";
1620        } else if (isType(LITERAL_super, selector)) {
1621            name = "super";
1622            if (objectExpression == VariableExpression.THIS_EXPRESSION) {
1623                objectExpression = VariableExpression.SUPER_EXPRESSION;
1624            }
1625        }
1626        else if (isPrimitiveTypeLiteral(selector)) {
1627            throw new ASTRuntimeException(selector, "Primitive type literal: " + selector.getText()
1628                    + " cannot be used as a method name");
1629        }
1630        else {
1631            name = identifier(selector);
1632        }
1633
1634        Expression arguments = arguments(elist);
1635        MethodCallExpression expression = new MethodCallExpression(objectExpression, name, arguments);
1636        boolean implicitThis = (objectExpression == VariableExpression.THIS_EXPRESSION);
1637        implicitThis = implicitThis || (objectExpression == VariableExpression.SUPER_EXPRESSION);
1638        expression.setSafe(safe);
1639        expression.setSpreadSafe(spreadSafe);
1640        expression.setImplicitThis(implicitThis);
1641        configureAST(expression, methodCallNode);
1642        return expression;
1643    }
1644
1645    protected Expression constructorCallExpression(AST node) {
1646        if (isType(CTOR_CALL, node) || isType(LITERAL_new, node)) {
1647            node = node.getFirstChild();
1648        }
1649        AST constructorCallNode = node;
1650
1651        String JavaDoc name = resolvedName(node);
1652        AST elist = node.getNextSibling();
1653
1654        if (isType(ARRAY_DECLARATOR, elist)) {
1655            AST expressionNode = elist.getFirstChild();
1656            if (expressionNode == null) {
1657                throw new ASTRuntimeException(elist, "No expression for the array constructor call");
1658            }
1659            Expression size = expression(expressionNode);
1660            ArrayExpression arrayExpression = new ArrayExpression(name, size);
1661            configureAST(arrayExpression, node);
1662            return arrayExpression;
1663        }
1664        Expression arguments = arguments(elist);
1665        ConstructorCallExpression expression = new ConstructorCallExpression(name, arguments);
1666        configureAST(expression, constructorCallNode);
1667        return expression;
1668    }
1669
1670    protected Expression arguments(AST elist) {
1671        List JavaDoc expressionList = new ArrayList JavaDoc();
1672        // FIXME: all labeled arguments should follow any unlabeled arguments
1673
boolean namedArguments = false;
1674        for (AST node = elist; node != null; node = node.getNextSibling()) {
1675            if (isType(ELIST, node)) {
1676                for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1677                    namedArguments |= addArgumentExpression(child, expressionList);
1678                }
1679            }
1680            else {
1681                namedArguments |= addArgumentExpression(node, expressionList);
1682            }
1683        }
1684        if (namedArguments) {
1685            if (!expressionList.isEmpty()) {
1686                // lets remove any non-MapEntryExpression instances
1687
// such as if the last expression is a ClosureExpression
1688
// so lets wrap the named method calls in a Map expression
1689
List JavaDoc argumentList = new ArrayList JavaDoc();
1690                for (Iterator JavaDoc iter = expressionList.iterator(); iter.hasNext();) {
1691                    Expression expression = (Expression) iter.next();
1692                    if (!(expression instanceof MapEntryExpression)) {
1693                        argumentList.add(expression);
1694                    }
1695                }
1696                if (!argumentList.isEmpty()) {
1697                    expressionList.removeAll(argumentList);
1698                    MapExpression mapExpression = new MapExpression(expressionList);
1699                    configureAST(mapExpression, elist);
1700                    argumentList.add(0, mapExpression);
1701                    ArgumentListExpression argumentListExpression = new ArgumentListExpression(argumentList);
1702                    configureAST(argumentListExpression, elist);
1703                    return argumentListExpression;
1704                }
1705            }
1706            NamedArgumentListExpression namedArgumentListExpression = new NamedArgumentListExpression(expressionList);
1707            configureAST(namedArgumentListExpression, elist);
1708            return namedArgumentListExpression;
1709        }
1710        else {
1711            ArgumentListExpression argumentListExpression = new ArgumentListExpression(expressionList);
1712            configureAST(argumentListExpression, elist);
1713            return argumentListExpression;
1714        }
1715    }
1716
1717    protected boolean addArgumentExpression(AST node, List JavaDoc expressionList) {
1718        if (node.getType() == SPREAD_MAP_ARG) {
1719            AST rightNode = node.getFirstChild();
1720            Expression keyExpression = spreadMapExpression(node);
1721            Expression rightExpression = expression(rightNode);
1722            MapEntryExpression mapEntryExpression = new MapEntryExpression(keyExpression, rightExpression);
1723            expressionList.add(mapEntryExpression);
1724            return true;
1725        }
1726        else {
1727            Expression expression = expression(node);
1728            expressionList.add(expression);
1729            return expression instanceof MapEntryExpression;
1730        }
1731    }
1732
1733    protected Expression expressionList(AST node) {
1734        List JavaDoc expressionList = new ArrayList JavaDoc();
1735        for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
1736            expressionList.add(expression(child));
1737        }
1738        if (expressionList.size() == 1) {
1739            return (Expression) expressionList.get(0);
1740        }
1741        else {
1742            ListExpression listExpression = new ListExpression(expressionList);
1743            configureAST(listExpression, node);
1744            return listExpression;
1745        }
1746    }
1747
1748    protected ClosureExpression closureExpression(AST node) {
1749        AST paramNode = node.getFirstChild();
1750        Parameter[] parameters = Parameter.EMPTY_ARRAY;
1751        AST codeNode = paramNode;
1752        if (isType(PARAMETERS, paramNode) || isType(IMPLICIT_PARAMETERS, paramNode)) {
1753            parameters = parameters(paramNode);
1754            codeNode = paramNode.getNextSibling();
1755        }
1756        Statement code = statementListNoChild(codeNode);
1757        ClosureExpression closureExpression = new ClosureExpression(parameters, code);
1758        configureAST(closureExpression, node);
1759        return closureExpression;
1760    }
1761
1762    protected Expression blockExpression(AST node) {
1763        AST codeNode = node.getFirstChild();
1764        if (codeNode == null) return ConstantExpression.NULL;
1765        if (codeNode.getType() == EXPR && codeNode.getNextSibling() == null) {
1766            // Simplify common case of {expr} to expr.
1767
return expression(codeNode);
1768        }
1769        Parameter[] parameters = Parameter.EMPTY_ARRAY;
1770        Statement code = statementListNoChild(codeNode);
1771        ClosureExpression closureExpression = new ClosureExpression(parameters, code);
1772        configureAST(closureExpression, node);
1773        // Call it immediately.
1774
String JavaDoc callName = "call";
1775        Expression noArguments = new ArgumentListExpression();
1776        MethodCallExpression call = new MethodCallExpression(closureExpression, callName, noArguments);
1777        configureAST(call, node);
1778        return call;
1779    }
1780
1781    protected Expression negateExpression(AST negateExpr) {
1782        AST node = negateExpr.getFirstChild();
1783
1784        // if we are a number literal then lets just parse it
1785
// as the negation operator on MIN_INT causes rounding to a long
1786
String JavaDoc text = node.getText();
1787        switch (node.getType()) {
1788            case NUM_DOUBLE:
1789            case NUM_FLOAT:
1790            case NUM_BIG_DECIMAL:
1791                ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal("-" + text));
1792                configureAST(constantExpression, negateExpr);
1793                return constantExpression;
1794
1795            case NUM_BIG_INT:
1796            case NUM_INT:
1797            case NUM_LONG:
1798                ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger("-" + text));
1799                configureAST(constantLongExpression, negateExpr);
1800                return constantLongExpression;
1801
1802            default:
1803                NegationExpression negationExpression = new NegationExpression(expression(node));
1804                configureAST(negationExpression, negateExpr);
1805                return negationExpression;
1806        }
1807    }
1808
1809    protected ConstantExpression decimalExpression(AST node) {
1810        String JavaDoc text = node.getText();
1811        ConstantExpression constantExpression = new ConstantExpression(Numbers.parseDecimal(text));
1812        configureAST(constantExpression, node);
1813        return constantExpression;
1814    }
1815
1816    protected ConstantExpression integerExpression(AST node) {
1817        String JavaDoc text = node.getText();
1818        ConstantExpression constantExpression = new ConstantExpression(Numbers.parseInteger(text));
1819        configureAST(constantExpression, node);
1820        return constantExpression;
1821    }
1822
1823    protected Expression gstring(AST gstringNode) {
1824        List JavaDoc strings = new ArrayList JavaDoc();
1825        List JavaDoc values = new ArrayList JavaDoc();
1826
1827        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1828
1829        boolean isPrevString = false;
1830
1831        for (AST node = gstringNode.getFirstChild(); node != null; node = node.getNextSibling()) {
1832            int type = node.getType();
1833            String JavaDoc text = null;
1834            switch (type) {
1835
1836                case STRING_LITERAL:
1837                    if (isPrevString) assertNodeType(IDENT, node); // parser bug
1838
isPrevString = true;
1839                    text = node.getText();
1840                    ConstantExpression constantExpression = new ConstantExpression(text);
1841                    configureAST(constantExpression, node);
1842                    strings.add(constantExpression);
1843                    buffer.append(text);
1844                    break;
1845
1846                default:
1847                    {
1848                        if (!isPrevString) assertNodeType(IDENT, node); // parser bug
1849
isPrevString = false;
1850                        Expression expression = expression(node);
1851                        values.add(expression);
1852                        buffer.append("$");
1853                        buffer.append(expression.getText());
1854                    }
1855                    break;
1856            }
1857        }
1858        GStringExpression gStringExpression = new GStringExpression(buffer.toString(), strings, values);
1859        configureAST(gStringExpression, gstringNode);
1860        return gStringExpression;
1861    }
1862
1863    protected Type type(AST typeNode) {
1864        // TODO intern types?
1865
// TODO configureAST(...)
1866
return new Type(resolvedName(typeNode.getFirstChild()));
1867    }
1868
1869    protected String JavaDoc qualifiedName(AST qualifiedNameNode) {
1870        if (isType(IDENT, qualifiedNameNode)) {
1871            return qualifiedNameNode.getText();
1872        }
1873        if (isType(DOT, qualifiedNameNode)) {
1874            AST node = qualifiedNameNode.getFirstChild();
1875            StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1876            boolean first = true;
1877
1878            for (; node != null; node = node.getNextSibling()) {
1879                if (first) {
1880                    first = false;
1881                }
1882                else {
1883                    buffer.append(".");
1884                }
1885                buffer.append(qualifiedName(node));
1886            }
1887            return buffer.toString();
1888        }
1889        else {
1890            return qualifiedNameNode.getText();
1891        }
1892    }
1893
1894    protected String JavaDoc typeName(AST typeNode) {
1895        String JavaDoc answer = null;
1896        AST node = typeNode.getFirstChild();
1897        if (node != null) {
1898            if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
1899                return resolveTypeName(qualifiedName(node.getFirstChild())) + "[]";
1900            }
1901            answer = resolveTypeName(qualifiedName(node));
1902            node = node.getNextSibling();
1903            if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
1904                return answer + "[]";
1905            }
1906        }
1907        return answer;
1908    }
1909
1910    /**
1911     * Performs a name resolution to see if the given name is a type from imports,
1912     * aliases or newly created classes
1913     */

1914    protected String JavaDoc resolveTypeName(String JavaDoc name, boolean safe) {
1915        if (name == null) {
1916            return null;
1917        }
1918        return resolveNewClassOrName(name, safe);
1919    }
1920
1921    /**
1922     * Performs a name resolution to see if the given name is a type from imports,
1923     * aliases or newly created classes
1924     */

1925    protected String JavaDoc resolveTypeName(String JavaDoc name) {
1926        return resolveTypeName(name, true);
1927    }
1928
1929    /**
1930     * Extracts an identifier from the Antlr AST and then performs a name resolution
1931     * to see if the given name is a type from imports, aliases or newly created classes
1932     */

1933    protected String JavaDoc resolvedName(AST node) {
1934        if (isType(TYPE, node)) {
1935            node = node.getFirstChild();
1936        }
1937        String JavaDoc answer = null;
1938        if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
1939            answer = qualifiedName(node);
1940        }
1941        else if (isPrimitiveTypeLiteral(node)) {
1942            answer = node.getText();
1943        }
1944        else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
1945            AST child = node.getFirstChild();
1946            String JavaDoc text = resolvedName(child);
1947            // TODO sometimes we have ARRAY_DECLARATOR->typeName
1948
// and sometimes we have typeName->ARRAY_DECLARATOR
1949
// so here's a little fudge while we be more consistent in the Antlr
1950
if (text.endsWith("[]")) {
1951                return text;
1952            }
1953            return text + "[]";
1954        }
1955        else {
1956            String JavaDoc identifier = node.getText();
1957            answer = resolveTypeName(identifier);
1958
1959        }
1960        AST nextSibling = node.getNextSibling();
1961        if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) {
1962            return answer + "[]";
1963        }
1964        else {
1965            return answer;
1966        }
1967    }
1968
1969    protected boolean isPrimitiveTypeLiteral(AST node) {
1970        int type = node.getType();
1971        switch (type) {
1972            case LITERAL_boolean:
1973            case LITERAL_byte:
1974            case LITERAL_char:
1975            case LITERAL_double:
1976            case LITERAL_float:
1977            case LITERAL_int:
1978            case LITERAL_long:
1979            case LITERAL_short:
1980                return true;
1981
1982            default:
1983                return false;
1984        }
1985    }
1986
1987    /**
1988     * Extracts an identifier from the Antlr AST
1989     */

1990    protected String JavaDoc identifier(AST node) {
1991        assertNodeType(IDENT, node);
1992        return node.getText();
1993    }
1994
1995    protected String JavaDoc label(AST labelNode) {
1996        AST node = labelNode.getFirstChild();
1997        if (node == null) {
1998            return null;
1999        }
2000        return identifier(node);
2001    }
2002
2003
2004
2005    // Helper methods
2006
//-------------------------------------------------------------------------
2007

2008
2009    /**
2010     * Returns true if the modifiers flags contain a visibility modifier
2011     */

2012    protected boolean hasVisibility(int modifiers) {
2013        return (modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) != 0;
2014    }
2015
2016    protected void configureAST(ASTNode node, AST ast) {
2017        if (ast==null) throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure "+node.getClass().getName()+" with null Node");
2018        node.setColumnNumber(ast.getColumn());
2019        node.setLineNumber(ast.getLine());
2020
2021        // TODO we could one day store the Antlr AST on the Groovy AST
2022
// node.setCSTNode(ast);
2023
}
2024
2025    protected static Token makeToken(int typeCode, AST node) {
2026        return Token.newSymbol(typeCode, node.getLine(), node.getColumn());
2027    }
2028
2029    protected String JavaDoc getFirstChildText(AST node) {
2030        AST child = node.getFirstChild();
2031        return child != null ? child.getText() : null;
2032    }
2033
2034
2035    protected boolean isType(int typeCode, AST node) {
2036        return node != null && node.getType() == typeCode;
2037    }
2038
2039    private String JavaDoc getTokenName(int token) {
2040        if (tokenNames==null) return ""+token;
2041        return tokenNames[token];
2042    }
2043    
2044    private String JavaDoc getTokenName(AST node) {
2045        if (node==null) return "null";
2046        return getTokenName(node.getType());
2047    }
2048
2049    protected void assertNodeType(int type, AST node) {
2050        if (node == null) {
2051            throw new ASTRuntimeException(node, "No child node available in AST when expecting type: " + getTokenName(type));
2052        }
2053        if (node.getType() != type) {
2054            throw new ASTRuntimeException(node, "Unexpected node type: " + getTokenName(node) + " found when expecting type: " + getTokenName(type));
2055        }
2056    }
2057
2058    protected void notImplementedYet(AST node) {
2059        throw new ASTRuntimeException(node, "AST node not implemented yet for type: " + getTokenName(node));
2060    }
2061
2062    protected void unknownAST(AST node) {
2063        throw new ASTRuntimeException(node, "Unknown type: " + getTokenName(node));
2064    }
2065
2066    protected void dumpTree(AST ast) {
2067        for (AST node = ast.getFirstChild(); node != null; node = node.getNextSibling()) {
2068            dump(node);
2069        }
2070    }
2071
2072    protected void dump(AST node) {
2073        System.out.println("Type: " + getTokenName(node) + " text: " + node.getText());
2074    }
2075}
2076
Popular Tags