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 }