1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.codehaus.groovy.syntax.parser;
47
48 import java.util.HashMap;
49 import java.util.Map;
50 import java.util.List;
51 import java.util.ArrayList;
52
53 import groovy.lang.BitwiseNegateEvaluatingException;
54 import org.codehaus.groovy.ast.ClassNode;
55 import org.codehaus.groovy.ast.InnerClassNode;
56 import org.codehaus.groovy.ast.ConstructorNode;
57 import org.codehaus.groovy.ast.MethodNode;
58 import org.codehaus.groovy.ast.MixinNode;
59 import org.codehaus.groovy.ast.ModuleNode;
60 import org.codehaus.groovy.ast.Parameter;
61 import org.codehaus.groovy.ast.PropertyNode;
62 import org.codehaus.groovy.ast.Type;
63 import org.codehaus.groovy.ast.expr.ArrayExpression;
64 import org.codehaus.groovy.ast.expr.BinaryExpression;
65 import org.codehaus.groovy.ast.expr.BooleanExpression;
66 import org.codehaus.groovy.ast.expr.CastExpression;
67 import org.codehaus.groovy.ast.expr.ClassExpression;
68 import org.codehaus.groovy.ast.expr.ClosureExpression;
69 import org.codehaus.groovy.ast.expr.ConstantExpression;
70 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
71 import org.codehaus.groovy.ast.expr.Expression;
72 import org.codehaus.groovy.ast.expr.GStringExpression;
73 import org.codehaus.groovy.ast.expr.ListExpression;
74 import org.codehaus.groovy.ast.expr.MapExpression;
75 import org.codehaus.groovy.ast.expr.MethodCallExpression;
76 import org.codehaus.groovy.ast.expr.NegationExpression;
77 import org.codehaus.groovy.ast.expr.BitwiseNegExpression;
78 import org.codehaus.groovy.ast.expr.NotExpression;
79 import org.codehaus.groovy.ast.expr.PostfixExpression;
80 import org.codehaus.groovy.ast.expr.PrefixExpression;
81 import org.codehaus.groovy.ast.expr.PropertyExpression;
82 import org.codehaus.groovy.ast.expr.RangeExpression;
83 import org.codehaus.groovy.ast.expr.RegexExpression;
84 import org.codehaus.groovy.ast.expr.TernaryExpression;
85 import org.codehaus.groovy.ast.expr.TupleExpression;
86 import org.codehaus.groovy.ast.expr.VariableExpression;
87 import org.codehaus.groovy.ast.stmt.AssertStatement;
88 import org.codehaus.groovy.ast.stmt.BlockStatement;
89 import org.codehaus.groovy.ast.stmt.BreakStatement;
90 import org.codehaus.groovy.ast.stmt.CaseStatement;
91 import org.codehaus.groovy.ast.stmt.CatchStatement;
92 import org.codehaus.groovy.ast.stmt.ContinueStatement;
93 import org.codehaus.groovy.ast.stmt.DoWhileStatement;
94 import org.codehaus.groovy.ast.stmt.EmptyStatement;
95 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
96 import org.codehaus.groovy.ast.stmt.ForStatement;
97 import org.codehaus.groovy.ast.stmt.IfStatement;
98 import org.codehaus.groovy.ast.stmt.ReturnStatement;
99 import org.codehaus.groovy.ast.stmt.Statement;
100 import org.codehaus.groovy.ast.stmt.SwitchStatement;
101 import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
102 import org.codehaus.groovy.ast.stmt.ThrowStatement;
103 import org.codehaus.groovy.ast.stmt.TryCatchStatement;
104 import org.codehaus.groovy.ast.stmt.WhileStatement;
105 import org.codehaus.groovy.control.SourceUnit;
106 import org.codehaus.groovy.syntax.CSTNode;
107 import org.codehaus.groovy.syntax.Token;
108 import org.codehaus.groovy.syntax.Types;
109 import org.codehaus.groovy.syntax.Numbers;
110 import org.codehaus.groovy.GroovyBugError;
111 import org.objectweb.asm.Constants;
112
113
114
115 /***
116 * Builds an Abstract Syntax Tree from the Concrete Syntax Tree produced
117 * by the Parser. The resulting AST is very preliminary, and must still
118 * be validated and massaged before it is ready to be used.
119 * <code>build()</code> is the primary entry point.
120 *
121 * @author James Strachan
122 * @author Bob McWhirter
123 * @author Sam Pullara
124 * @author Chris Poirier
125 */
126
127 public class ASTBuilder extends ASTHelper
128 {
129
130 public ASTBuilder( SourceUnit sourceUnit, ClassLoader classLoader )
131 {
132 super(sourceUnit, classLoader);
133 }
134
135
136
137
138
139
140
141
142 /***
143 * Builds an AST ModuleNode from a Parser.module() Reduction.
144 */
145
146 public ModuleNode build( CSTNode input ) throws ParserException
147 {
148 makeModule();
149
150
151
152
153
154
155
156 setPackageName( packageDeclaration( input.get(1) ));
157
158 importStatements(input.get(2) );
159
160 for( int i = 3; i < input.size(); ++i )
161 {
162 topLevelStatement( output, input.get(i) );
163 }
164
165 if( output.isEmpty() )
166 {
167 output.addStatement( new BlockStatement() );
168 }
169
170 return output;
171 }
172
173
174
175
176
177
178
179
180 /***
181 * Processes the Reduction produced by Parser.packageDeclaration().
182 */
183
184 protected String packageDeclaration( CSTNode reduction )/package-summary.html">ong> String packageDeclaration( CSTNode reduction )
185 {
186 if( reduction.hasChildren() )
187 {
188 return makeName( reduction.get(1) );
189 }
190
191 return null;
192
193 }
194
195
196
197 /***
198 * Processes the imports Reduction produced by Parser.module().
199 */
200
201 protected void importStatements(CSTNode container)
202 {
203 for( int i = 1; i < container.size(); ++i)
204 {
205 importStatement( container.get(i) );
206 }
207 }
208
209
210
211 /***
212 * Processes the Reduction produced by Parser.importStatement().
213 */
214
215 protected void importStatement(CSTNode reduction)
216 {
217
218
219
220 String importPackage = makeName( reduction.get(1), null );
221
222
223
224
225
226
227 if( reduction.get(2).isA(Types.STAR) )
228 {
229 importPackageWithStar(importPackage);
230 }
231
232
233
234
235
236 else
237 {
238 for( int i = 2; i < reduction.size(); i++ )
239 {
240 CSTNode clause = reduction.get(i);
241 String name = identifier( clause );
242 String as = (clause.hasChildren() ? identifier(clause.get(1)) : name);
243
244 importClass(importPackage, name, as);
245
246 }
247 }
248 }
249
250
251 /***
252 * Processes the Reduction produced by Parser.topLevelStatement().
253 */
254
255 protected void topLevelStatement( ModuleNode module, CSTNode reduction ) throws ParserException
256 {
257 int type = reduction.getMeaning();
258 switch( type )
259 {
260 case Types.SYNTH_CLASS:
261 module.addClass( classDeclaration(null, reduction) );
262 break;
263
264 case Types.SYNTH_INTERFACE:
265 module.addClass( interfaceDeclaration(null, reduction) );
266 break;
267
268 case Types.SYNTH_METHOD:
269 module.addMethod( methodDeclaration(null, reduction) );
270 break;
271
272 default:
273 module.addStatement( statement(reduction) );
274 break;
275 }
276
277 }
278
279
280
281 /***
282 * Processes the Reduction produced by Parser.classDeclaration().
283 */
284
285 protected ClassNode classDeclaration( ClassNode context, CSTNode reduction ) throws ParserException
286 {
287
288
289
290 String name = identifier( reduction );
291 addNewClassName(name);
292 int modifiers = modifiers( reduction.get(1) );
293 String parent = resolveName( reduction.get(2).get(1) );
294
295
296
297
298
299 CSTNode interfaceReduction = reduction.get(3);
300 String[] interfaces = new String[interfaceReduction.children()];
301 for( int i = 1; i < interfaceReduction.size(); i++ )
302 {
303 interfaces[i-1] = resolveName( interfaceReduction.get(i) );
304 }
305
306
307
308
309
310 ClassNode classNode = (
311 context == null
312 ? new ClassNode( dot(getPackageName(), name), modifiers, parent, interfaces, MixinNode.EMPTY_ARRAY )
313 : new InnerClassNode( context, dot(getPackageName(), name), modifiers, parent, interfaces, MixinNode.EMPTY_ARRAY )
314 );
315
316 classNode.setCSTNode( reduction.get(0) );
317 typeBody( classNode, reduction.get(4), 0, 0 );
318 return classNode;
319 }
320
321
322 /***
323 * Processes a type body for classDeclaration() and others.
324 */
325
326 protected void typeBody( ClassNode classNode, CSTNode body, int propertyModifiers, int methodModifiers ) throws ParserException
327 {
328 for( int i = 1; i < body.size(); i++ )
329 {
330 CSTNode statement = body.get(i);
331 switch( statement.getMeaning() )
332 {
333 case Types.SYNTH_PROPERTY:
334 addPropertyDeclaration( classNode, statement, propertyModifiers );
335 break;
336
337 case Types.SYNTH_METHOD:
338 methodDeclaration( classNode, statement, methodModifiers );
339 break;
340
341 case Types.SYNTH_CLASS:
342 classDeclaration( classNode, statement );
343 break;
344
345 case Types.SYNTH_INTERFACE:
346 interfaceDeclaration( classNode, statement );
347 break;
348
349 default:
350 throw new GroovyBugError( "unrecognized type body statement [" + statement.toString() + "]" );
351 }
352 }
353 }
354
355
356
357 /***
358 * Processes the Reduction produced by Parser.propertyDeclaration().
359 * Adds the property to the supplied class.
360 */
361
362 protected void addPropertyDeclaration( ClassNode classNode, CSTNode reduction, int extraModifiers ) throws ParserException
363 {
364 String name = identifier( reduction );
365 int modifiers = modifiers( reduction.get(1) ) | extraModifiers;
366 String type = resolveName( reduction.get(2) );
367
368 Expression value = reduction.size() > 3 ? expression(reduction.get(3)) : null;
369
370 PropertyNode propertyNode = classNode.addProperty( name, modifiers, type, value, null, null );
371 propertyNode.setCSTNode( reduction.get(0) );
372
373 }
374
375
376
377 /***
378 * A synonym for <code>addPropertyDeclaration( classNode, reduction, 0 )</code>.
379 */
380
381 protected void addPropertyDeclaration( ClassNode classNode, CSTNode reduction ) throws ParserException
382 {
383 addPropertyDeclaration( classNode, reduction, 0 );
384 }
385
386
387
388 /***
389 * Processes the Reduction produced by Parser.methodDeclaration().
390 * Adds the method to the supplied class.
391 */
392
393 protected MethodNode methodDeclaration( ClassNode classNode, CSTNode reduction, int extraModifiers ) throws ParserException
394 {
395 String className = null;
396 if( classNode != null )
397 {
398 className = classNode.getNameWithoutPackage();
399 }
400
401
402
403
404
405 String name = identifier( reduction );
406 int modifiers = modifiers( reduction.get(1) ) | extraModifiers;
407 String type = resolveName( reduction.get(2) );
408
409 Parameter[] parameters = parameterDeclarations( reduction.get(3) );
410 BlockStatement body = statementBody( reduction.get(5) );
411
412
413
414
415
416 CSTNode clause = reduction.get(4);
417 String[] throwTypes = new String[clause.children()];
418 for( int i = 1; i < clause.size(); i++ )
419 {
420 throwTypes[i-1] = resolveName( clause.get(i) );
421 }
422
423 if( clause.hasChildren() ) { throw new GroovyBugError( "NOT YET IMPLEMENTED: throws clause" ); }
424
425
426
427
428
429 if( name.length() == 0 )
430 {
431 throw new GroovyBugError( "NOT YET IMPLEMENTED: static initializers" );
432
433
434
435
436
437
438
439
440
441
442 }
443
444
445
446
447
448 else if( className != null && name.equals(className) )
449 {
450 ConstructorNode node = new ConstructorNode( modifiers, parameters, body );
451 node.setCSTNode( reduction.get(0) );
452
453 classNode.addConstructor( node );
454 return null;
455 }
456
457
458
459
460
461 else
462 {
463 MethodNode method = new MethodNode( name, modifiers, type, parameters, body );
464 method.setCSTNode( reduction.get(0) );
465
466 if( classNode != null )
467 {
468 classNode.addMethod( method );
469 }
470
471 return method;
472 }
473
474 }
475
476
477
478 /***
479 * A synonym for <code>methodDeclaration( classNode, reduction, 0 )</code>.
480 */
481
482 protected MethodNode methodDeclaration( ClassNode classNode, CSTNode reduction ) throws ParserException
483 {
484 return methodDeclaration( classNode, reduction, 0 );
485 }
486
487
488
489 /***
490 * Processes the Reduction produced by Parser.parameterDeclarationList().
491 */
492
493 protected Parameter[] parameterDeclarations( CSTNode reduction ) throws ParserException
494 {
495 Parameter[] parameters = new Parameter[ reduction.children() ];
496
497 for( int i = 1; i < reduction.size(); i++ )
498 {
499 CSTNode node = reduction.get(i);
500
501 String identifier = identifier( node );
502 String type = resolveName( node.get(1) );
503
504 if( node.size() > 2 )
505 {
506 parameters[i-1] = new Parameter( type, identifier, expression(node.get(2)) );
507 }
508 else
509 {
510 parameters[i-1] = new Parameter( type, identifier );
511 }
512 }
513
514 return parameters;
515
516 }
517
518
519
520 /***
521 * Processes the Reduction produced by Parser.interfaceDeclaration().
522 */
523
524 protected ClassNode interfaceDeclaration( ClassNode context, CSTNode reduction ) throws ParserException
525 {
526 throw new GroovyBugError( "NOT YET IMPLEMENTED: interfaces" );
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569 }
570
571
572
573
574
575
576
577
578 /***
579 * Processes the Reduction that results from Parser.statementBody().
580 */
581
582 protected BlockStatement statementBody( CSTNode reduction ) throws ParserException
583 {
584 if( reduction.isEmpty() )
585 {
586 return new BlockStatement();
587 }
588 else if( reduction.getMeaning() == Types.LEFT_CURLY_BRACE )
589 {
590 return statementBlock( reduction );
591 }
592 else
593 {
594 Statement statement = statement( reduction );
595 statement.setCSTNode( reduction );
596
597 BlockStatement block = null;
598 if( statement instanceof BlockStatement )
599 {
600 block = (BlockStatement)statement;
601 }
602 else
603 {
604 block = new BlockStatement();
605 block.addStatement( statement );
606 }
607
608 return block;
609 }
610 }
611
612
613
614 /***
615 * Processes any series of statements, starting at the specified offset
616 * and running to the end of the CSTNode.
617 */
618
619 protected BlockStatement statements( CSTNode reduction, int first ) throws ParserException
620 {
621 BlockStatement block = new BlockStatement();
622
623 for( int i = first; i < reduction.size(); i++ )
624 {
625 CSTNode statementReduction = reduction.get(i);
626
627 Statement statement = statement( statementReduction );
628 statement.setCSTNode( statementReduction );
629
630 block.addStatement( statement );
631 }
632
633 return block;
634 }
635
636
637
638 /***
639 * Processes any statement block.
640 */
641
642 protected BlockStatement statementBlock( CSTNode reduction ) throws ParserException
643 {
644 return statements( reduction, 1 );
645 }
646
647
648
649 /***
650 * Processes the Reduction produced by Parser.statement().
651 */
652
653 protected Statement statement( CSTNode reduction ) throws ParserException
654 {
655 Statement statement = null;
656
657
658
659
660 switch( reduction.getMeaning() )
661 {
662 case Types.KEYWORD_ASSERT:
663 {
664 statement = assertStatement( reduction );
665 break;
666 }
667
668 case Types.KEYWORD_BREAK:
669 {
670 statement = breakStatement( reduction );
671 break;
672 }
673
674 case Types.KEYWORD_CONTINUE:
675 {
676 statement = continueStatement( reduction );
677 break;
678 }
679
680 case Types.KEYWORD_IF:
681 {
682 statement = ifStatement( reduction );
683 break;
684 }
685
686 case Types.KEYWORD_RETURN:
687 {
688 statement = returnStatement( reduction );
689 break;
690 }
691
692 case Types.KEYWORD_SWITCH:
693 {
694 statement = switchStatement( reduction );
695 break;
696 }
697
698 case Types.KEYWORD_SYNCHRONIZED:
699 {
700 statement = synchronizedStatement( reduction );
701 break;
702 }
703
704 case Types.KEYWORD_THROW:
705 {
706 statement = throwStatement( reduction );
707 break;
708 }
709
710 case Types.KEYWORD_TRY:
711 {
712 statement = tryStatement( reduction );
713 break;
714 }
715
716 case Types.KEYWORD_FOR:
717 {
718 statement = forStatement( reduction );
719 break;
720 }
721
722 case Types.KEYWORD_WHILE:
723 {
724 statement = whileStatement( reduction );
725 break;
726 }
727
728 case Types.KEYWORD_DO:
729 {
730 statement = doWhileStatement( reduction );
731 break;
732 }
733
734 case Types.SYNTH_BLOCK:
735 case Types.LEFT_CURLY_BRACE:
736 {
737 statement = statementBlock( reduction );
738 break;
739 }
740
741 case Types.SYNTH_LABEL:
742 {
743 statement = statement( reduction.get(1) );
744 statement.setStatementLabel( identifier(reduction) );
745 break;
746 }
747
748 case Types.SYNTH_CLOSURE:
749 default:
750 {
751 statement = expressionStatement( reduction );
752 break;
753 }
754
755 }
756
757
758 statement.setCSTNode( reduction );
759 return statement;
760 }
761
762
763
764 /***
765 * Processes the Reduction produced by Parser.assertStatement().
766 */
767
768 protected AssertStatement assertStatement( CSTNode reduction ) throws ParserException
769 {
770 BooleanExpression expression = new BooleanExpression( expression(reduction.get(1)) );
771
772 if( reduction.children() > 1 )
773 {
774 return new AssertStatement( expression, expression(reduction.get(2)) );
775 }
776
777 return new AssertStatement( expression, ConstantExpression.NULL );
778 }
779
780
781
782 /***
783 * Processes the Reduction produced by Parser.breakStatement().
784 */
785
786 protected BreakStatement breakStatement( CSTNode reduction ) throws ParserException
787 {
788 if( reduction.hasChildren() )
789 {
790 return new BreakStatement( reduction.get(1).getRootText() );
791 }
792
793 return new BreakStatement();
794 }
795
796
797
798 /***
799 * Processes the Reduction produced by Parser.continueStatement().
800 */
801
802 protected ContinueStatement continueStatement( CSTNode reduction ) throws ParserException
803 {
804
805 if( reduction.hasChildren() )
806 {
807 return new ContinueStatement( reduction.get(1).getRootText() );
808 }
809
810 return new ContinueStatement();
811 }
812
813
814
815 /***
816 * Processes the Reduction produced by Parser.ifStatement().
817 */
818
819 protected IfStatement ifStatement( CSTNode reduction ) throws ParserException
820 {
821 Expression condition = expression( reduction.get(1) );
822 BlockStatement body = statementBody( reduction.get(2) );
823 Statement elseBlock = EmptyStatement.INSTANCE;
824
825 if( reduction.size() > 3 )
826 {
827 CSTNode elseReduction = reduction.get(3);
828 if( elseReduction.getMeaning() == Types.KEYWORD_IF )
829 {
830 elseBlock = ifStatement( elseReduction );
831 }
832 else
833 {
834 elseBlock = statementBody( elseReduction.get(1) );
835 }
836
837 }
838
839 return new IfStatement( new BooleanExpression(condition), body, elseBlock );
840 }
841
842
843
844 /***
845 * Processes the Reduction produced by Parser.returnStatement().
846 */
847
848 protected ReturnStatement returnStatement( CSTNode reduction ) throws ParserException
849 {
850 if( reduction.hasChildren() )
851 {
852 return new ReturnStatement( expression(reduction.get(1)) );
853 }
854
855 return ReturnStatement.RETURN_NULL_OR_VOID;
856 }
857
858
859
860 /***
861 * Processes the Reduction produced by Parser.switchStatement().
862 */
863
864 protected SwitchStatement switchStatement( CSTNode reduction ) throws ParserException
865 {
866 SwitchStatement statement = new SwitchStatement( expression(reduction.get(1)) );
867
868 for( int i = 2; i < reduction.size(); i++ )
869 {
870 CSTNode child = reduction.get(i);
871
872 switch( child.getMeaning() )
873 {
874
875 case Types.KEYWORD_CASE:
876 statement.addCase( caseStatement(child) );
877 break;
878
879 case Types.KEYWORD_DEFAULT:
880 statement.setDefaultStatement( statementBlock(child) );
881 break;
882
883 default:
884 throw new GroovyBugError( "invalid something in switch [" + child + "]" );
885 }
886 }
887
888 return statement;
889 }
890
891
892
893 /***
894 * Processes the Reduction produced by Parser.switchStatement() for cases.
895 */
896
897 protected CaseStatement caseStatement( CSTNode reduction ) throws ParserException
898 {
899 return new CaseStatement( expression(reduction.get(1)), statements(reduction, 2) );
900 }
901
902
903
904 /***
905 * Processes the Reduction produced by Parser.synchronizedStatement().
906 */
907
908 protected SynchronizedStatement synchronizedStatement( CSTNode reduction ) throws ParserException
909 {
910 return new SynchronizedStatement( expression(reduction.get(1)), statementBody(reduction.get(2)) );
911 }
912
913
914
915 /***
916 * Processes the Reduction produced by Parser.throwStatement().
917 */
918
919 protected ThrowStatement throwStatement( CSTNode reduction ) throws ParserException
920 {
921 return new ThrowStatement( expression(reduction.get(1)) );
922 }
923
924
925
926 /***
927 * Processes the Reduction produced by Parser.tryStatement().
928 */
929
930 protected TryCatchStatement tryStatement( CSTNode reduction ) throws ParserException
931 {
932 BlockStatement body = statementBody( reduction.get(1) );
933 BlockStatement finallyBlock = statementBody( reduction.get(3) );
934
935 TryCatchStatement statement = new TryCatchStatement( body, finallyBlock );
936
937 CSTNode catches = reduction.get(2);
938 for( int i = 1; i < catches.size(); i++ )
939 {
940 CSTNode element = catches.get(i);
941 String type = resolveName( element.get(1) );
942 String identifier = identifier( element.get(2) );
943
944 statement.addCatch( new CatchStatement(type, identifier, statementBody(element.get(3))) );
945 }
946
947 return statement;
948 }
949
950
951
952 /***
953 * Processes the Reduction produced by Parser.forStatement().
954 */
955
956 protected ForStatement forStatement( CSTNode reduction ) throws ParserException
957 {
958 CSTNode header = reduction.get(1);
959 Statement body = statementBody( reduction.get(2) );
960
961
962
963
964
965 if( header.getMeaning() == Types.UNKNOWN )
966 {
967 Expression[] init = expressions( header.get(1) );
968 Expression test = expression( header.get(2) );
969 Expression[] incr = expressions( header.get(3) );
970
971 throw new GroovyBugError( "NOT YET IMPLEMENTED: standard for loop" );
972 }
973
974
975
976
977
978 else
979 {
980
981 Type type = typeExpression( header.get(1) );
982 String identifier = identifier( header.get(2) );
983 Expression source = expression( header.get(3) );
984
985 return new ForStatement( identifier, type, source, body );
986 }
987 }
988
989
990
991 /***
992 * Processes the Reduction produced by Parser.doWhileStatement().
993 */
994
995 protected DoWhileStatement doWhileStatement( CSTNode reduction ) throws ParserException
996 {
997 Expression condition = expression( reduction.get(2) );
998 BlockStatement body = statementBody( reduction.get(1) );
999
1000 return new DoWhileStatement( new BooleanExpression(condition), body );
1001 }
1002
1003
1004
1005 /***
1006 * Processes the Reduction produced by Parser.whileStatement().
1007 */
1008
1009 protected WhileStatement whileStatement( CSTNode reduction ) throws ParserException
1010 {
1011 Expression condition = expression( reduction.get(1) );
1012 BlockStatement body = statementBody( reduction.get(2) );
1013
1014 return new WhileStatement( new BooleanExpression(condition), body );
1015
1016 }
1017
1018
1019
1020
1021
1022
1023
1024
1025 /***
1026 * Processes any expression that forms a complete statement.
1027 */
1028
1029 protected Statement expressionStatement( CSTNode node ) throws ParserException
1030 {
1031 return new ExpressionStatement( expression(node) );
1032 }
1033
1034
1035
1036 /***
1037 * Processes a series of expression to an Expression[].
1038 */
1039
1040 protected Expression[] expressions( CSTNode reduction ) throws ParserException
1041 {
1042 Expression[] expressions = new Expression[ reduction.children() ];
1043
1044 for( int i = 1; i < reduction.size(); i++ )
1045 {
1046 expressions[i-1] = expression( reduction.get(i) );
1047 }
1048
1049 return expressions;
1050 }
1051
1052
1053
1054 /***
1055 * Processes the CSTNode produced by Parser.expression().
1056 */
1057
1058 protected Expression expression( CSTNode reduction ) throws ParserException
1059 {
1060 Expression expression = null;
1061
1062 int type = reduction.getMeaningAs( EXPRESSION_HANDLERS );
1063 switch( type )
1064 {
1065 case Types.SYNTHETIC:
1066 {
1067 expression = syntheticExpression( reduction );
1068 break;
1069 }
1070
1071 case Types.RANGE_OPERATOR:
1072 {
1073 Expression from = expression( reduction.get(1) );
1074 Expression to = expression( reduction.get(2) );
1075
1076 expression = new RangeExpression( from, to, reduction.getMeaning() == Types.DOT_DOT );
1077 break;
1078 }
1079
1080
1081 case Types.LEFT_SQUARE_BRACKET:
1082 case Types.INFIX_OPERATOR:
1083 {
1084 expression = infixExpression( reduction );
1085 break;
1086 }
1087
1088
1089 case Types.REGEX_PATTERN:
1090 {
1091 CSTNode body = reduction.get(1);
1092 Token token = body.getRoot();
1093 String text = body.getRootText();
1094
1095 if ( body.isA(Types.SYNTH_GSTRING) )
1096 {
1097 expression = new RegexExpression( expression(reduction.get(1)) );
1098 }
1099 else
1100 {
1101 expression = new BitwiseNegExpression( expression(body) );
1102 }
1103 break;
1104 }
1105
1106
1107 case Types.PREFIX_OPERATOR:
1108 {
1109 expression = prefixExpression( reduction );
1110 break;
1111 }
1112
1113
1114 case Types.POSTFIX_OPERATOR:
1115 {
1116 Expression body = expression( reduction.get(1) );
1117 expression = new PostfixExpression( body, reduction.getRoot() );
1118 break;
1119 }
1120
1121
1122 case Types.SIMPLE_EXPRESSION:
1123 {
1124 expression = simpleExpression( reduction );
1125 break;
1126 }
1127
1128
1129 case Types.KEYWORD_NEW:
1130 {
1131 expression = newExpression( reduction );
1132 break;
1133 }
1134
1135 default:
1136 throw new GroovyBugError( "unhandled CST: [" + reduction.toString() + "]" );
1137
1138 }
1139
1140 if( expression == null )
1141 {
1142 throw new GroovyBugError( "expression produced null: [" + reduction.toString() + "]" );
1143 }
1144
1145 expression.setCSTNode( reduction );
1146 return expression;
1147 }
1148
1149
1150 public static final int[] EXPRESSION_HANDLERS = {
1151 Types.SYNTHETIC
1152 , Types.RANGE_OPERATOR
1153 , Types.LEFT_SQUARE_BRACKET
1154 , Types.INFIX_OPERATOR
1155 , Types.REGEX_PATTERN
1156 , Types.PREFIX_OPERATOR
1157 , Types.POSTFIX_OPERATOR
1158 , Types.SIMPLE_EXPRESSION
1159 , Types.KEYWORD_NEW
1160 };
1161
1162
1163
1164
1165 /***
1166 * Processes most infix operators.
1167 */
1168
1169 public Expression infixExpression( CSTNode reduction ) throws ParserException
1170 {
1171 Expression expression;
1172
1173 int type = reduction.getMeaning();
1174 switch( type )
1175 {
1176 case Types.DOT:
1177 case Types.NAVIGATE:
1178 {
1179 String name = reduction.get(2).getRootText();
1180
1181 Expression context = null;
1182 if( name.equals("class") )
1183 {
1184 CSTNode node = reduction.get(1);
1185 if( node.isA(Types.LEFT_SQUARE_BRACKET) && node.children() == 1 )
1186 {
1187 throw new GroovyBugError( "NOT YET IMPLEMENTED: .class for array types" );
1188
1189 }
1190 }
1191
1192 if( context == null )
1193 {
1194 context = expression( reduction.get(1) );
1195 }
1196
1197 expression = new PropertyExpression( context, name, type == Types.NAVIGATE );
1198 break;
1199 }
1200
1201
1202 case Types.KEYWORD_INSTANCEOF:
1203 {
1204 Expression lhs = expression( reduction.get(1) );
1205 Expression rhs = classExpression( reduction.get(2) );
1206 expression = new BinaryExpression( lhs, reduction.getRoot(), rhs );
1207 break;
1208 }
1209
1210
1211 default:
1212 {
1213 Expression lhs = expression( reduction.get(1) );
1214 Expression rhs = expression( reduction.get(2) );
1215 expression = new BinaryExpression( lhs, reduction.getRoot(), rhs );
1216 break;
1217 }
1218 }
1219
1220 return expression;
1221 }
1222
1223
1224
1225 /***
1226 * Processes most prefix operators.
1227 */
1228
1229 public Expression prefixExpression( CSTNode reduction ) throws ParserException
1230 {
1231 Expression expression = null;
1232 CSTNode body = reduction.get(1);
1233
1234 int type = reduction.getMeaning();
1235 switch( type )
1236 {
1237 case Types.PREFIX_MINUS:
1238 if( body.size() == 1 && body.isA(Types.NUMBER) )
1239 {
1240 expression = numericExpression( body, true );
1241 }
1242 else
1243 {
1244 expression = new NegationExpression( expression(body) );
1245 }
1246 break;
1247
1248 case Types.PREFIX_PLUS:
1249 expression = expression(body);
1250 break;
1251
1252 case Types.NOT:
1253 expression = new NotExpression( expression(body) );
1254 break;
1255
1256 case Types.BITWISE_NEGATION:
1257 expression = new BitwiseNegExpression( expression(body) );
1258 break;
1259
1260 default:
1261 expression = new PrefixExpression( reduction.getRoot(), expression(body) );
1262 break;
1263 }
1264
1265 return expression;
1266 }
1267
1268
1269
1270 /***
1271 * Processes most simple expressions.
1272 */
1273
1274 public Expression simpleExpression( CSTNode reduction ) throws ParserException
1275 {
1276 Expression expression = null;
1277
1278 int type = reduction.getMeaning();
1279 switch( type )
1280 {
1281 case Types.KEYWORD_NULL:
1282 expression = ConstantExpression.NULL;
1283 break;
1284
1285 case Types.KEYWORD_TRUE:
1286 expression = ConstantExpression.TRUE;
1287 break;
1288
1289 case Types.KEYWORD_FALSE:
1290 expression = ConstantExpression.FALSE;
1291 break;
1292
1293 case Types.STRING:
1294 expression = new ConstantExpression( reduction.getRootText() );
1295 break;
1296
1297 case Types.INTEGER_NUMBER:
1298 case Types.DECIMAL_NUMBER:
1299 expression = numericExpression( reduction, false );
1300 break;
1301
1302 case Types.KEYWORD_SUPER:
1303 case Types.KEYWORD_THIS:
1304 expression = variableExpression( reduction );
1305 break;
1306
1307 case Types.IDENTIFIER:
1308 expression = variableOrClassExpression( reduction );
1309 break;
1310
1311 }
1312
1313 return expression;
1314 }
1315
1316
1317
1318 /***
1319 * Processes numeric literals.
1320 */
1321
1322 public Expression numericExpression( CSTNode reduction, boolean negate ) throws ParserException
1323 {
1324 Token token = reduction.getRoot();
1325 String text = reduction.getRootText();
1326 String signed = negate ? "-" + text : text;
1327
1328 boolean isInteger = (token.getMeaning() == Types.INTEGER_NUMBER);
1329
1330 try
1331 {
1332 Number number = isInteger ? Numbers.parseInteger(signed) : Numbers.parseDecimal(signed);
1333
1334 return new ConstantExpression( number );
1335 }
1336 catch( NumberFormatException e )
1337 {
1338 error( "numeric literal [" + signed + "] invalid or out of range for its type", token );
1339 }
1340
1341 throw new GroovyBugError( "this should never happen" );
1342 }
1343
1344
1345
1346 /***
1347 * Processes most synthetic expressions.
1348 */
1349
1350 public Expression syntheticExpression( CSTNode reduction ) throws ParserException
1351 {
1352 Expression expression = null;
1353
1354 int type = reduction.getMeaning();
1355 switch( type )
1356 {
1357 case Types.SYNTH_TERNARY:
1358 {
1359 BooleanExpression condition = new BooleanExpression( expression(reduction.get(1)) );
1360 Expression trueBranch = expression( reduction.get(2) );
1361 Expression falseBranch = expression( reduction.get(3) );
1362
1363 expression = new TernaryExpression( condition, trueBranch, falseBranch );
1364 break;
1365 }
1366
1367
1368 case Types.SYNTH_CAST:
1369 {
1370 String className = resolveName( reduction.get(1) );
1371 Expression body = expression( reduction.get(2) );
1372
1373 expression = new CastExpression( className, body );
1374 break;
1375 }
1376
1377
1378 case Types.SYNTH_VARIABLE_DECLARATION:
1379 {
1380 expression = variableDeclarationExpression( reduction );
1381 break;
1382 }
1383
1384
1385 case Types.SYNTH_METHOD_CALL:
1386 {
1387 expression = methodCallExpression( reduction );
1388 break;
1389 }
1390
1391
1392 case Types.SYNTH_CLOSURE:
1393 {
1394 expression = closureExpression( reduction );
1395 break;
1396 }
1397
1398
1399 case Types.SYNTH_GSTRING:
1400 {
1401 expression = gstringExpression( reduction );
1402 break;
1403 }
1404
1405
1406 case Types.SYNTH_LIST:
1407 {
1408 expression = listExpression( reduction );
1409 break;
1410 }
1411
1412
1413 case Types.SYNTH_MAP:
1414 {
1415 expression = mapExpression( reduction );
1416 break;
1417 }
1418 }
1419
1420 return expression;
1421 }
1422
1423
1424
1425
1426 /***
1427 * Converts a (typically IDENTIFIER) CSTNode to a ClassExpression, if valid,
1428 * or a VariableExpression otherwise.
1429 */
1430
1431 protected Expression variableOrClassExpression( CSTNode reduction ) throws ParserException
1432 {
1433 String className = resolveName( reduction, false );
1434
1435 if( className == null )
1436 {
1437 return variableExpression( reduction );
1438 }
1439 else
1440 {
1441 return new ClassExpression( className );
1442 }
1443 }
1444
1445
1446
1447 /***
1448 * Converts a CSTNode into a ClassExpression.
1449 */
1450
1451 protected ClassExpression classExpression( CSTNode reduction ) throws ParserException
1452 {
1453 String name = resolveName( reduction, true );
1454 return new ClassExpression( name );
1455 }
1456
1457
1458
1459 /***
1460 * Converts a (typically IDENTIFIER) CSTNode to a VariableExpression, if
1461 * valid.
1462 */
1463
1464 protected VariableExpression variableExpression( CSTNode reduction )
1465 {
1466 return new VariableExpression( reduction.getRootText(), null );
1467 }
1468
1469 protected VariableExpression variableExpression( CSTNode reduction, String type )
1470 {
1471 return new VariableExpression( reduction.getRootText(), type );
1472 }
1473
1474
1475
1476 /***
1477 * Converts an (possibly optional) type expression to a Type.
1478 */
1479
1480 protected Type typeExpression( CSTNode reduction )
1481 {
1482 String name = makeName( reduction, null );
1483 if( name == null )
1484 {
1485 return Type.DYNAMIC_TYPE;
1486 }
1487 else
1488 {
1489 return new Type( resolveName(name, true) );
1490 }
1491 }
1492
1493
1494
1495 /***
1496 * Processes the Reduction produced by parsing a typed variable
1497 * declaration.
1498 */
1499
1500 protected Expression variableDeclarationExpression( CSTNode reduction ) throws ParserException
1501 {
1502 String type = resolveName( reduction.get(1) );
1503
1504
1505
1506
1507
1508 if( reduction.size() == 3 )
1509 {
1510 CSTNode node = reduction.get(2);
1511
1512 VariableExpression name = variableExpression( node, type );
1513
1514
1515 Token symbol = Token.newSymbol( Types.EQUAL, -1, -1 );
1516
1517 return new BinaryExpression( name, symbol, expression(node.get(1)) );
1518 }
1519
1520
1521 throw new GroovyBugError( "NOT YET IMPLEMENTED: generalized variable declarations" );
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536 }
1537
1538
1539
1540 /***
1541 * Processes a SYNTH_METHOD_CALL Reduction produced by Parser.expression().
1542 */
1543
1544 protected MethodCallExpression methodCallExpression( CSTNode reduction ) throws ParserException
1545 {
1546 MethodCallExpression call = null;
1547
1548
1549
1550
1551 CSTNode descriptor = reduction.get(1);
1552 Expression context = null;
1553 boolean implicit = false;
1554 String method = "call";
1555 boolean safe = false;
1556
1557 int type = descriptor.getMeaning();
1558 switch( type )
1559 {
1560 case Types.KEYWORD_SUPER:
1561 {
1562 context = variableExpression( descriptor );
1563 method = identifier( descriptor );
1564 break;
1565 }
1566
1567 case Types.KEYWORD_THIS:
1568 {
1569 context = VariableExpression.THIS_EXPRESSION;
1570 method = identifier( descriptor );
1571 break;
1572 }
1573
1574 case Types.IDENTIFIER:
1575 {
1576 context = VariableExpression.THIS_EXPRESSION;
1577 method = identifier( descriptor );
1578 implicit = true;
1579 break;
1580 }
1581
1582 case Types.DOT:
1583 case Types.NAVIGATE:
1584 {
1585 context = expression( descriptor.get(1) );
1586 method = identifier( descriptor.get(2) );
1587 safe = type == Types.NAVIGATE;
1588 break;
1589 }
1590
1591 default:
1592 {
1593 context = expression( descriptor );
1594 break;
1595 }
1596 }
1597
1598
1599
1600
1601
1602 Expression parameters = parameterList( reduction.get(2) );
1603
1604
1605
1606 call = new MethodCallExpression( context, method, parameters );
1607 call.setImplicitThis( implicit );
1608 call.setSafe( safe );
1609
1610 return call;
1611 }
1612
1613
1614
1615 /***
1616 * Processes the Reduction produced by Parser.closureExpression().
1617 */
1618
1619 protected ClosureExpression closureExpression( CSTNode reduction ) throws ParserException
1620 {
1621 ClosureExpression expression = null;
1622
1623 Parameter[] parameters = parameterDeclarations( reduction.get(1) );
1624 expression = new ClosureExpression( parameters, statementBlock(reduction.get(2)) );
1625
1626 return expression;
1627 }
1628
1629
1630
1631 /***
1632 * Processes the Reduction produced by Parser.parameterList().
1633 */
1634
1635 protected Expression parameterList( CSTNode reduction ) throws ParserException
1636 {
1637 TupleExpression list = new TupleExpression();
1638
1639 for( int i = 1; i < reduction.size(); i++ )
1640 {
1641 CSTNode node = reduction.get(i);
1642 list.addExpression( expression(node) );
1643 }
1644
1645 return list;
1646 }
1647
1648
1649
1650 /***
1651 * Processes the Reduction produced by Parser.newExpression().
1652 */
1653
1654 protected Expression newExpression( CSTNode reduction ) throws ParserException
1655 {
1656 Expression expression = null;
1657 CSTNode typeNode = reduction.get(1);
1658 String type = resolveName( typeNode );
1659
1660
1661
1662
1663
1664 if( typeNode.getMeaning() == Types.LEFT_SQUARE_BRACKET )
1665 {
1666 CSTNode dimensions = reduction.get(2);
1667
1668
1669
1670
1671
1672
1673
1674
1675 if( typeNode.get(1).getMeaning() == Types.LEFT_SQUARE_BRACKET )
1676 {
1677 throw new GroovyBugError( "NOT YET IMPLEMENTED: multidimensional arrays" );
1678 }
1679 else
1680 {
1681 type = resolveName( typeNode.get(1) );
1682 }
1683
1684
1685
1686
1687
1688 if( dimensions.isEmpty() )
1689 {
1690 CSTNode data = reduction.get(3);
1691
1692 if( data.get(1, true).getMeaning() == Types.SYNTH_TUPLE )
1693 {
1694 throw new GroovyBugError( "NOT YET IMPLEMENTED: multidimensional arrays" );
1695 }
1696
1697 expression = new ArrayExpression( type, tupleExpression(data).getExpressions() );
1698 }
1699
1700
1701
1702
1703
1704 else
1705 {
1706 if( dimensions.size() > 2 )
1707 {
1708 throw new GroovyBugError( "NOT YET IMPLEMENTED: multidimensional arrays" );
1709
1710
1711
1712
1713
1714
1715 }
1716 else
1717 {
1718 expression = new ArrayExpression( type, expression(dimensions.get(1)) );
1719 }
1720 }
1721 }
1722
1723
1724
1725
1726
1727 else
1728 {
1729 Expression parameters = parameterList( reduction.get(2) );
1730
1731 if( reduction.size() > 3 )
1732 {
1733 throw new GroovyBugError( "NOT YET IMPLEMENTED: anonymous classes" );
1734 }
1735
1736 expression = new ConstructorCallExpression( type, parameters );
1737 }
1738
1739 return expression;
1740 }
1741
1742
1743
1744 /***
1745 * Processes the Reduction produced by Parser.newArrayInitializer().
1746 */
1747
1748 protected TupleExpression tupleExpression( CSTNode reduction ) throws ParserException
1749 {
1750 TupleExpression tuple = new TupleExpression();
1751
1752 for( int i = 1; i < reduction.size(); i++ )
1753 {
1754 CSTNode element = reduction.get(i);
1755
1756 if( element.getMeaning() == Types.SYNTH_TUPLE )
1757 {
1758 tuple.addExpression( tupleExpression(element) );
1759 }
1760 else
1761 {
1762 tuple.addExpression( expression(element) );
1763 }
1764 }
1765
1766 return tuple;
1767 }
1768
1769
1770
1771 /***
1772 * Processes the Reduction produced by Parser.gstring().
1773 */
1774
1775 protected Expression gstringExpression( CSTNode reduction ) throws ParserException
1776 {
1777 if( !reduction.hasChildren() )
1778 {
1779 return new ConstantExpression( "" );
1780 }
1781
1782 if( reduction.children() == 1 && reduction.get(1).getMeaning() == Types.STRING )
1783 {
1784 return expression( reduction.get(1) );
1785 }
1786
1787
1788 GStringExpression expression = new GStringExpression( reduction.getRootText() );
1789 boolean lastWasExpression = false;
1790
1791 for( int i = 1; i < reduction.size(); i++ )
1792 {
1793 CSTNode element = reduction.get(i);
1794 if( element.getMeaning() == Types.STRING )
1795 {
1796 ConstantExpression string = new ConstantExpression( element.getRootText() );
1797 string.setCSTNode( element );
1798
1799 expression.addString( string );
1800
1801 lastWasExpression = false;
1802 }
1803 else
1804 {
1805 if( lastWasExpression )
1806 {
1807 expression.addString( new ConstantExpression("") );
1808 }
1809
1810 lastWasExpression = true;
1811 expression.addValue( element.isEmpty() ? ConstantExpression.NULL : expression(element) );
1812 }
1813 }
1814
1815 return expression;
1816 }
1817
1818
1819
1820 /***
1821 * Processes one of the Reductions produced by Parser.listOrMapExpression().
1822 */
1823
1824 protected ListExpression listExpression( CSTNode reduction ) throws ParserException
1825 {
1826 ListExpression list = new ListExpression();
1827
1828 for( int i = 1; i < reduction.size(); i++ )
1829 {
1830 list.addExpression( expression(reduction.get(i)) );
1831 }
1832
1833 return list;
1834 }
1835
1836
1837
1838 /***
1839 * Processes the other Reduction produced by Parser.listOrMapExpression().
1840 */
1841
1842 protected MapExpression mapExpression( CSTNode reduction ) throws ParserException
1843 {
1844 MapExpression map = new MapExpression();
1845
1846 for( int i = 1; i < reduction.size(); i++ )
1847 {
1848 CSTNode element = reduction.get(i);
1849 Expression key = expression( element.get(1) );
1850 Expression value = expression( element.get(2) );
1851
1852 map.addMapEntryExpression( key, value );
1853 }
1854
1855 return map;
1856 }
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866 /***
1867 * Converts a CSTNode representation of a type name back into
1868 * a string.
1869 */
1870
1871 protected String makeName( CSTNode root, String defaultName )
1872 {
1873 if( root == null )
1874 {
1875 return defaultName;
1876 }
1877
1878 String name = "";
1879 switch( root.getMeaning() )
1880 {
1881 case Types.LEFT_SQUARE_BRACKET:
1882 {
1883 name = makeName( root.get(1) ) + "[]";
1884 break;
1885 }
1886
1887 case Types.DOT:
1888 {
1889 CSTNode node = root;
1890 while( node.isA(Types.DOT) )
1891 {
1892 name = "." + node.get(2).getRootText() + name;
1893 node = node.get(1);
1894 }
1895
1896 name = node.getRootText() + name;
1897 break;
1898 }
1899
1900 case Types.UNKNOWN:
1901 {
1902 name = defaultName;
1903 break;
1904 }
1905
1906 default:
1907 {
1908 name = root.getRootText();
1909 break;
1910 }
1911
1912 }
1913
1914 return name;
1915 }
1916
1917
1918
1919 /***
1920 * A synonym for <code>makeName( root, "java.lang.Object" )</code>.
1921 */
1922
1923 protected String makeName( CSTNode root )
1924 {
1925 return makeName( root, "" );
1926 }
1927
1928
1929
1930 /***
1931 * Returns the text of an identifier.
1932 */
1933
1934 protected String identifier( CSTNode identifier )
1935 {
1936 return identifier.getRootText();
1937 }
1938
1939
1940 /***
1941 * Builds a name from a CSTNode, then resolves it. Returns the resolved name
1942 * if available, or null, unless safe is set, in which case the built name
1943 * is returned instead of null.
1944 *
1945 * @todo we should actually remove all resolving code from the ASTBuilder and
1946 * move it into the verifier / analyser
1947 */
1948
1949 protected String resolveName( CSTNode root, boolean safe )
1950 {
1951 String name = makeName( root );
1952 if (name.length() == 0)
1953 return "";
1954 return resolveNewClassOrName(name, safe);
1955 }
1956
1957
1958 /***
1959 * A synonym for <code>resolveName( root, true )</code>.
1960 */
1961
1962 protected String resolveName( CSTNode root )
1963 {
1964 return resolveName( root, true );
1965 }
1966
1967
1968
1969
1970
1971
1972
1973
1974 /***
1975 * Returns the ASM Constant bits for the specified modifiers.
1976 */
1977
1978 protected int modifiers( CSTNode list )
1979 {
1980 int modifiers = 0;
1981
1982 for( int i = 1; i < list.size(); ++i )
1983 {
1984 SWITCH: switch( list.get(i).getMeaning() )
1985 {
1986 case Types.KEYWORD_PUBLIC:
1987 {
1988 modifiers |= Constants.ACC_PUBLIC;
1989 break SWITCH;
1990 }
1991
1992 case Types.KEYWORD_PROTECTED:
1993 {
1994 modifiers |= Constants.ACC_PROTECTED;
1995 break SWITCH;
1996 }
1997
1998 case Types.KEYWORD_PRIVATE:
1999 {
2000 modifiers |= Constants.ACC_PRIVATE;
2001 break SWITCH;
2002 }
2003
2004
2005 case Types.KEYWORD_ABSTRACT:
2006 {
2007 modifiers |= Constants.ACC_ABSTRACT;
2008 break SWITCH;
2009 }
2010
2011 case Types.KEYWORD_FINAL:
2012 {
2013 modifiers |= Constants.ACC_FINAL;
2014 break SWITCH;
2015 }
2016
2017 case Types.KEYWORD_NATIVE:
2018 {
2019 modifiers |= Constants.ACC_NATIVE;
2020 break SWITCH;
2021 }
2022
2023 case Types.KEYWORD_TRANSIENT:
2024 {
2025 modifiers |= Constants.ACC_TRANSIENT;
2026 break SWITCH;
2027 }
2028
2029 case Types.KEYWORD_VOLATILE:
2030 {
2031 modifiers |= Constants.ACC_VOLATILE;
2032 break SWITCH;
2033 }
2034
2035
2036 case Types.KEYWORD_SYNCHRONIZED:
2037 {
2038 modifiers |= Constants.ACC_SYNCHRONIZED;
2039 break SWITCH;
2040 }
2041 case Types.KEYWORD_STATIC:
2042 {
2043 modifiers |= Constants.ACC_STATIC;
2044 break SWITCH;
2045 }
2046
2047 }
2048 }
2049
2050
2051
2052
2053
2054 if( (modifiers & (Constants.ACC_PROTECTED | Constants.ACC_PRIVATE)) == 0 )
2055 {
2056 modifiers |= Constants.ACC_PUBLIC;
2057 }
2058
2059 return modifiers;
2060 }
2061
2062
2063
2064
2065
2066
2067
2068
2069 /***
2070 * Throws a <code>ParserException</code>.
2071 */
2072
2073 protected void error( String description, CSTNode node ) throws ParserException
2074 {
2075 throw new ParserException( description, node.getRoot() );
2076 }
2077
2078
2079 }