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