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