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
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;
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
117 if ("xml".equals(System.getProperty("antlr.ast"))) {
118 saveAsXML(sourceUnit.getName(), ast);
119 }
120
121
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
134
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
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
226
227
228 protected void packageDef(AST packageDef) {/package-summary.html">ong> 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
239
240 AST node = importNode.getFirstChild();
241
242 String alias = null;
243 if (isType(LITERAL_as, node)) {
244
245 node = node.getFirstChild();
246 AST aliasNode = node.getNextSibling();
247 alias = identifier(aliasNode);
248 }
249
250 if (node.getNumberOfChildren()==0) {
251
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
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
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
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
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
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
644
645
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
659 case ANNOTATION:
660 annotations.add(annotation(node));
661 break;
662
663
664
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
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
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
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
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
996
997
998
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
1054 answer = new CaseStatement((Expression) expressions.get(0), statement);
1055 } else {
1056
1057
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
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
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
1156
1157
1158
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
1234
1235
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
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
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
1307 case INC:
1308 return prefixExpression(node, Types.PLUS_PLUS);
1309
1310 case DEC:
1311 return prefixExpression(node, Types.MINUS_MINUS);
1312
1313
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
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