1   package org.codehaus.groovy.syntax.parser;
2   
3   import groovy.util.GroovyTestCase;
4   
5   import org.codehaus.groovy.control.CompilationFailedException;
6   import org.codehaus.groovy.control.SourceUnit;
7   
8   /*
9   import org.codehaus.groovy.syntax.lexer.CharStream;
10  import org.codehaus.groovy.syntax.lexer.StringCharStream;
11  import org.codehaus.groovy.syntax.lexer.Lexer;
12  import org.codehaus.groovy.syntax.lexer.LexerTokenStream;
13  import org.codehaus.groovy.syntax.Token;
14  import org.codehaus.groovy.syntax.TokenStream;
15  import org.codehaus.groovy.tools.ExceptionCollector;
16  */
17  
18  public class ParserTest extends GroovyTestCase {
19  
20     private int tolerance = 0;
21  
22  
23     /***
24      * This test case performs the same logic as the interactive shell to
25      * decide if a statement is complete or not
26      */
27     public void testParserThrowsTheRightException() throws Exception {
28          String code = "class Cheese {";
29          SourceUnit parser = null;
30  
31          try {
32              parser = SourceUnit.create("groovysh script", code, tolerance);
33              parser.parse();
34              parser.getCST();
35          }
36          catch (CompilationFailedException e) {
37              assertTrue("Parser should have failed with Unexpected EOF flag", parser.failedWithUnexpectedEOF());
38              assertTrue("Parser should have an error count of 1 or less", parser.getErrorCount() <= 1);
39          }
40      }
41  
42  
43  /*
44      // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
45      //     package
46      // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
47  
48      public void testEmptyScript() throws Exception {
49          Parser parser = newParser("");
50  
51          CSTNode root = parser.compilationUnit();
52  
53          assertEquals(null, root.getToken());
54          
55          System.out.println("Root: " + root);
56          {
57              CSTNode child = root.getChild(0);
58              
59              System.out.println("Child: "+ child);
60              
61              //assertEquals(null, child);
62          }
63      }
64  
65      public void testPackageDeclaration_NoDots() throws Exception {
66          Parser parser = newParser("package cheese");
67  
68          CSTNode root = parser.packageDeclaration();
69  
70          assertNode(root, "package", Token.KEYWORD_PACKAGE, 1);
71  
72          {
73              assertNode(root.getChild(0), "cheese", Token.IDENTIFIER, 0);
74          }
75      }
76  
77      public void testPackageDeclaration_OneDot() throws Exception {
78          Parser parser = newParser("package cheese.toast");
79  
80          CSTNode root = parser.packageDeclaration();
81  
82          assertNode(root, "package", Token.KEYWORD_PACKAGE, 1);
83  
84          {
85              assertNode(root.getChild(0), ".", Token.DOT, 2);
86  
87              {
88                  assertNode(root.getChild(0).getChild(0), "cheese", Token.IDENTIFIER, 0);
89  
90                  assertNode(root.getChild(0).getChild(1), "toast", Token.IDENTIFIER, 0);
91              }
92          }
93      }
94  
95      public void testPackageDeclaration_MultipleDots() throws Exception {
96          Parser parser = newParser("package cheddar.cheese.toast");
97  
98          CSTNode root = parser.packageDeclaration();
99  
100         assertNode(root, "package", Token.KEYWORD_PACKAGE, 1);
101 
102         {
103             assertNode(root.getChild(0), ".", Token.DOT, 2);
104 
105             {
106                 assertNode(root.getChild(0).getChild(0), ".", Token.DOT, 2);
107                 {
108                     assertNode(root.getChild(0).getChild(0).getChild(0), "cheddar", Token.IDENTIFIER, 0);
109 
110                     assertNode(root.getChild(0).getChild(0).getChild(1), "cheese", Token.IDENTIFIER, 0);
111                 }
112 
113                 assertNode(root.getChild(0).getChild(1), "toast", Token.IDENTIFIER, 0);
114             }
115         }
116     }
117 
118     public void testPackageDeclaration_UnexpectedToken_NoInitialIdentifier() throws Exception {
119         Parser parser = newParser("package .");
120 
121         try {
122             try {
123                 parser.packageDeclaration();
124                 fail("should have thrown UnexpectedTokenException");
125             }
126             catch( ExceptionCollector e ) {
127                 e.throwFirstChild();
128             }
129         }
130         catch (UnexpectedTokenException e) {
131             // expected and correct
132             assertToken(e.getUnexpectedToken(), ".", Token.DOT);
133 
134             assertLength(1, e.getExpectedTypes());
135 
136             assertContains(Token.IDENTIFIER, e.getExpectedTypes());
137         }
138     }
139 
140     public void testPackageDeclaration_UnexpectedToken_NoIdentifierFollowingDot() throws Exception {
141         Parser parser = newParser("package cheese.");
142 
143         try {
144             try {
145                 parser.packageDeclaration();
146                 fail("should have thrown UnexpectedTokenException");
147             }
148             catch( ExceptionCollector e ) {
149                 e.throwFirstChild();
150             }
151         }
152         catch (UnexpectedTokenException e) {
153             // expected and correct
154             assertNull(e.getUnexpectedToken());
155 
156             assertLength(1, e.getExpectedTypes());
157 
158             assertContains(Token.IDENTIFIER, e.getExpectedTypes());
159         }
160     }
161 
162     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
163     //     import
164     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
165 
166     public void testImportStatement_NoDots() throws Exception {
167         Parser parser = newParser("import Cheese");
168 
169         CSTNode root = parser.importStatement();
170 
171         assertNode(root, "import", Token.KEYWORD_IMPORT, 2);
172 
173         {
174             assertNullNode(root.getChild(0), 0);
175 
176             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 0);
177         }
178     }
179 
180     public void testImportStatement_As_NoDots() throws Exception {
181         Parser parser = newParser("import Cheese as Toast");
182 
183         CSTNode root = parser.importStatement();
184 
185         assertNode(root, "import", Token.KEYWORD_IMPORT, 2);
186 
187         {
188             assertNullNode(root.getChild(0), 0);
189 
190             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 1);
191 
192             assertNode(root.getChild(1).getChild(0), "Toast", Token.IDENTIFIER, 0);
193         }
194     }
195 
196     public void testImportStatement_OneDot() throws Exception {
197         Parser parser = newParser("import cheese.Toast");
198 
199         CSTNode root = parser.importStatement();
200 
201         assertNode(root, "import", Token.KEYWORD_IMPORT, 2);
202 
203         {
204             assertNode(root.getChild(0), "cheese", Token.IDENTIFIER, 0);
205             assertNode(root.getChild(1), "Toast", Token.IDENTIFIER, 0);
206         }
207     }
208 
209     public void testImportStatement_As_OneDot() throws Exception {
210         Parser parser = newParser("import cheese.Toast as Bread");
211 
212         CSTNode root = parser.importStatement();
213 
214         assertNode(root, "import", Token.KEYWORD_IMPORT, 2);
215 
216         {
217             assertNode(root.getChild(0), "cheese", Token.IDENTIFIER, 0);
218 
219             assertNode(root.getChild(1), "Toast", Token.IDENTIFIER, 1);
220 
221             assertNode(root.getChild(1).getChild(0), "Bread", Token.IDENTIFIER, 0);
222         }
223     }
224 
225     public void testImportStatement_MultipleDots() throws Exception {
226         Parser parser = newParser("import cheddar.cheese.Toast");
227 
228         CSTNode root = parser.importStatement();
229 
230         assertNode(root, "import", Token.KEYWORD_IMPORT, 2);
231 
232         {
233             assertNode(root.getChild(0), ".", Token.DOT, 2);
234             {
235                 assertNode(root.getChild(0).getChild(0), "cheddar", Token.IDENTIFIER, 0);
236                 assertNode(root.getChild(0).getChild(1), "cheese", Token.IDENTIFIER, 0);
237             }
238             
239             assertNode(root.getChild(1), "Toast", Token.IDENTIFIER, 0);
240         }
241     }
242 
243     public void testImportStatement_As_MultipleDots() throws Exception {
244         Parser parser = newParser("import cheddar.cheese.Toast as Bread");
245 
246         CSTNode root = parser.importStatement();
247 
248         assertNode(root, "import", Token.KEYWORD_IMPORT, 2);
249 
250         {
251             assertNode(root.getChild(0), ".", Token.DOT, 2);
252             {
253                 assertNode(root.getChild(0).getChild(0), "cheddar", Token.IDENTIFIER, 0);
254                 assertNode(root.getChild(0).getChild(1), "cheese", Token.IDENTIFIER, 0);
255             }
256             
257             assertNode(root.getChild(1), "Toast", Token.IDENTIFIER, 1);
258             assertNode(root.getChild(1).getChild(0), "Bread", Token.IDENTIFIER, 0);
259         }
260     }
261 
262     public void testImportStatement_UnexpectedToken_NoInitialIdentifier() throws Exception {
263         Parser parser = newParser("import .");
264 
265         try {
266             try {
267                 parser.importStatement();
268                 fail("should have thrown UnexpectedTokenException");
269             }
270             catch( ExceptionCollector e ) {
271                 e.throwFirstChild();
272             }
273         }
274         catch (UnexpectedTokenException e) {
275             // expected and correct
276             assertToken(e.getUnexpectedToken(), ".", Token.DOT);
277 
278             assertLength(1, e.getExpectedTypes());
279 
280             assertContains(Token.IDENTIFIER, e.getExpectedTypes());
281         }
282     }
283 
284     public void testImportStatement_UnexpectedToken_NoIdentifierFollowingDot() throws Exception {
285         Parser parser = newParser("import cheese.");
286 
287         try {
288             try {
289                 parser.importStatement();
290                 fail("should have thrown UnexpectedTokenException");
291             }
292             catch( ExceptionCollector e ) {
293                 e.throwFirstChild();
294             }
295         }
296         catch (UnexpectedTokenException e) {
297             // expected and correct
298             assertNull(e.getUnexpectedToken());
299 
300             assertLength(1, e.getExpectedTypes());
301 
302             assertContains(Token.IDENTIFIER, e.getExpectedTypes());
303         }
304     }
305 
306     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
307     //     class
308     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
309 
310     public void testClassDeclaration_NoModifiers_NoBody_NoExtendsOrImplements() throws Exception {
311         Parser parser = newParser("class Cheese { }");
312 
313         CSTNode modifiers = new CSTNode();
314 
315         CSTNode root = parser.classDeclaration(modifiers);
316 
317         assertNode(root, "class", Token.KEYWORD_CLASS, 5);
318 
319         {
320             assertSame(modifiers, root.getChild(0));
321 
322             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 0);
323 
324             assertNullNode(root.getChild(2), 0);
325 
326             assertNullNode(root.getChild(3), 0);
327 
328             assertNullNode(root.getChild(4), 0);
329         }
330     }
331 
332     public void testClassDeclaration_NoIdentifier() throws Exception {
333         Parser parser = newParser("class {");
334 
335         CSTNode modifiers = new CSTNode();
336 
337         try {
338             try {
339                 parser.classDeclaration(modifiers);
340             }
341             catch( ExceptionCollector e ) {
342                 e.throwFirstChild();
343             }
344         }
345         catch (UnexpectedTokenException e) {
346             // expected and correct
347             assertToken(e.getUnexpectedToken(), "{", Token.LEFT_CURLY_BRACE);
348 
349             assertLength(1, e.getExpectedTypes());
350 
351             assertContains(Token.IDENTIFIER, e.getExpectedTypes());
352         }
353     }
354 
355     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
356     //     interface
357     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
358 
359     public void testInterfaceDeclaration_NoModifiers_NoBody_NoExtendsOrImplements() throws Exception {
360         Parser parser = newParser("interface Cheese { }");
361 
362         CSTNode modifiers = new CSTNode();
363 
364         CSTNode root = parser.interfaceDeclaration(modifiers);
365 
366         assertNode(root, "interface", Token.KEYWORD_INTERFACE, 5);
367 
368         {
369             assertSame(modifiers, root.getChild(0));
370 
371             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 0);
372 
373             assertNullNode(root.getChild(2), 0);
374         }
375     }
376 
377     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
378     //     <type declaration>
379     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
380 
381     public void testTypeDeclaration_Class_NoModifiers_NoBody_NoExtendsOrImplements() throws Exception {
382         Parser parser = newParser("class Cheese { }");
383 
384         CSTNode root = parser.typeDeclaration();
385 
386         assertNode(root, "class", Token.KEYWORD_CLASS, 5);
387 
388         {
389             assertNullNode(root.getChild(0), 0);
390 
391             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 0);
392 
393             assertNullNode(root.getChild(2), 0);
394 
395             assertNullNode(root.getChild(3), 0);
396 
397             assertNullNode(root.getChild(4), 0);
398         }
399     }
400 
401     public void testTypeDeclaration_Class_WithModifiers_NoBody_NoExtendsOrImplements() throws Exception {
402         Parser parser = newParser("public class Cheese { }");
403 
404         CSTNode root = parser.typeDeclaration();
405 
406         assertNode(root, "class", Token.KEYWORD_CLASS, 5);
407 
408         {
409             assertNullNode(root.getChild(0), 1);
410             {
411                 assertNode(root.getChild(0).getChild(0), "public", Token.KEYWORD_PUBLIC, 0);
412             }
413 
414             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 0);
415 
416             assertNullNode(root.getChild(2), 0);
417 
418             assertNullNode(root.getChild(3), 0);
419 
420             assertNullNode(root.getChild(4), 0);
421         }
422     }
423 
424     public void testTypeDeclaration_Interface_NoModifiers_NoBody_NoExtendsOrImplements() throws Exception {
425         Parser parser = newParser("interface Cheese { }");
426 
427         CSTNode root = parser.typeDeclaration();
428 
429         assertNode(root, "interface", Token.KEYWORD_INTERFACE, 5);
430 
431         {
432             assertNullNode(root.getChild(0), 0);
433 
434             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 0);
435 
436             assertNullNode(root.getChild(2), 0);
437         }
438     }
439 
440     public void testTypeDeclaration_Interface_WithModifiers_NoBody_NoExtendsOrImplements() throws Exception {
441         Parser parser = newParser("public interface Cheese { }");
442 
443         CSTNode root = parser.typeDeclaration();
444 
445         assertNode(root, "interface", Token.KEYWORD_INTERFACE, 5);
446 
447         {
448             assertNullNode(root.getChild(0), 1);
449             {
450                 assertNode(root.getChild(0).getChild(0), "public", Token.KEYWORD_PUBLIC, 0);
451             }
452 
453             assertNode(root.getChild(1), "Cheese", Token.IDENTIFIER, 0);
454 
455             assertNullNode(root.getChild(2), 0);
456         }
457     }
458 
459 /*    /*
460     
461     The following is actually now valid...
462     
463     public void testTypeDeclaration_UnexpectedToken()
464         throws Exception
465     {
466         Parser parser = newParser( "cheese" );
467     
468         try
469         {
470             try {
471                 parser.typeDeclaration();
472                 fail( "should have thrown UnexpectedTokenException" );
473             }
474             catch( ExceptionCollector e ) {
475                 e.throwFirstChild();
476             }
477         }
478         catch (UnexpectedTokenException e)
479         {
480             assertToken( e.getToken(),
481                          "cheese",
482                          Token.IDENTIFIER );
483     
484             assertLength( 2,
485                           e.getExpectedTypes() );
486     
487             assertContains( Token.KEYWORD_CLASS,
488                             e.getExpectedTypes() );
489     
490             assertContains( Token.KEYWORD_INTERFACE,
491                             e.getExpectedTypes() );
492         }
493     }
494     */
495 /*
496 
497     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
498     //     <compilation unit>
499     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
500 
501     public void testCompilationUnit_NoImports_OneClass() throws Exception {
502         Parser parser = newParser("package cheese; public class Cheese{}");
503 
504         CSTNode root = parser.compilationUnit();
505 
506         assertNullNode(root, 3);
507 
508         {
509             assertNode(root.getChild(0), "package", Token.KEYWORD_PACKAGE, 1);
510 
511             {
512                 assertNode(root.getChild(0).getChild(0), "cheese", Token.IDENTIFIER, 0);
513             }
514 
515             assertNullNode(root.getChild(1), 0);
516 
517             assertNode(root.getChild(2), "class", Token.KEYWORD_CLASS, 5);
518         }
519     }
520 
521     public void testCompilationUnit_NoImports_OneInterface() throws Exception {
522         Parser parser = newParser("package cheese; public interface Cheese{}");
523 
524         CSTNode root = parser.compilationUnit();
525 
526         assertNullNode(root, 3);
527 
528         {
529             assertNode(root.getChild(0), "package", Token.KEYWORD_PACKAGE, 1);
530 
531             {
532                 assertNode(root.getChild(0).getChild(0), "cheese", Token.IDENTIFIER, 0);
533             }
534 
535             assertNullNode(root.getChild(1), 0);
536 
537             assertNode(root.getChild(2), "interface", Token.KEYWORD_INTERFACE, 5);
538         }
539     }
540 
541     public void testCompilationUnit_WithImports_OneClass() throws Exception {
542         Parser parser = newParser("package cheese; import com.Toast; import com.Jelly; public class Cheese{}");
543 
544         CSTNode root = parser.compilationUnit();
545 
546         assertNullNode(root, 3);
547 
548         {
549             assertNode(root.getChild(0), "package", Token.KEYWORD_PACKAGE, 1);
550 
551             {
552                 assertNode(root.getChild(0).getChild(0), "cheese", Token.IDENTIFIER, 0);
553             }
554 
555             assertNullNode(root.getChild(1), 2);
556 
557             {
558                 assertNode(root.getChild(1).getChild(0), "import", Token.KEYWORD_IMPORT, 2);
559 
560                 assertNode(root.getChild(1).getChild(1), "import", Token.KEYWORD_IMPORT, 2);
561             }
562 
563             assertNode(root.getChild(2), "class", Token.KEYWORD_CLASS, 5);
564         }
565     }
566 
567     public void testCompilationUnit_WithImports_TwoClasses() throws Exception {
568         Parser parser =
569             newParser("package cheese; import com.Toast; import com.Jelly; public class Cheese{} public class Goober {}");
570 
571         CSTNode root = parser.compilationUnit();
572 
573         assertNullNode(root, 4);
574 
575         {
576             assertNode(root.getChild(0), "package", Token.KEYWORD_PACKAGE, 1);
577 
578             {
579                 assertNode(root.getChild(0).getChild(0), "cheese", Token.IDENTIFIER, 0);
580             }
581 
582             assertNullNode(root.getChild(1), 2);
583 
584             {
585                 assertNode(root.getChild(1).getChild(0), "import", Token.KEYWORD_IMPORT, 2);
586 
587                 assertNode(root.getChild(1).getChild(1), "import", Token.KEYWORD_IMPORT, 2);
588             }
589 
590             assertNode(root.getChild(2), "class", Token.KEYWORD_CLASS, 5);
591             {
592                 assertNode(root.getChild(2).getChild(1), "Cheese", Token.IDENTIFIER, 0);
593             }
594 
595             assertNode(root.getChild(3), "class", Token.KEYWORD_CLASS, 5);
596             {
597                 assertNode(root.getChild(3).getChild(1), "Goober", Token.IDENTIFIER, 0);
598             }
599         }
600     }
601 
602     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
603     //     <body statement>
604     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
605 
606     public void testBodyStatement_PropertyDeclaration_NoModifiers_NoType() throws Exception {
607         Parser parser = newParser("property cheese;");
608 
609         CSTNode root = parser.bodyStatement();
610 
611         System.out.println("Got: " + root);
612 
613         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
614 
615         {
616             assertNullNode(root.getChild(0), 0);
617 
618             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
619 
620             assertNullNode(root.getChild(2), 0);
621         }
622     }
623 
624     public void testBodyStatement_PropertyDeclaration_OneModifier_NoType() throws Exception {
625         Parser parser = newParser("static property cheese;");
626 
627         CSTNode root = parser.bodyStatement();
628 
629         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
630 
631         {
632             assertNullNode(root.getChild(0), 1);
633 
634             {
635                 assertNode(root.getChild(0).getChild(0), "static", Token.KEYWORD_STATIC, 0);
636             }
637 
638             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
639 
640             assertNullNode(root.getChild(2), 0);
641         }
642     }
643 
644     public void testBodyStatement_PropertyDeclaration_TwoModifiers_NoType() throws Exception {
645         Parser parser = newParser("static synchronized property cheese;");
646 
647         CSTNode root = parser.bodyStatement();
648 
649         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
650 
651         {
652             assertNullNode(root.getChild(0), 2);
653 
654             {
655                 assertNode(root.getChild(0).getChild(0), "static", Token.KEYWORD_STATIC, 0);
656 
657                 assertNode(root.getChild(0).getChild(1), "synchronized", Token.KEYWORD_SYNCHRONIZED, 0);
658             }
659 
660             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
661 
662             assertNullNode(root.getChild(2), 0);
663         }
664     }
665 
666     public void testBodyStatement_PropertyDeclaration_NoProperty_NoModifiers_NoType() throws Exception {
667         Parser parser = newParser("cheese;");
668 
669         CSTNode root = parser.bodyStatement();
670 
671         System.out.println("Got: " + root);
672 
673         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
674 
675         {
676             assertNullNode(root.getChild(0), 0);
677 
678             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
679 
680             assertNullNode(root.getChild(2), 0);
681         }
682     }
683 
684     public void testBodyStatement_PropertyDeclaration_NoProperty_OneModifier_NoType() throws Exception {
685         Parser parser = newParser("static cheese;");
686 
687         CSTNode root = parser.bodyStatement();
688 
689         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
690 
691         {
692             assertNullNode(root.getChild(0), 1);
693 
694             {
695                 assertNode(root.getChild(0).getChild(0), "static", Token.KEYWORD_STATIC, 0);
696             }
697 
698             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
699 
700             assertNullNode(root.getChild(2), 0);
701         }
702     }
703 
704     public void testBodyStatement_PropertyDeclaration_NoProperty_TwoModifiers_NoType() throws Exception {
705         Parser parser = newParser("static synchronized cheese;");
706 
707         CSTNode root = parser.bodyStatement();
708 
709         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
710 
711         {
712             assertNullNode(root.getChild(0), 2);
713 
714             {
715                 assertNode(root.getChild(0).getChild(0), "static", Token.KEYWORD_STATIC, 0);
716 
717                 assertNode(root.getChild(0).getChild(1), "synchronized", Token.KEYWORD_SYNCHRONIZED, 0);
718             }
719 
720             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
721 
722             assertNullNode(root.getChild(2), 0);
723         }
724     }
725 
726     public void testBodyStatement_PropertyDeclaration_NoType_WithExpression() throws Exception {
727         Parser parser = newParser("cheese = 1234");
728 
729         CSTNode root = parser.bodyStatement();
730 
731         assertNode(root, "property", Token.KEYWORD_PROPERTY, 4);
732 
733         {
734             assertNullNode(root.getChild(0), 0);
735 
736             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
737 
738             assertNullNode(root.getChild(2), 0);
739 
740             assertNode(root.getChild(3), "1234", Token.INTEGER_NUMBER, 0);
741         }
742     }
743 
744     public void testBodyStatement_PropertyDeclaration_Type_WithExpression() throws Exception {
745         Parser parser = newParser("Food cheese = defaultValue()");
746 
747         CSTNode root = parser.bodyStatement();
748 
749         assertNode(root, "property", Token.KEYWORD_PROPERTY, 4);
750 
751         {
752             assertNullNode(root.getChild(0), 0);
753 
754             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
755 
756             assertNode(root.getChild(2), "Food", Token.IDENTIFIER, 0);
757 
758             assertNode(root.getChild(3), "(", Token.LEFT_PARENTHESIS, 3);
759         }
760     }
761 
762     public void testBodyStatement_MethodDeclaration_NoReturnType_NoParameters() throws Exception {
763         Parser parser = newParser("cheeseIt() { } ");
764 
765         CSTNode root = parser.bodyStatement();
766 
767         assertNode(root, "<synthetic>", Token.SYNTH_METHOD, 6);
768 
769         {
770             assertNullNode(root.getChild(0), 0);
771 
772             assertNode(root.getChild(1), "cheeseIt", Token.IDENTIFIER, 0);
773 
774             assertNullNode(root.getChild(2), 0);
775 
776             assertNode(root.getChild(3), "(", Token.LEFT_PARENTHESIS, 0);
777         }
778     }
779 
780     public void testBodyStatement_MethodDeclaration_WithReturnType_NoParameters() throws Exception {
781         Parser parser = newParser("String cheeseIt() { }");
782 
783         CSTNode root = parser.bodyStatement();
784 
785         assertNode(root, "<synthetic>", Token.SYNTH_METHOD, 6);
786 
787         {
788             assertNullNode(root.getChild(0), 0);
789 
790             assertNode(root.getChild(1), "cheeseIt", Token.IDENTIFIER, 0);
791 
792             assertNode(root.getChild(2), "String", Token.IDENTIFIER, 0);
793 
794             assertNode(root.getChild(3), "(", Token.LEFT_PARENTHESIS, 0);
795         }
796     }
797 
798     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
799     //     <parameter>
800     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
801 
802     public void testParameterList() throws Exception {
803     }
804 
805     public void testParameterDeclarationWithoutDatatype() throws Exception {
806         Parser parser = newParser("cheese");
807 
808         CSTNode root = parser.parameterDeclaration();
809 
810         assertNode(root, "<synthetic>", Token.SYNTH_PARAMETER_DECLARATION, 2);
811 
812         {
813             assertNullNode(root.getChild(0), 0);
814 
815             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
816         }
817     }
818 
819     public void testParameterDeclarationWithDatatype_Simple() throws Exception {
820         Parser parser = newParser("String cheese");
821 
822         CSTNode root = parser.parameterDeclaration();
823 
824         assertNode(root, "<synthetic>", Token.SYNTH_PARAMETER_DECLARATION, 2);
825 
826         {
827             assertNode(root.getChild(0), "String", Token.IDENTIFIER, 0);
828 
829             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
830         }
831     }
832 
833     public void testParameterDeclarationWithDatatype_Qualified() throws Exception {
834         Parser parser = newParser("java.lang.String cheese");
835 
836         CSTNode root = parser.parameterDeclaration();
837 
838         assertNode(root, "<synthetic>", Token.SYNTH_PARAMETER_DECLARATION, 2);
839 
840         {
841             assertNode(root.getChild(0), ".", Token.DOT, 2);
842             {
843                 assertNode(root.getChild(0).getChild(0), ".", Token.DOT, 2);
844 
845                 {
846                     assertNode(root.getChild(0).getChild(0).getChild(0), "java", Token.IDENTIFIER, 0);
847 
848                     assertNode(root.getChild(0).getChild(0).getChild(1), "lang", Token.IDENTIFIER, 0);
849                 }
850 
851                 assertNode(root.getChild(0).getChild(1), "String", Token.IDENTIFIER, 0);
852             }
853 
854             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
855         }
856     }
857 
858     public void testParameterDeclaration_General_WithoutDatatype() throws Exception {
859         Parser parser = newParser("cheese");
860 
861         CSTNode root = parser.parameterDeclaration();
862 
863         assertNode(root, "<synthetic>", Token.SYNTH_PARAMETER_DECLARATION, 2);
864 
865         {
866             assertNullNode(root.getChild(0), 0);
867 
868             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
869         }
870     }
871 
872     public void testParameterDeclaration_General_WithDatatype() throws Exception {
873         Parser parser = newParser("String cheese");
874 
875         CSTNode root = parser.parameterDeclaration();
876 
877         assertNode(root, "<synthetic>", Token.SYNTH_PARAMETER_DECLARATION, 2);
878 
879         {
880             assertNode(root.getChild(0), "String", Token.IDENTIFIER, 0);
881 
882             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
883         }
884     }
885 
886     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
887     //     <parameter list>
888     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
889 
890     public void testParameterList_Empty() throws Exception {
891         Parser parser = newParser("");
892 
893         CSTNode root = parser.parameterDeclarationList();
894 
895         assertNullNode(root, 0);
896     }
897 
898     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
899     //     method
900     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
901 
902     public void testMethod_NoModifiers_NoReturnType_NoParameters() throws Exception {
903         Parser parser = newParser("cheeseIt() { }");
904 
905         CSTNode root = parser.bodyStatement();
906 
907         assertNode(root, "<synthetic>", Token.SYNTH_METHOD, 6);
908 
909         {
910             assertNullNode(root.getChild(0), 0);
911 
912             assertNode(root.getChild(1), "cheeseIt", Token.IDENTIFIER, 0);
913 
914             assertNullNode(root.getChild(2), 0);
915 
916             assertNode(root.getChild(3), "(", Token.LEFT_PARENTHESIS, 0);
917         }
918     }
919 
920     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
921     //     property
922     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
923 
924     public void testProperty_NoModifiers_NoType() throws Exception {
925         Parser parser = newParser("property cheese");
926 
927         CSTNode root = parser.bodyStatement();
928 
929         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
930 
931         {
932             assertNullNode(root.getChild(0), 0);
933 
934             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
935 
936             assertNullNode(root.getChild(2), 0);
937         }
938     }
939 
940     public void testProperty_NoModifiers_NoProperty_NoType() throws Exception {
941         Parser parser = newParser("cheese");
942 
943         CSTNode root = parser.bodyStatement();
944 
945         assertNode(root, "property", Token.KEYWORD_PROPERTY, 3);
946 
947         {
948             assertNullNode(root.getChild(0), 0);
949 
950             assertNode(root.getChild(1), "cheese", Token.IDENTIFIER, 0);
951 
952             assertNullNode(root.getChild(2), 0);
953         }
954     }
955 
956     //     ((misc))
957     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
958 
959     public void testIsModifier() throws Exception {
960         assertTrue(Token.isModifier(Token.KEYWORD_PUBLIC));
961         assertTrue(Token.isModifier(Token.KEYWORD_PROTECTED));
962         assertTrue(Token.isModifier(Token.KEYWORD_PRIVATE));
963         assertTrue(Token.isModifier(Token.KEYWORD_STATIC));
964         assertTrue(Token.isModifier(Token.KEYWORD_FINAL));
965         assertTrue(Token.isModifier(Token.KEYWORD_SYNCHRONIZED));
966         assertFalse(Token.isModifier(Token.IDENTIFIER));
967     }
968 
969     public void testConsumeUntil_Found() throws Exception {
970         Parser parser = newParser("cheese toast is; bread");
971 
972         assertToken(parser.la(), "cheese", Token.IDENTIFIER);
973 
974         parser.consumeUntil(Token.SEMICOLON);
975 
976         assertToken(parser.la(), "bread", Token.IDENTIFIER);
977     }
978 
979     public void testConsumeUntil_NotFound() throws Exception {
980         Parser parser = newParser("cheese toast");
981 
982         assertToken(parser.la(), "cheese", Token.IDENTIFIER);
983 
984         parser.consumeUntil(Token.SEMICOLON);
985 
986         assertNull(parser.la());
987     }
988 
989     public void testAssignmentExpression() throws Exception {
990         Parser parser = newParser("answer = list.collect( { item | return item * 2 } )");
991 
992         CSTNode root = parser.expression();
993     }
994 
995     public void testSafeMethodCallExpression() throws Exception {
996         Parser parser = newParser("answer = foo->someMethod()");
997 
998         CSTNode root = parser.expression();
999 
1000         System.out.println("Got: " + root);
1001     }
1002 
1003     public void testLogicalAndExpression() throws Exception {
1004         Parser parser = newParser("x > 1 && \n y < 2");
1005 
1006         CSTNode root = parser.expression();
1007 
1008         System.out.println("Got: " + root);
1009     }
1010 
1011     public void testStatement_CharacterizeMePlease() throws Exception {
1012         Parser parser = newParser("callBlock(5, { owner | owner.incrementCallCount() })");
1013 
1014         CSTNode root = parser.statement();
1015     }
1016 
1017     public void testStatementBlock_CharacterizeMePlease() throws Exception {
1018         Parser parser =
1019             newParser("keys = answer.collect( { entry | return entry.key } ); values = answer.collect( { entry | return entry.value })");
1020 
1021         CSTNode root = parser.statement();
1022 
1023         root = parser.statement();
1024     }
1025 
1026     public void testStatementBlock_MissingSemicolon() throws Exception {
1027         Parser parser =
1028             newParser("keys = answer.collect( { entry | return entry.key } )  values = answer.collect( { entry | return entry.value })");
1029 
1030         try {
1031             try {
1032                 parser.statement(); 
1033                 fail("should have thrown UnexpectedTokenException");
1034             }
1035             catch( ExceptionCollector e ) {
1036                 e.throwFirstChild();
1037             }
1038         }
1039         catch (UnexpectedTokenException e) {
1040         }
1041     }
1042 
1043     public void testNewExpression() throws Exception {
1044         Parser parser = newParser("new Cheese()");
1045 
1046         CSTNode root = parser.newExpression();
1047 
1048         assertNode(root, "new", Token.KEYWORD_NEW, 2);
1049 
1050         {
1051             assertNode(root.getChild(0), "Cheese", Token.IDENTIFIER, 0);
1052 
1053             assertNode(root.getChild(1), "<synthetic>", Token.SYNTH_LIST, 0);
1054         }
1055     }
1056 
1057     public void testDatatype_NoDots() throws Exception {
1058         Parser parser = newParser("Cheese");
1059 
1060         CSTNode root = parser.datatype();
1061 
1062         assertNode(root, "Cheese", Token.IDENTIFIER, 0);
1063     }
1064 
1065     public void testDatatype_OneDot() throws Exception {
1066         Parser parser = newParser("cheese.Toast");
1067 
1068         CSTNode root = parser.datatype();
1069 
1070         assertNode(root, ".", Token.DOT, 2);
1071         {
1072             assertNode(root.getChild(0), "cheese", Token.IDENTIFIER, 0);
1073 
1074             assertNode(root.getChild(1), "Toast", Token.IDENTIFIER, 0);
1075         }
1076     }
1077 
1078     public void testDatatype_TwoDots() throws Exception {
1079         Parser parser = newParser("toast.is.Bread");
1080 
1081         CSTNode root = parser.datatype();
1082 
1083         assertNode(root, ".", Token.DOT, 2);
1084         {
1085             assertNode(root.getChild(0), ".", Token.DOT, 2);
1086             {
1087                 assertNode(root.getChild(0).getChild(0), "toast", Token.IDENTIFIER, 0);
1088 
1089                 assertNode(root.getChild(0).getChild(1), "is", Token.IDENTIFIER, 0);
1090             }
1091 
1092             assertNode(root.getChild(1), "Bread", Token.IDENTIFIER, 0);
1093         }
1094     }
1095 
1096     // ----------------------------------------------------------------------
1097     // ----------------------------------------------------------------------
1098 
1099     protected void assertNullNode(CSTNode node, int numChildren) {
1100         assertNotNull(node);
1101         assertNull(node.getToken());
1102         assertLength(numChildren, node.getChildren());
1103     }
1104 
1105     protected void assertNode(CSTNode node, String text, int type) {
1106         assertNotNull(node);
1107         assertNotNull(node.getToken());
1108         assertEquals(text, node.getToken().getText());
1109         assertEquals(type, node.getToken().getType());
1110     }
1111 
1112     protected void assertNode(CSTNode node, String text, int type, int numChildren) {
1113         assertNotNull("Node should not be null!", node);
1114         assertNotNull(node.getToken());
1115         assertEquals(text, node.getToken().getText());
1116         assertEquals(type, node.getToken().getType());
1117         assertLength(numChildren, node.getChildren());
1118     }
1119 
1120     protected void assertToken(Token token, String text, int type) {
1121         assertNotNull(token);
1122         assertEquals(text, token.getText());
1123         assertEquals(type, token.getType());
1124     }
1125 
1126     protected Parser newParser(String text) {
1127         CharStream chars = new StringCharStream(text);
1128         Lexer lexer = new Lexer(chars);
1129         TokenStream tokens = new LexerTokenStream(lexer);
1130 
1131         return new Parser(tokens);
1132     }
1133 */
1134 }