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