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