Charj: simplify and improve chare type handling
[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(
89             pd={$p.st}, ids={$i}, tds={$t.st}, debug={debug()})
90         -> {emitCI()}? charjSource_ci(pd={$p.st}, ids={$i}, tds={$t.st}, debug={debug()})
91         -> {emitH()}? charjSource_h(
92             pd={$p.st}, ids={$i}, tds={$t.st}, debug={debug()})
93         ->
94     ;
95
96 packageDeclaration
97 @init { 
98     List<String> names = null; 
99 }
100     :   ^('package' qualifiedIdentifier)
101         ->
102     ;
103     
104 importDeclaration
105 @init {
106     String importID = null;
107 }
108     :   ^('import' qualifiedIdentifier ds='.*'?)
109         {
110             importID = $qualifiedIdentifier.text;
111             if ($ds != null) {
112             }
113         }
114         {$ds == null}? // TODO: add support for importing x.*
115         -> {(emitCC() || emitH())}? importDeclaration_cc_h(
116             inc_id={importID.replace(".","/")},
117             use_id={importID.replace(".","::")})
118         ->
119     ;
120     
121 typeDeclaration
122     :   ^(TYPE 'class' IDENT (^('extends' su=type))? (^('implements' type+))? (csds+=classScopeDeclaration)*)
123         {
124             currentClass = (ClassSymbol)$IDENT.symbol;
125         }
126         -> {emitCC()}? classDeclaration_cc(
127                 sym={currentClass},
128                 ident={$IDENT.text}, 
129                 ext={$su.st}, 
130                 csds={$csds})
131         -> {emitH()}?  classDeclaration_h(
132                 sym={currentClass},
133                 ident={$IDENT.text}, 
134                 ext={$su.st}, 
135                 csds={$csds})
136         ->
137     |   ^('interface' IDENT (^('extends' type+))? interfaceScopeDeclaration*)
138         -> template(t={$text}) "/*INTERFACE-not implemented*/ <t>"
139     |   ^('enum' IDENT (^('implements' type+))? classScopeDeclaration*)
140         -> template(t={$text}) "/*ENUM-not implemented*/ <t>"
141     |   ^(TYPE chareType IDENT (^('extends' type))? (^('implements' type+))? classScopeDeclaration*)
142         {
143             currentClass = (ClassSymbol)$IDENT.symbol;
144         }
145         -> {emitCC()}? chareDeclaration_cc(
146                 sym={currentClass},
147                 ident={$IDENT.text}, 
148                 ext={$su.st}, 
149                 csds={$csds})
150         -> {emitCI()}? chareDeclaration_ci(
151                 sym={currentClass},
152                 chareType={$chareType.st},
153                 arrayDim={null},
154                 ident={$IDENT.text}, 
155                 ext={$su.st}, 
156                 csds={$csds})
157         -> {emitH()}? chareDeclaration_h(
158                 sym={currentClass},
159                 ident={$IDENT.text}, 
160                 ext={$su.st}, 
161                 csds={$csds})
162         ->
163     ;
164
165 chareType
166 @init {
167 $st = %{$start.getText()};
168 }
169     :   'chare'
170     |   'group'
171     |   'nodegroup'
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 { boolean entry = false; }
183     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
184             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
185             b=block?)
186         { 
187             if ($m.st != null) {
188                 // determine whether this is an entry method
189                 entry = listContainsToken($m.start.getChildren(), ENTRY);
190             }
191         }
192         -> {emitCC()}? funcMethodDecl_cc(
193                 modl={$m.st}, 
194                 gtpl={$g.st}, 
195                 ty={$ty.text},
196                 id={$IDENT.text}, 
197                 fpl={$f.st}, 
198                 adl={$a.st},
199                 block={$b.st})
200         -> {emitH()}? funcMethodDecl_h(
201                 modl={$m.st}, 
202                 gtpl={$g.st}, 
203                 ty={$ty.text},
204                 id={$IDENT.text}, 
205                 fpl={$f.st}, 
206                 adl={$a.st},
207                 block={$b.st})
208         -> {(emitCI() && entry)}? funcMethodDecl_ci(
209                 modl={$m.st}, 
210                 gtpl={$g.st}, 
211                 ty={$ty.text},
212                 id={$IDENT.text}, 
213                 fpl={$f.st}, 
214                 adl={$a.st},
215                 block={$b.st})
216         ->
217     |   ^(VOID_METHOD_DECL m=modifierList? g=genericTypeParameterList? IDENT 
218             f=formalParameterList b=block?)
219         { 
220             // determine whether this is an entry method
221             if ($m.st != null) {
222                 entry = listContainsToken($m.start.getChildren(), ENTRY);
223             }
224         }
225         -> {emitCC()}? voidMethodDecl_cc(
226                 modl={$m.st}, 
227                 gtpl={$g.st}, 
228                 id={$IDENT.text}, 
229                 fpl={$f.st}, 
230                 block={$b.st})
231         -> {emitCI() && entry}? voidMethodDecl_ci(
232                 modl={$m.st}, 
233                 gtpl={$g.st}, 
234                 id={$IDENT.text}, 
235                 fpl={$f.st}, 
236                 block={$b.st})
237         -> {emitH()}? voidMethodDecl_h(
238                 modl={$m.st}, 
239                 gtpl={$g.st}, 
240                 id={$IDENT.text}, 
241                 fpl={$f.st}, 
242                 block={$b.st})
243         ->
244     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
245         -> {emitCC() || emitH()}? class_var_decl(
246             modl={$modifierList.st},
247             type={$simpleType.st},
248             declList={$variableDeclaratorList.st})
249         ->
250     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
251         -> {emitCC() || emitH()}? class_var_decl(
252             modl={$modifierList.st},
253             type={$objectType.st},
254             declList={$variableDeclaratorList.st})
255         ->
256     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList b=block)
257         { 
258             // determine whether this is an entry method
259             if ($m.st != null) {
260                 entry = listContainsToken($m.start.getChildren(), ENTRY);
261             }
262         }
263         -> {emitCC()}? ctorDecl_cc(
264                 modl={$m.st}, 
265                 gtpl={$g.st}, 
266                 id={$IDENT.text}, 
267                 fpl={$f.st}, 
268                 block={$b.st})
269         -> {emitCI() && entry}? ctorDecl_ci(
270                 modl={$m.st}, 
271                 gtpl={$g.st}, 
272                 id={$IDENT.text}, 
273                 fpl={$f.st}, 
274                 block={$b.st})
275         -> {emitH()}? ctorDecl_h(
276                 modl={$m.st}, 
277                 gtpl={$g.st}, 
278                 id={$IDENT.text}, 
279                 fpl={$f.st}, 
280                 block={$b.st})
281         ->
282     ;
283     
284 interfaceScopeDeclaration
285     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? type IDENT formalParameterList arrayDeclaratorList?)
286         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
287     |   ^(VOID_METHOD_DECL modifierList? genericTypeParameterList? IDENT formalParameterList)
288         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
289     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
290         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
291     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
292         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
293     ;
294
295 variableDeclaratorList
296     :   ^(VAR_DECLARATOR_LIST (var_decls+=variableDeclarator)+)
297         -> var_decl_list(var_decls={$var_decls})
298     ;
299
300 variableDeclarator
301     :   ^(VAR_DECLARATOR id=variableDeclaratorId initializer=variableInitializer?)
302         -> var_decl(id={$id.st}, initializer={$initializer.st})
303     ;
304     
305 variableDeclaratorId
306     :   ^(IDENT adl=arrayDeclaratorList?)
307         -> var_decl_id(id={$IDENT.text}, arrayDeclList={$adl.st})
308     ;
309
310 variableInitializer
311     :   arrayInitializer
312         -> {$arrayInitializer.st}
313     |   expression
314         -> {$expression.st}
315     ;
316
317 arrayDeclaratorList
318     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
319         -> template(t={$text}) "<t>"
320     ;
321     
322 arrayInitializer
323     :   ^(ARRAY_INITIALIZER variableInitializer*)
324         -> template(t={$text}) "/* arrayInitializer-not implemented */ <t>"
325     ;
326
327 genericTypeParameterList
328     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
329         -> template(t={$text}) "/*GENERIC_TYPE_PARAM_LIST-not implemented*/ <t>"
330     ;
331
332 genericTypeParameter
333     :   ^(IDENT bound?)
334         -> template(t={$text}) "/*genericTypeParameter-not implemented*/ <t>"
335     ;
336         
337 bound
338     :   ^(EXTENDS_BOUND_LIST type+)
339         -> template(t={$text}) "/*EXTENDS_BOUND_LIST-not implemented*/ <t>"
340     ;
341
342 throwsClause
343     :   ^(THROWS_CLAUSE qualifiedIdentifier+)
344         -> template(t={$text}) "/* throwsClause-not implemented */ <t>"
345     ;
346
347 modifierList
348     :   ^(MODIFIER_LIST (m+=modifier)+)
349         -> mod_list(mods={$m})
350     ;
351
352 modifier
353 @init {
354 $st = %{$start.getText()};
355 }
356     :   'public'
357     |   'protected'
358     |   'private'
359     |   'entry'
360     |   'abstract'
361     |   'native'
362     |   localModifier
363         -> {$localModifier.st}
364     ;
365
366 localModifierList
367     :   ^(LOCAL_MODIFIER_LIST (m+=localModifier)+)
368         -> local_mod_list(mods={$m})
369     ;
370
371 localModifier
372 @init {
373 $st = %{$start.getText()};
374 }
375     :   'final'
376     |   'static'
377     |   'volatile'
378     ;
379
380     
381 type
382     :   simpleType
383         -> {$simpleType.st}
384     |   objectType 
385         -> {$objectType.st}
386     ;
387
388 simpleType
389     :   ^(TYPE primitiveType arrayDeclaratorList?)
390         -> type(typeID={$primitiveType.st}, arrDeclList={$arrayDeclaratorList.st})
391     ;
392
393 objectType
394     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
395         -> type(typeID={$qualifiedTypeIdent.st}, arrDeclList={$arrayDeclaratorList.st})
396     ;
397
398 qualifiedTypeIdent
399     :   ^(QUALIFIED_TYPE_IDENT (t+=typeIdent)+) 
400         -> template(types={$t}) "<types; separator=\".\">"
401     ;
402
403 typeIdent
404     :   ^(IDENT genericTypeArgumentList?)
405         -> typeIdent(typeID={$IDENT.text}, generics={$genericTypeArgumentList.st})
406     ;
407
408 primitiveType
409 @init {
410 $st = %{$start.getText()};
411 }
412     :   'boolean'
413         -> template() "bool"
414     |   'char'
415     |   'byte'
416         -> template() "char"
417     |   'short'
418     |   'int'
419     |   'long'
420     |   'float'
421     |   'double'
422     ;
423
424 genericTypeArgumentList
425     :   ^(GENERIC_TYPE_ARG_LIST (gta+=genericTypeArgument)+)
426         -> template(gtal={$gta}) "\<<gtal; separator=\", \">\>"
427     ;
428     
429 genericTypeArgument
430     :   type
431         -> {$type.st}
432     |   '?'
433         -> template(t={$text}) "/* genericTypeArgument: wildcard bound types not implemented */ <t>"
434     ;
435
436 formalParameterList
437     :   ^(FORMAL_PARAM_LIST (fpsd+=formalParameterStandardDecl)* fpvd=formalParameterVarargDecl?)
438         -> formal_param_list(sdecl={$fpsd}, vdecl={$fpvd.st})
439     ;
440     
441 formalParameterStandardDecl
442     :   ^(FORMAL_PARAM_STD_DECL lms=localModifierList? t=type vdid=variableDeclaratorId)
443         -> formal_param_decl(modList={$lms.st}, type={$t.st}, declID={$vdid.st})
444     ;
445     
446 formalParameterVarargDecl
447     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
448         -> template(t={$text}) "/*formal parameter varargs not implemented*/ <t>"
449     ;
450     
451 qualifiedIdentifier
452     :   IDENT
453         -> template(t={$text}) "<t>"
454     |   ^('.' qualifiedIdentifier IDENT)
455         -> template(t={$text}) "<t>"
456     ;
457     
458 block
459 @init { boolean emptyBlock = true; }
460     :   ^(BLOCK (b+=blockStatement)*)
461         { emptyBlock = ($b == null || $b.size() == 0); }
462         -> {emitCC() && emptyBlock}? template(bsl={$b}) "{ }"
463         -> {emitCC()}? block_cc(bsl={$b})
464         ->
465     ;
466     
467 blockStatement
468     :   localVariableDeclaration
469         -> {$localVariableDeclaration.st}
470     |   statement
471         -> {$statement.st}
472     ;
473
474
475 localVariableDeclaration
476     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
477         -> local_var_decl(
478             modList={null},
479             type={$simpleType.st},
480             declList={$variableDeclaratorList.st})
481     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
482         -> local_var_decl(
483             modList={null},
484             type={$objectType.st},
485             declList={$variableDeclaratorList.st})
486     ;
487
488
489 statement
490     :   block
491         -> {$block.st}
492     |   ^('assert' cond=expression msg=expression?)
493         -> assert(cond={$cond.st}, msg={$msg.st})
494     |   ^('if' parenthesizedExpression then=statement else_=statement?)
495         -> if(cond={$parenthesizedExpression.st}, then={$then.st}, else_={$else_.st})
496     |   ^('for' forInit? FOR_EXPR cond=expression? FOR_UPDATE (update+=expression)* s=statement)
497         -> for(initializer={$forInit.st}, cond={$cond.st}, update={$update}, body={$s.st})
498     |   ^(FOR_EACH localModifierList? type IDENT expression statement) 
499         -> template(t={$text}) "/* foreach not implemented */ <t>"
500     |   ^('while' pe=parenthesizedExpression s=statement)
501         -> while(cond={$pe.st}, body={$s.st})
502     |   ^('do' s=statement pe=parenthesizedExpression)
503         -> dowhile(cond={$pe.st}, block={$s.st})
504     |   ^('switch' pe=parenthesizedExpression (scls+=switchCaseLabel)*)
505         -> switch(expr={$pe.st}, labels={$scls})
506     |   ^('return' e=expression?)
507         -> return(val={$e.st})
508     |   ^('throw' expression)
509         -> template(t={$text}) "/* throw not implemented */ <t>"
510     |   ^('break' IDENT?)
511         -> template() "break;" // TODO: support labeling
512     |   ^('continue' IDENT?)
513         -> template() "continue;" // TODO: support labeling
514     |   ^(LABELED_STATEMENT i=IDENT s=statement)
515         -> label(text={$i.text}, stmt={$s.st})
516     |   expression
517         -> template(expr={$expression.st}) "<expr>;"
518     |   ^('embed' STRING_LITERAL EMBED_BLOCK)
519         ->  embed_cc(str={$STRING_LITERAL.text}, blk={$EMBED_BLOCK.text})
520     |   ';' // Empty statement.
521         -> {%{$start.getText()}}
522     ;
523         
524 switchCaseLabel
525     :   ^('case' expression (b+=blockStatement)*)
526         -> case(expr={$expression.st}, block={$b})
527     |   ^('default' (b+=blockStatement)*)
528         -> template(block={$b}) "default: <block>"
529     ;
530     
531 forInit
532     :   localVariableDeclaration
533         -> template(lvd={$localVariableDeclaration.st}) "<lvd>"
534     |   (ex+=expression)+
535         -> template(ex={$ex}) "<ex; separator=\", \">"
536     ;
537
538 // EXPRESSIONS
539
540 parenthesizedExpression
541     :   ^(PAREN_EXPR exp=expression)
542         -> template(expr={$exp.st}) "(<expr>)"
543     ;
544     
545 expression
546     :   ^(EXPR expr)
547         -> {$expr.st}
548     ;
549
550 expr
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)
560         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> /= <e2>"
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     |   ^('?' e1=expr e2=expr e3=expr)
576         -> template(e1={$e1.st}, e2={$e2.st}, e3={$e3.st}) "<e1> ? <e2> : <e3>"
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     |   ^('instanceof' expr type)
592         -> template(t={$text}) "/* instanceof not implemented */ <t>"
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     |   ^('>' e1=expr e2=expr)
602         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \> <e2>"
603     |   ^('<<' e1=expr e2=expr)
604         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \<\< <e2>"
605     |   ^('<' e1=expr e2=expr)
606         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> \< <e2>"
607     |   ^('+' e1=expr e2=expr)
608         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> + <e2>"
609     |   ^('-' e1=expr e2=expr)
610         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> - <e2>"
611     |   ^('*' e1=expr e2=expr)
612         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> * <e2>"
613     |   ^('/' e1=expr e2=expr)
614         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> / <e2>"
615     |   ^('%' e1=expr e2=expr)
616         -> template(e1={$e1.st}, e2={$e2.st}) "<e1> % <e2>"
617     |   ^(UNARY_PLUS e1=expr)
618         -> template(e1={$e1.st}) "+<e1>"
619     |   ^(UNARY_MINUS e1=expr)
620         -> template(e1={$e1.st}) "-<e1>"
621     |   ^(PRE_INC e1=expr)
622         -> template(e1={$e1.st}) "++<e1>"
623     |   ^(PRE_DEC e1=expr)
624         -> template(e1={$e1.st}) "--<e1>"
625     |   ^(POST_INC e1=expr)
626         -> template(e1={$e1.st}) "<e1>++"
627     |   ^(POST_DEC e1=expr)
628         -> template(e1={$e1.st}) "<e1>--"
629     |   ^('~' e1=expr)
630         -> template(e1={$e1.st}) "~<e1>"
631     |   ^('!' e1=expr)
632         -> template(e1={$e1.st}) "!<e1>"
633     |   ^(CAST_EXPR ty=type e1=expr)
634         -> template(ty={$ty.st}, e1={$e1.st}) "(<ty>)<e1>"
635     |   primaryExpression
636         -> {$primaryExpression.st}
637     ;
638     
639 primaryExpression
640     :   ^('.' prim=primaryExpression IDENT)
641         -> template(id={$IDENT}, prim={$prim.st}) "<prim>.<id>"
642     |   ^('.' prim=primaryExpression 'this')
643         -> template(prim={$prim.st}) "<prim>.this"
644     |   ^('.' prim=primaryExpression 'super')
645         -> template(prim={$prim.st}) "<prim>.super"
646     |   parenthesizedExpression
647         -> {$parenthesizedExpression.st}
648     |   IDENT
649         -> {%{$start.getText()}}
650     |   ^(METHOD_CALL pe=primaryExpression gtal=genericTypeArgumentList? args=arguments)
651         -> method_call(primary={$pe.st}, generic_types={$gtal.st}, args={$args.st})
652     |   explicitConstructorCall
653         -> {$explicitConstructorCall.st}
654     |   ^(ARRAY_ELEMENT_ACCESS pe=primaryExpression ex=expression)
655         -> template(pe={$pe.st}, ex={$ex.st}) "<pe>[<ex>]"
656     |   literal
657         -> {$literal.st}
658     |   newExpression
659         -> {$newExpression.st}
660     |   'this'
661         -> {%{$start.getText()}}
662     |   arrayTypeDeclarator
663         -> {$arrayTypeDeclarator.st}
664     |   'super'
665         -> {%{$start.getText()}}
666     ;
667     
668 explicitConstructorCall
669     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
670         -> template(t={$text}) "<t>"
671     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
672         -> template(t={$text}) "<t>"
673     ;
674
675 arrayTypeDeclarator
676     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
677         -> template(t={$text}) "<t>"
678     ;
679
680 newExpression
681     :   ^(  STATIC_ARRAY_CREATOR
682             (   primitiveType newArrayConstruction
683             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
684             )
685         )
686         -> template(t={$text}) "<t>"
687     ;
688
689 newArrayConstruction
690     :   arrayDeclaratorList arrayInitializer
691         -> array_construction_with_init(
692                 array_decls={$arrayDeclaratorList.st},
693                 initializer={$arrayInitializer.st})
694     |   (ex+=expression)+ adl=arrayDeclaratorList?
695         -> array_construction(exprs={$ex}, array_decls={$adl.st})
696     ;
697
698 arguments
699     :   ^(ARGUMENT_LIST (ex+=expression)*)
700         -> arguments(exprs={$ex})
701     ;
702
703 literal
704 @init {
705 $st = %{$start.getText()};
706 }
707     :   HEX_LITERAL
708     |   OCTAL_LITERAL
709     |   DECIMAL_LITERAL
710     |   FLOATING_POINT_LITERAL
711     |   CHARACTER_LITERAL
712     |   STRING_LITERAL
713     |   'true'
714     |   'false'
715     |   'null'
716     ;
717