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