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