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