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