Charj: added some provisions for handling mainchares
[charm.git] / src / langs / charj / src / charj / translator / CharjEmitter.g
1 /**
2  * ANTLR (v3) Tree Parser for the Charj Language
3  */
4
5 tree grammar CharjEmitter;
6
7 options {
8     backtrack = true; 
9     memoize = true;
10     tokenVocab = Charj;
11     ASTLabelType = CharjAST;
12     output = template;
13 }
14
15
16 @header {
17 package charj.translator;
18 }
19
20
21 @members {
22     SymbolTable symtab = null;
23
24     PackageScope currentPackage = null;
25     ClassSymbol currentClass = null;
26     MethodSymbol currentMethod = null;
27     LocalScope currentLocalScope = null;
28
29     Translator translator_;
30     OutputMode mode_;
31
32     private boolean emitCC() { return mode_ == OutputMode.cc; }
33     private boolean emitCI() { return mode_ == OutputMode.ci; }
34     private boolean emitH() { return mode_ == OutputMode.h; }
35     private boolean debug() { return translator_.debug(); }
36
37     /**
38      *  Override ANTLR's token mismatch behavior so we throw exceptions early.
39      */
40     protected void mismatch(IntStream input, int ttype, BitSet follow)
41         throws RecognitionException {
42         throw new MismatchedTokenException(ttype, input);
43     }
44
45     /**
46      *  Override ANTLR's set mismatch behavior so we throw exceptions early.
47      */
48     public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow)
49         throws RecognitionException {
50         throw e;
51     }
52
53     /**
54      *  Test a list of CharjAST nodes to see if any of them has the given token
55      *  type.
56      */
57     public boolean listContainsToken(List<CharjAST> list, int tokenType) {
58         if (list == null) return false;
59         for (CharjAST node : list) {
60             if (node.token.getType() == tokenType) {
61                 return true;
62             }
63         }
64         return false;
65     }
66 }
67
68
69 // Replace default ANTLR generated catch clauses with this action, allowing early failure.
70 @rulecatch {
71     catch (RecognitionException re) {
72         reportError(re);
73         throw re;
74     }
75 }
76
77
78 // Starting point for parsing a Charj file.
79 charjSource[SymbolTable symtab, OutputMode m]
80 @init {
81     this.symtab = symtab;
82     this.translator_ = symtab.translator;
83     this.mode_ = m;
84 }
85     :   ^(CHARJ_SOURCE (p=packageDeclaration)? 
86         (i+=importDeclaration)* 
87         (t=typeDeclaration))
88         -> {emitCC()}? charjSource_cc(pd={$p.names}, ids={$i}, tds={$t.st}, debug={debug()})
89         -> {emitCI()}? charjSource_ci(pd={$p.names}, ids={$i}, tds={$t.st}, debug={debug()})
90         -> {emitH()}? charjSource_h(pd={$p.names}, ids={$i}, tds={$t.st}, debug={debug()})
91         ->
92     ;
93
94 packageDeclaration
95 returns [List names]
96     :   ^('package' (ids+=IDENT)+)
97         {
98             $names = $ids;
99         }
100         ->
101     ;
102     
103 importDeclaration
104 @init {
105     String importID = null;
106 }
107     :   ^('import' qualifiedIdentifier ds='.*'?)
108         {
109             importID = $qualifiedIdentifier.text;
110             if ($ds != null) {
111             }
112         }
113         {$ds == null}? // TODO: add support for importing x.*
114         -> {(emitCC() || emitH())}? importDeclaration_cc_h(
115             inc_id={importID.replace(".","/")},
116             use_id={importID.replace(".","::")})
117         ->
118     ;
119     
120 typeDeclaration
121     :   ^(TYPE 'class' IDENT (^('extends' su=type))? (^('implements' type+))? (csds+=classScopeDeclaration)*)
122         {
123             currentClass = (ClassSymbol)$IDENT.symbol;
124         }
125         -> {emitCC()}? classDeclaration_cc(
126                 sym={currentClass},
127                 ident={$IDENT.text}, 
128                 ext={$su.st}, 
129                 csds={$csds})
130         -> {emitH()}?  classDeclaration_h(
131                 sym={currentClass},
132                 ident={$IDENT.text}, 
133                 ext={$su.st}, 
134                 csds={$csds})
135         ->
136     |   ^('interface' IDENT (^('extends' type+))? interfaceScopeDeclaration*)
137         -> template(t={$text}) "/*INTERFACE-not implemented*/ <t>"
138     |   ^('enum' IDENT (^('implements' type+))? classScopeDeclaration*)
139         -> template(t={$text}) "/*ENUM-not implemented*/ <t>"
140     |   ^(TYPE chareType IDENT (^('extends' type))? (^('implements' type+))? (csds+=classScopeDeclaration)*)
141         {
142             currentClass = (ClassSymbol)$IDENT.symbol;
143         }
144         -> {emitCC()}? chareDeclaration_cc(
145                 sym={currentClass},
146                 ident={$IDENT.text}, 
147                 ext={$su.st}, 
148                 csds={$csds})
149         -> {emitCI()}? chareDeclaration_ci(
150                 sym={currentClass},
151                 chareType={$chareType.st},
152                 arrayDim={null},
153                 ident={$IDENT.text}, 
154                 ext={$su.st}, 
155                 csds={$csds})
156         -> {emitH()}? chareDeclaration_h(
157                 sym={currentClass},
158                 ident={$IDENT.text}, 
159                 ext={$su.st}, 
160                 csds={$csds})
161         ->
162     ;
163
164 chareType
165 @init {
166 $st = %{$start.getText()};
167 }
168     :   'chare'
169     |   'group'
170     |   'nodegroup'
171     |   'mainchare'
172     |   ^('chare_array' ARRAY_DIMENSION)
173         -> template(t={$ARRAY_DIMENSION.text}) "array [<t>]"
174     ;
175
176 enumConstant
177     :   ^(IDENT arguments?)
178         -> template(t={$text}) "/*enumConstant-not implemented*/ <t>"
179     ;
180
181 classScopeDeclaration
182 @init {
183   boolean entry = false;
184   List<String> modList = new ArrayList<String>();
185
186 }
187     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
188             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
189             b=block?)
190         { 
191             if ($m.st != null) {
192                 // determine whether this is an entry method
193                 entry = listContainsToken($m.start.getChildren(), ENTRY);
194                 for(Object o : $m.names)
195                   if(o.equals("entry")) continue;
196                   else modList.add(o.toString());
197             }
198         }
199         -> {emitCC()}? funcMethodDecl_cc(
200                 modl={modList}, 
201                 gtpl={$g.st}, 
202                 ty={$ty.text},
203                 id={$IDENT.text}, 
204                 fpl={$f.st}, 
205                 adl={$a.st},
206                 block={$b.st})
207         -> {emitH()}? funcMethodDecl_h(
208                 modl={modList}, 
209                 gtpl={$g.st}, 
210                 ty={$ty.text},
211                 id={$IDENT.text}, 
212                 fpl={$f.st}, 
213                 adl={$a.st},
214                 block={$b.st})
215         -> {(emitCI() && entry)}? funcMethodDecl_ci(
216                 modl={$m.st}, 
217                 gtpl={$g.st}, 
218                 ty={$ty.text},
219                 id={$IDENT.text}, 
220                 fpl={$f.st}, 
221                 adl={$a.st},
222                 block={$b.st})
223         ->
224     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
225         -> {emitCC() || emitH()}? class_var_decl(
226             modl={$modifierList.st},
227             type={$simpleType.st},
228             declList={$variableDeclaratorList.st})
229         ->
230     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
231         -> {emitCC() || emitH()}? class_var_decl(
232             modl={$modifierList.st},
233             type={$objectType.st},
234             declList={$variableDeclaratorList.st})
235         ->
236     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList b=block)
237         { 
238             // determine whether this is an entry method
239             if ($m.st != null) {
240                 entry = listContainsToken($m.start.getChildren(), ENTRY);
241             }
242         }
243         -> {emitCC()}? ctorDecl_cc(
244                 modl={$m.st}, 
245                 gtpl={$g.st}, 
246                 id={$IDENT.text}, 
247                 fpl={$f.st}, 
248                 block={$b.st})
249         -> {emitCI() && entry}? ctorDecl_ci(
250                 modl={$m.st}, 
251                 gtpl={$g.st}, 
252                 id={$IDENT.text}, 
253                 fpl={$f.st}, 
254                 block={$b.st})
255         -> {emitH()}? ctorDecl_h(
256                 modl={$m.st}, 
257                 gtpl={$g.st}, 
258                 id={$IDENT.text}, 
259                 fpl={$f.st}, 
260                 block={$b.st})
261         ->
262     ;
263     
264 interfaceScopeDeclaration
265     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? type IDENT formalParameterList arrayDeclaratorList?)
266         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
267     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
268         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
269     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
270         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
271     ;
272
273 variableDeclaratorList
274     :   ^(VAR_DECLARATOR_LIST (var_decls+=variableDeclarator)+)
275         -> var_decl_list(var_decls={$var_decls})
276     ;
277
278 variableDeclarator
279     :   ^(VAR_DECLARATOR id=variableDeclaratorId initializer=variableInitializer?)
280         -> var_decl(id={$id.st}, initializer={$initializer.st})
281     ;
282     
283 variableDeclaratorId
284     :   ^(IDENT adl=arrayDeclaratorList?)
285         -> var_decl_id(id={$IDENT.text}, arrayDeclList={$adl.st})
286     ;
287
288 variableInitializer
289     :   arrayInitializer
290         -> {$arrayInitializer.st}
291     |   expression
292         -> {$expression.st}
293     ;
294
295 arrayDeclaratorList
296     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
297         -> template(t={$text}) "<t>"
298     ;
299     
300 arrayInitializer
301     :   ^(ARRAY_INITIALIZER variableInitializer*)
302         -> template(t={$text}) "/* arrayInitializer-not implemented */ <t>"
303     ;
304
305 genericTypeParameterList
306     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
307         -> template(t={$text}) "/*GENERIC_TYPE_PARAM_LIST-not implemented*/ <t>"
308     ;
309
310 genericTypeParameter
311     :   ^(IDENT bound?)
312         -> template(t={$text}) "/*genericTypeParameter-not implemented*/ <t>"
313     ;
314         
315 bound
316     :   ^(EXTENDS_BOUND_LIST type+)
317         -> template(t={$text}) "/*EXTENDS_BOUND_LIST-not implemented*/ <t>"
318     ;
319
320 throwsClause
321     :   ^(THROWS_CLAUSE qualifiedIdentifier+)
322         -> template(t={$text}) "/* throwsClause-not implemented */ <t>"
323     ;
324
325 modifierList
326 returns [List<String> names]
327     :   ^(MODIFIER_LIST (m+=modifier)+)
328         {
329           $names = new ArrayList<String>();
330           for(Object o : $m) $names.add(o.toString());
331         }
332         -> mod_list(mods={$m})
333     ;
334
335 modifier
336 @init {
337 $st = %{$start.getText()};
338 }
339     :   'public'
340     |   'protected'
341     |   'private'
342     |   'entry'
343     |   'abstract'
344     |   'native'
345     |   localModifier
346         -> {$localModifier.st}
347     ;
348
349 localModifierList
350     :   ^(LOCAL_MODIFIER_LIST (m+=localModifier)+)
351         -> local_mod_list(mods={$m})
352     ;
353
354 localModifier
355 @init {
356 $st = %{$start.getText()};
357 }
358     :   'final'
359     |   'static'
360     |   'volatile'
361     ;
362
363     
364 type
365     :   simpleType
366         -> {$simpleType.st}
367     |   objectType 
368         -> {$objectType.st}
369     |   'void'
370     ;
371
372 simpleType
373     :   ^(TYPE primitiveType arrayDeclaratorList?)
374         -> type(typeID={$primitiveType.st}, arrDeclList={$arrayDeclaratorList.st})
375     ;
376
377 objectType
378     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
379         -> type(typeID={$qualifiedTypeIdent.st}, arrDeclList={$arrayDeclaratorList.st})
380     ;
381
382 qualifiedTypeIdent
383     :   ^(QUALIFIED_TYPE_IDENT (t+=typeIdent)+) 
384         -> template(types={$t}) "<types; separator=\".\">"
385     ;
386
387 typeIdent
388     :   ^(IDENT genericTypeArgumentList?)
389         -> typeIdent(typeID={$IDENT.text}, generics={$genericTypeArgumentList.st})
390     ;
391
392 primitiveType
393 @init {
394 $st = %{$start.getText()};
395 }
396     :   'boolean'
397         -> template() "bool"
398     |   'char'
399     |   'byte'
400         -> template() "char"
401     |   'short'
402     |   'int'
403     |   'long'
404     |   'float'
405     |   'double'
406     ;
407
408 genericTypeArgumentList
409     :   ^(GENERIC_TYPE_ARG_LIST (gta+=genericTypeArgument)+)
410         -> template(gtal={$gta}) "\<<gtal; separator=\", \">\>"
411     ;
412     
413 genericTypeArgument
414     :   type
415         -> {$type.st}
416     |   '?'
417         -> template(t={$text}) "/* genericTypeArgument: wildcard bound types not implemented */ <t>"
418     ;
419
420 formalParameterList
421     :   ^(FORMAL_PARAM_LIST (fpsd+=formalParameterStandardDecl)* fpvd=formalParameterVarargDecl?)
422         -> formal_param_list(sdecl={$fpsd}, vdecl={$fpvd.st})
423     ;
424     
425 formalParameterStandardDecl
426     :   ^(FORMAL_PARAM_STD_DECL lms=localModifierList? t=type vdid=variableDeclaratorId)
427         -> formal_param_decl(modList={$lms.st}, type={$t.st}, declID={$vdid.st})
428     ;
429     
430 formalParameterVarargDecl
431     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
432         -> template(t={$text}) "/*formal parameter varargs not implemented*/ <t>"
433     ;
434     
435 qualifiedIdentifier
436     :   IDENT
437         -> template(t={$text}) "<t>"
438     |   ^('.' qualifiedIdentifier IDENT)
439         -> template(t={$text}) "<t>"
440     ;
441     
442 block
443 @init { boolean emptyBlock = true; }
444     :   ^(BLOCK (b+=blockStatement)*)
445         { emptyBlock = ($b == null || $b.size() == 0); }
446         -> {emitCC() && emptyBlock}? template(bsl={$b}) "{ }"
447         -> {emitCC()}? block_cc(bsl={$b})
448         ->
449     ;
450     
451 blockStatement
452     :   localVariableDeclaration
453         -> {$localVariableDeclaration.st}
454     |   statement
455         -> {$statement.st}
456     ;
457
458
459 localVariableDeclaration
460     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
461         -> local_var_decl(
462             modList={null},
463             type={$simpleType.st},
464             declList={$variableDeclaratorList.st})
465     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
466         -> local_var_decl(
467             modList={null},
468             type={$objectType.st},
469             declList={$variableDeclaratorList.st})
470     ;
471
472
473 statement
474     :   block
475         -> {$block.st}
476     |   ^('assert' cond=expression msg=expression?)
477         -> assert(cond={$cond.st}, msg={$msg.st})
478     |   ^('if' parenthesizedExpression then=statement else_=statement?)
479         -> if(cond={$parenthesizedExpression.st}, then={$then.st}, else_={$else_.st})
480     |   ^('for' forInit? FOR_EXPR cond=expression? FOR_UPDATE (update+=expression)* s=statement)
481         -> for(initializer={$forInit.st}, cond={$cond.st}, update={$update}, body={$s.st})
482     |   ^(FOR_EACH localModifierList? type IDENT expression statement) 
483         -> template(t={$text}) "/* foreach not implemented */ <t>"
484     |   ^('while' pe=parenthesizedExpression s=statement)
485         -> while(cond={$pe.st}, body={$s.st})
486     |   ^('do' s=statement pe=parenthesizedExpression)
487         -> dowhile(cond={$pe.st}, block={$s.st})
488     |   ^('switch' pe=parenthesizedExpression (scls+=switchCaseLabel)*)
489         -> switch(expr={$pe.st}, labels={$scls})
490     |   ^('return' e=expression?)
491         -> return(val={$e.st})
492     |   ^('throw' expression)
493         -> template(t={$text}) "/* throw not implemented */ <t>"
494     |   ^('break' IDENT?)
495         -> template() "break;" // TODO: support labeling
496     |   ^('continue' IDENT?)
497         -> template() "continue;" // TODO: support labeling
498     |   ^(LABELED_STATEMENT i=IDENT s=statement)
499         -> label(text={$i.text}, stmt={$s.st})
500     |   expression
501         -> template(expr={$expression.st}) "<expr>;"
502     |   ^('embed' STRING_LITERAL EMBED_BLOCK)
503         ->  embed_cc(str={$STRING_LITERAL.text}, blk={$EMBED_BLOCK.text})
504     |   ';' // Empty statement.
505         -> {%{$start.getText()}}
506     ;
507         
508 switchCaseLabel
509     :   ^('case' expression (b+=blockStatement)*)
510         -> case(expr={$expression.st}, block={$b})
511     |   ^('default' (b+=blockStatement)*)
512         -> template(block={$b}) "default: <block>"
513     ;
514     
515 forInit
516     :   localVariableDeclaration
517         -> template(lvd={$localVariableDeclaration.st}) "<lvd>"
518     |   (ex+=expression)+
519         -> template(ex={$ex}) "<ex; separator=\", \">"
520     ;
521
522 // EXPRESSIONS
523
524 parenthesizedExpression
525     :   ^(PAREN_EXPR exp=expression)
526         -> template(expr={$exp.st}) "(<expr>)"
527     ;
528     
529 expression
530     :   ^(EXPR expr)
531         -> {$expr.st}
532     ;
533
534 expr
535     :   ^('=' e1=expr e2=expr)
536         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> = <e2>"
537     |   ^('+=' e1=expr e2=expr)
538         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> += <e2>"
539     |   ^('-=' e1=expr e2=expr)
540         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> -= <e2>"
541     |   ^('*=' e1=expr e2=expr)
542         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> *= <e2>"
543     |   ^('/=' e1=expr e2=expr)
544         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> /= <e2>"
545     |   ^('&=' e1=expr e2=expr)
546         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> &= <e2>"
547     |   ^('|=' e1=expr e2=expr)
548         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> |= <e2>"
549     |   ^('^=' e1=expr e2=expr)
550         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> ^= <e2>"
551     |   ^('%=' e1=expr e2=expr)
552         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> %= <e2>"
553     |   ^('>>>=' e1=expr e2=expr)
554         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \>\>\>= <e2>"
555     |   ^('>>=' e1=expr e2=expr)
556         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \>\>= <e2>"
557     |   ^('<<=' e1=expr e2=expr)
558         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \<\<= <e2>"
559     |   ^('?' e1=expr e2=expr e3=expr)
560         -> template(e1={$e1.st}, e2={$e2.st}, e3={$e3.st}) "<e1> ? <e2> : <e3>"
561     |   ^('||' e1=expr e2=expr)
562         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> || <e2>"
563     |   ^('&&' e1=expr e2=expr)
564         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> && <e2>"
565     |   ^('|' e1=expr e2=expr)
566         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> | <e2>"
567     |   ^('^' e1=expr e2=expr)
568         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> ^ <e2>"
569     |   ^('&' e1=expr e2=expr)
570         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> & <e2>"
571     |   ^('==' e1=expr e2=expr)
572         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> == <e2>"
573     |   ^('!=' e1=expr e2=expr)
574         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> != <e2>"
575     |   ^('instanceof' expr type)
576         -> template(t={$text}) "/* instanceof not implemented */ <t>"
577     |   ^('<=' e1=expr e2=expr)
578         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \<= <e2>"
579     |   ^('>=' e1=expr e2=expr)
580         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \>= <e2>"
581     |   ^('>>>' e1=expr e2=expr)
582         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \>\>\> <e2>"
583     |   ^('>>' e1=expr e2=expr)
584         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \>\> <e2>"
585     |   ^('>' e1=expr e2=expr)
586         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \> <e2>"
587     |   ^('<<' e1=expr e2=expr)
588         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \<\< <e2>"
589     |   ^('<' e1=expr e2=expr)
590         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \< <e2>"
591     |   ^('+' e1=expr e2=expr)
592         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> + <e2>"
593     |   ^('-' e1=expr e2=expr)
594         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> - <e2>"
595     |   ^('*' e1=expr e2=expr)
596         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> * <e2>"
597     |   ^('/' e1=expr e2=expr)
598         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> / <e2>"
599     |   ^('%' e1=expr e2=expr)
600         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> % <e2>"
601     |   ^(UNARY_PLUS e1=expr)
602         -> template(e1={$e1.st}) "+<e1>"
603     |   ^(UNARY_MINUS e1=expr)
604         -> template(e1={$e1.st}) "-<e1>"
605     |   ^(PRE_INC e1=expr)
606         -> template(e1={$e1.st}) "++<e1>"
607     |   ^(PRE_DEC e1=expr)
608         -> template(e1={$e1.st}) "--<e1>"
609     |   ^(POST_INC e1=expr)
610         -> template(e1={$e1.st}) "<e1>++"
611     |   ^(POST_DEC e1=expr)
612         -> template(e1={$e1.st}) "<e1>--"
613     |   ^('~' e1=expr)
614         -> template(e1={$e1.st}) "~<e1>"
615     |   ^('!' e1=expr)
616         -> template(e1={$e1.st}) "!<e1>"
617     |   ^(CAST_EXPR ty=type e1=expr)
618         -> template(ty={$ty.st}, e1={$e1.st}) "(<ty>)<e1>"
619     |   primaryExpression
620         -> {$primaryExpression.st}
621     ;
622     
623 primaryExpression
624     :   ^('.' prim=primaryExpression IDENT)
625         -> template(id={$IDENT}, prim={$prim.st}) "<prim>.<id>"
626     |   ^('.' prim=primaryExpression 'this')
627         -> template(prim={$prim.st}) "<prim>.this"
628     |   ^('.' prim=primaryExpression 'super')
629         -> template(prim={$prim.st}) "<prim>.super"
630     |   parenthesizedExpression
631         -> {$parenthesizedExpression.st}
632     |   IDENT
633         -> {%{$start.getText()}}
634     |   ^(METHOD_CALL pe=primaryExpression gtal=genericTypeArgumentList? args=arguments)
635         -> method_call(primary={$pe.st}, generic_types={$gtal.st}, args={$args.st})
636     |   explicitConstructorCall
637         -> {$explicitConstructorCall.st}
638     |   ^(ARRAY_ELEMENT_ACCESS pe=primaryExpression ex=expression)
639         -> template(pe={$pe.st}, ex={$ex.st}) "<pe>[<ex>]"
640     |   literal
641         -> {$literal.st}
642     |   newExpression
643         -> {$newExpression.st}
644     |   'this'
645         -> {%{$start.getText()}}
646     |   arrayTypeDeclarator
647         -> {$arrayTypeDeclarator.st}
648     |   'super'
649         -> {%{$start.getText()}}
650     ;
651     
652 explicitConstructorCall
653     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
654         -> template(t={$text}) "<t>"
655     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
656         -> template(t={$text}) "<t>"
657     ;
658
659 arrayTypeDeclarator
660     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
661         -> template(t={$text}) "<t>"
662     ;
663
664 newExpression
665     :   ^(  STATIC_ARRAY_CREATOR
666             (   primitiveType newArrayConstruction
667             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
668             )
669         )
670         -> template(t={$text}) "<t>"
671     ;
672
673 newArrayConstruction
674     :   arrayDeclaratorList arrayInitializer
675         -> array_construction_with_init(
676                 array_decls={$arrayDeclaratorList.st},
677                 initializer={$arrayInitializer.st})
678     |   (ex+=expression)+ adl=arrayDeclaratorList?
679         -> array_construction(exprs={$ex}, array_decls={$adl.st})
680     ;
681
682 arguments
683     :   ^(ARGUMENT_LIST (ex+=expression)*)
684         -> arguments(exprs={$ex})
685     ;
686
687 literal
688 @init {
689 $st = %{$start.getText()};
690 }
691     :   HEX_LITERAL
692     |   OCTAL_LITERAL
693     |   DECIMAL_LITERAL
694     |   FLOATING_POINT_LITERAL
695     |   CHARACTER_LITERAL
696     |   STRING_LITERAL
697     |   'true'
698     |   'false'
699     |   'null'
700     ;
701