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