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