Charj: allow multiple type definitions per file
[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     private String basename() { return translator_.basename(); }
37
38     /**
39      *  Override ANTLR's token mismatch behavior so we throw exceptions early.
40      */
41     protected void mismatch(IntStream input, int ttype, BitSet follow)
42         throws RecognitionException {
43         throw new MismatchedTokenException(ttype, input);
44     }
45
46     /**
47      *  Override ANTLR's set mismatch behavior so we throw exceptions early.
48      */
49     public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow)
50         throws RecognitionException {
51         throw e;
52     }
53
54     /**
55      *  Test a list of CharjAST nodes to see if any of them has the given token
56      *  type.
57      */
58     public boolean listContainsToken(List<CharjAST> list, int tokenType) {
59         if (list == null) return false;
60         for (CharjAST node : list) {
61             if (node.token.getType() == tokenType) {
62                 return true;
63             }
64         }
65         return false;
66     }
67 }
68
69
70 // Replace default ANTLR generated catch clauses with this action, allowing early failure.
71 @rulecatch {
72     catch (RecognitionException re) {
73         reportError(re);
74         throw re;
75     }
76 }
77
78
79 // Starting point for parsing a Charj file.
80 charjSource[SymbolTable symtab, OutputMode m]
81 @init {
82     this.symtab = symtab;
83     this.translator_ = symtab.translator;
84     this.mode_ = m;
85 }
86     :   ^(CHARJ_SOURCE (p=packageDeclaration)? 
87         (i+=importDeclaration)* 
88         (t+=typeDeclaration)*)
89         -> {emitCC()}? charjSource_cc(basename={basename()}, pd={$p.names}, ids={$i}, tds={$t}, debug={debug()})
90         -> {emitCI()}? charjSource_ci(basename={basename()}, pd={$p.names}, ids={$i}, tds={$t}, debug={debug()})
91         -> {emitH()}? charjSource_h(basename={basename()}, pd={$p.names}, ids={$i}, tds={$t}, debug={debug()})
92         ->
93     ;
94
95 packageDeclaration
96 returns [List names]
97     :   ^('package' (ids+=IDENT)+)
98         {
99             $names = $ids;
100         }
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+))?
123         {
124             currentClass = (ClassSymbol)$IDENT.symbol;
125         }
126         (csds+=classScopeDeclaration)*)
127         -> {emitCC()}? classDeclaration_cc(
128                 sym={currentClass},
129                 ident={$IDENT.text}, 
130                 ext={$su.st}, 
131                 csds={$csds})
132         -> {emitH()}?  classDeclaration_h(
133                 sym={currentClass},
134                 ident={$IDENT.text}, 
135                 ext={$su.st}, 
136                 csds={$csds})
137         ->
138     |   ^(INTERFACE IDENT (^('extends' type+))? interfaceScopeDeclaration*)
139         -> template(t={$text}) "/*INTERFACE-not implemented*/ <t>"
140     |   ^(ENUM IDENT (^('implements' type+))? classScopeDeclaration*)
141         -> template(t={$text}) "/*ENUM-not implemented*/ <t>"
142     |   ^(TYPE chareType IDENT (^('extends' type))? (^('implements' type+))?
143         {
144             currentClass = (ClassSymbol)$IDENT.symbol;
145         }
146         (csds+=classScopeDeclaration)*)
147         -> {emitCC()}? chareDeclaration_cc(
148                 sym={currentClass},
149                 ident={$IDENT.text}, 
150                 ext={$su.st}, 
151                 csds={$csds})
152         -> {emitCI()}? chareDeclaration_ci(
153                 sym={currentClass},
154                 chareType={$chareType.st},
155                 arrayDim={null},
156                 ident={$IDENT.text}, 
157                 ext={$su.st}, 
158                 csds={$csds})
159         -> {emitH()}? chareDeclaration_h(
160                 sym={currentClass},
161                 ident={$IDENT.text}, 
162                 ext={$su.st}, 
163                 csds={$csds})
164         ->
165     ;
166
167 chareType
168 @init {
169 $st = %{$start.getText()};
170 }
171     :   CHARE
172     |   GROUP
173     |   NODEGROUP
174     |   MAINCHARE
175     |   ^(CHARE_ARRAY ARRAY_DIMENSION)
176         -> template(t={$ARRAY_DIMENSION.text}) "array [<t>]"
177     ;
178
179 enumConstant
180     :   ^(IDENT arguments?)
181         -> template(t={$text}) "/*enumConstant-not implemented*/ <t>"
182     ;
183
184 classScopeDeclaration
185 @init {
186   boolean entry = false;
187   List<String> modList = new ArrayList<String>();
188 }
189     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
190             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
191             b=block?)
192         { 
193             if ($m.st != null) {
194                 // determine whether this is an entry method
195                 entry = listContainsToken($m.start.getChildren(), ENTRY);
196                 for(Object o : $m.names) {
197                     if (o.equals("entry")) continue;
198                     else modList.add(o.toString());
199                 }
200             }
201         }
202         -> {emitCC()}? funcMethodDecl_cc(
203                 sym={currentClass},
204                 modl={modList}, 
205                 gtpl={$g.st}, 
206                 ty={$ty.st},
207                 id={$IDENT.text}, 
208                 fpl={$f.st}, 
209                 adl={$a.st},
210                 block={$b.st})
211         -> {emitH()}? funcMethodDecl_h(
212                 modl={modList}, 
213                 gtpl={$g.st}, 
214                 ty={$ty.st},
215                 id={$IDENT.text}, 
216                 fpl={$f.st}, 
217                 adl={$a.st},
218                 block={$b.st})
219         -> {(emitCI() && entry)}? funcMethodDecl_ci(
220                 modl={$m.st}, 
221                 gtpl={$g.st}, 
222                 ty={$ty.st},
223                 id={$IDENT.text}, 
224                 fpl={$f.st}, 
225                 adl={$a.st},
226                 block={$b.st})
227         ->
228     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
229         -> {emitH()}? class_var_decl(
230             modl={$modifierList.st},
231             type={$simpleType.st},
232             declList={$variableDeclaratorList.st})
233         ->
234     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
235         -> {emitH()}? class_var_decl(
236             modl={$modifierList.st},
237             type={$objectType.st},
238             declList={$variableDeclaratorList.st})
239         ->
240     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList b=block)
241         { 
242             // determine whether this is an entry method
243             if ($m.st != null) {
244                 entry = listContainsToken($m.start.getChildren(), ENTRY);
245                 for(Object o : $m.names) {
246                     if (o.equals("entry")) continue;
247                     else modList.add(o.toString());
248                 }
249             }
250         }
251         -> {emitCC()}? ctorDecl_cc(
252                 modl={modList},
253                 gtpl={$g.st}, 
254                 id={$IDENT.text}, 
255                 fpl={$f.st}, 
256                 block={$b.st})
257         -> {emitCI() && entry}? ctorDecl_ci(
258                 modl={modList},
259                 gtpl={$g.st}, 
260                 id={$IDENT.text}, 
261                 fpl={$f.st}, 
262                 block={$b.st})
263         -> {emitH()}? ctorDecl_h(
264                 modl={modList},
265                 gtpl={$g.st}, 
266                 id={$IDENT.text}, 
267                 fpl={$f.st}, 
268                 block={$b.st})
269         ->
270     ;
271     
272 interfaceScopeDeclaration
273     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? type IDENT formalParameterList arrayDeclaratorList?)
274         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
275     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
276         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
277     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
278         -> template(t={$text}) "/*interfaceScopeDeclarations-not implemented */ <t>"
279     ;
280
281 variableDeclaratorList
282     :   ^(VAR_DECLARATOR_LIST (var_decls+=variableDeclarator)+)
283         -> var_decl_list(var_decls={$var_decls})
284     ;
285
286 variableDeclarator
287     :   ^(VAR_DECLARATOR id=variableDeclaratorId initializer=variableInitializer?)
288         -> var_decl(id={$id.st}, initializer={$initializer.st})
289     ;
290     
291 variableDeclaratorId
292     :   ^(IDENT adl=arrayDeclaratorList?)
293         -> var_decl_id(id={$IDENT.text}, arrayDeclList={$adl.st})
294     ;
295
296 variableInitializer
297     :   arrayInitializer
298         -> {$arrayInitializer.st}
299     |   expression
300         -> {$expression.st}
301     ;
302
303 arrayDeclaratorList
304     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
305         -> template(t={$text}) "<t>"
306     ;
307     
308 arrayInitializer
309     :   ^(ARRAY_INITIALIZER variableInitializer*)
310         -> template(t={$text}) "/* arrayInitializer-not implemented */ <t>"
311     ;
312
313 genericTypeParameterList
314     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
315         -> template(t={$text}) "/*GENERIC_TYPE_PARAM_LIST-not implemented*/ <t>"
316     ;
317
318 genericTypeParameter
319     :   ^(IDENT bound?)
320         -> template(t={$text}) "/*genericTypeParameter-not implemented*/ <t>"
321     ;
322         
323 bound
324     :   ^(EXTENDS_BOUND_LIST type+)
325         -> template(t={$text}) "/*EXTENDS_BOUND_LIST-not implemented*/ <t>"
326     ;
327
328 throwsClause
329     :   ^(THROWS_CLAUSE qualifiedIdentifier+)
330         -> template(t={$text}) "/* throwsClause-not implemented */ <t>"
331     ;
332
333 modifierList
334 returns [List<String> names]
335     :   ^(MODIFIER_LIST (m+=modifier)+)
336         {
337           $names = new ArrayList<String>();
338           for(Object o : $m) $names.add(o.toString());
339         }
340         -> mod_list(mods={$m})
341     ;
342
343 modifier
344 @init {
345 $st = %{$start.getText()};
346 }
347     :   PUBLIC
348     |   PROTECTED
349     |   PRIVATE
350     |   ENTRY
351     |   ABSTRACT
352     |   NATIVE
353     |   localModifier
354         -> {$localModifier.st}
355     ;
356
357 localModifierList
358     :   ^(LOCAL_MODIFIER_LIST (m+=localModifier)+)
359         -> local_mod_list(mods={$m})
360     ;
361
362 localModifier
363 @init {
364 $st = %{$start.getText()};
365 }
366     :   FINAL
367     |   STATIC
368     |   VOLATILE
369     ;
370
371     
372 type
373     :   simpleType
374         -> {$simpleType.st}
375     |   objectType 
376         -> {$objectType.st}
377     |   VOID
378         {
379             $st = %{$start.getText()};
380         }
381     ;
382
383 simpleType
384     :   ^(SIMPLE_TYPE primitiveType arrayDeclaratorList?)
385         -> simple_type(typeID={$primitiveType.st}, arrDeclList={$arrayDeclaratorList.st})
386     ;
387
388 objectType
389     :   ^(OBJECT_TYPE qualifiedTypeIdent arrayDeclaratorList?)
390         -> obj_type(typeID={$qualifiedTypeIdent.st}, arrDeclList={$arrayDeclaratorList.st})
391     |   ^(PROXY_TYPE qualifiedTypeIdent arrayDeclaratorList?)
392         -> proxy_type(typeID={$qualifiedTypeIdent.st}, arrDeclList={$arrayDeclaratorList.st})
393     |   ^(POINTER_TYPE qualifiedTypeIdent arrayDeclaratorList?)
394         -> pointer_type(typeID={$qualifiedTypeIdent.st}, arrDeclList={$arrayDeclaratorList.st})
395     |   ^(REFERENCE_TYPE qualifiedTypeIdent arrayDeclaratorList?)
396         -> reference_type(typeID={$qualifiedTypeIdent.st}, arrDeclList={$arrayDeclaratorList.st})
397     ;
398
399 qualifiedTypeIdent
400     :   ^(QUALIFIED_TYPE_IDENT (t+=typeIdent)+) 
401         -> template(types={$t}) "<types; separator=\"::\">"
402     ;
403
404 typeIdent
405     :   ^(IDENT genericTypeArgumentList?)
406         -> typeIdent(typeID={$IDENT.text}, generics={$genericTypeArgumentList.st})
407     ;
408
409 primitiveType
410 @init {
411 $st = %{$start.getText()};
412 }
413     :   BOOLEAN
414         -> template() "bool"
415     |   CHAR
416     |   BYTE
417         -> template() "char"
418     |   SHORT
419     |   INT
420     |   LONG
421     |   FLOAT
422     |   DOUBLE
423     ;
424
425 genericTypeArgumentList
426     :   ^(GENERIC_TYPE_ARG_LIST (gta+=genericTypeArgument)+)
427         -> template(gtal={$gta}) "\<<gtal; separator=\", \">\>"
428     ;
429     
430 genericTypeArgument
431     :   type
432         -> {$type.st}
433     |   '?'
434         -> template(t={$text}) "/* genericTypeArgument: wildcard bound types not implemented */ <t>"
435     ;
436
437 formalParameterList
438     :   ^(FORMAL_PARAM_LIST (fpsd+=formalParameterStandardDecl)* fpvd=formalParameterVarargDecl?)
439         -> formal_param_list(sdecl={$fpsd}, vdecl={$fpvd.st})
440     ;
441     
442 formalParameterStandardDecl
443     :   ^(FORMAL_PARAM_STD_DECL lms=localModifierList? t=type vdid=variableDeclaratorId)
444         -> formal_param_decl(modList={$lms.st}, type={$t.st}, declID={$vdid.st})
445     ;
446     
447 formalParameterVarargDecl
448     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
449         -> template(t={$text}) "/*formal parameter varargs not implemented*/ <t>"
450     ;
451     
452 qualifiedIdentifier
453     :   IDENT
454         -> template(t={$text}) "<t>"
455     |   ^(DOT qualifiedIdentifier IDENT)
456         -> template(t={$text}) "<t>"
457     ;
458     
459 block
460 @init { boolean emptyBlock = true; }
461     :   ^(BLOCK (b+=blockStatement)*)
462         { emptyBlock = ($b == null || $b.size() == 0); }
463         -> {emitCC() && emptyBlock}? template(bsl={$b}) "{ }"
464         -> {emitCC()}? block_cc(bsl={$b})
465         ->
466     ;
467     
468 blockStatement
469     :   localVariableDeclaration
470         -> {$localVariableDeclaration.st}
471     |   statement
472         -> {$statement.st}
473     ;
474
475
476 localVariableDeclaration
477     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
478         -> local_var_decl(
479             modList={null},
480             type={$simpleType.st},
481             declList={$variableDeclaratorList.st})
482     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
483         -> local_var_decl(
484             modList={null},
485             type={$objectType.st},
486             declList={$variableDeclaratorList.st})
487     ;
488
489
490 statement
491     :   nonBlockStatement
492         -> {$nonBlockStatement.st}
493     |   block
494         -> {$block.st}
495     ;
496
497 nonBlockStatement
498     :   ^(ASSERT cond=expression msg=expression?)
499         -> assert(cond={$cond.st}, msg={$msg.st})
500     |   ^(IF parenthesizedExpression then=block else_=block?)
501         -> if(cond={$parenthesizedExpression.st}, then={$then.st}, else_={$else_.st})
502     |   ^(FOR forInit? FOR_EXPR cond=expression? FOR_UPDATE (update+=expression)* b=block)
503         -> for(initializer={$forInit.st}, cond={$cond.st}, update={$update}, body={$block.st})
504     |   ^(FOR_EACH localModifierList? type IDENT expression block) 
505         -> template(t={$text}) "/* foreach not implemented */ <t>"
506     |   ^(WHILE pe=parenthesizedExpression b=block)
507         -> while(cond={$pe.st}, body={$b.st})
508     |   ^(DO b=block pe=parenthesizedExpression)
509         -> dowhile(cond={$pe.st}, block={$b.st})
510     |   ^(SWITCH pe=parenthesizedExpression (scls+=switchCaseLabel)*)
511         -> switch(expr={$pe.st}, labels={$scls})
512     |   ^(RETURN e=expression?)
513         -> return(val={$e.st})
514     |   ^(THROW expression)
515         -> template(t={$text}) "/* throw not implemented */ <t>"
516     |   ^(BREAK IDENT?)
517         -> template() "break;" // TODO: support labeling
518     |   ^(CONTINUE IDENT?)
519         -> template() "continue;" // TODO: support labeling
520     |   ^(LABELED_STATEMENT i=IDENT s=statement)
521         -> label(text={$i.text}, stmt={$s.st})
522     |   expression
523         -> template(expr={$expression.st}) "<expr>;"
524     |   ^('delete' qualifiedIdentifier)
525         -> template(t={$qualifiedIdentifier.st}) "delete <t>;"
526     |   ^('embed' STRING_LITERAL EMBED_BLOCK)
527         ->  embed_cc(str={$STRING_LITERAL.text}, blk={$EMBED_BLOCK.text})
528     |   ';' // Empty statement.
529         -> {%{$start.getText()}}
530     ;
531         
532 switchCaseLabel
533     :   ^(CASE expression (b+=blockStatement)*)
534         -> case(expr={$expression.st}, block={$b})
535     |   ^(DEFAULT (b+=blockStatement)*)
536         -> template(block={$b}) "default: <block>"
537     ;
538     
539 forInit
540     :   localVariableDeclaration
541         -> template(lvd={$localVariableDeclaration.st}) "<lvd>"
542     |   (ex+=expression)+
543         -> template(ex={$ex}) "<ex; separator=\", \">"
544     ;
545
546 // EXPRESSIONS
547
548 parenthesizedExpression
549     :   ^(PAREN_EXPR exp=expression)
550         -> template(expr={$exp.st}) "(<expr>)"
551     ;
552     
553 expression
554     :   ^(EXPR expr)
555         -> {$expr.st}
556     ;
557
558 expr
559     :   ^(ASSIGNMENT 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)
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 e3=expr)
584         -> template(e1={$e1.st}, e2={$e2.st}, e3={$e3.st}) "<e1> ? <e2> : <e3>"
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     |   ^(BITWISE_OR 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     |   ^(EQUALS 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     |   ^('instanceof' expr type)
600         -> template(t={$text}) "/* instanceof not implemented */ <t>"
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     |   ^('-' 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     |   ^(UNARY_PLUS e1=expr)
626         -> template(e1={$e1.st}) "+<e1>"
627     |   ^(UNARY_MINUS e1=expr)
628         -> template(e1={$e1.st}) "-<e1>"
629     |   ^(PRE_INC e1=expr)
630         -> template(e1={$e1.st}) "++<e1>"
631     |   ^(PRE_DEC e1=expr)
632         -> template(e1={$e1.st}) "--<e1>"
633     |   ^(POST_INC e1=expr)
634         -> template(e1={$e1.st}) "<e1>++"
635     |   ^(POST_DEC e1=expr)
636         -> template(e1={$e1.st}) "<e1>--"
637     |   ^(TILDE e1=expr)
638         -> template(e1={$e1.st}) "~<e1>"
639     |   ^(NOT e1=expr)
640         -> template(e1={$e1.st}) "!<e1>"
641     |   ^(CAST_EXPR ty=type e1=expr)
642         -> template(ty={$ty.st}, e1={$e1.st}) "(<ty>)<e1>"
643     |   primaryExpression
644         -> {$primaryExpression.st}
645     ;
646
647 primaryExpression
648     :   ^(DOT prim=primaryExpression
649             ( IDENT   -> template(id={$IDENT}, prim={$prim.st}) "<prim>.<id>"
650             | THIS    -> template(prim={$prim.st}) "<prim>.this"
651             | SUPER   -> template(prim={$prim.st}) "<prim>.super"
652             )
653         )
654     |   ^(ARROW prim=primaryExpression
655             ( IDENT   -> template(id={$IDENT}, prim={$prim.st}) "<prim>-><id>"
656             | THIS    -> template(prim={$prim.st}) "<prim>->this"
657             | SUPER   -> template(prim={$prim.st}) "<prim>->super"
658             )
659         )
660     |   parenthesizedExpression
661         -> {$parenthesizedExpression.st}
662     |   IDENT
663         -> {%{$start.getText()}}
664     |   ^(METHOD_CALL pe=primaryExpression gtal=genericTypeArgumentList? args=arguments)
665         -> method_call(primary={$pe.st}, generic_types={$gtal.st}, args={$args.st})
666     |   ^(ENTRY_METHOD_CALL pe=primaryExpression gtal=genericTypeArgumentList? args=arguments)
667         -> method_call(primary={$pe.st}, generic_types={$gtal.st}, args={$args.st})
668     |   explicitConstructorCall
669         -> {$explicitConstructorCall.st}
670     |   ^(ARRAY_ELEMENT_ACCESS pe=primaryExpression ex=expression)
671         -> template(pe={$pe.st}, ex={$ex.st}) "<pe>[<ex>]"
672     |   literal
673         -> {$literal.st}
674     |   newExpression
675         -> {$newExpression.st}
676     |   THIS
677         -> {%{$start.getText()}}
678     |   arrayTypeDeclarator
679         -> {$arrayTypeDeclarator.st}
680     |   SUPER
681         -> {%{$start.getText()}}
682     ;
683     
684 explicitConstructorCall
685     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
686         -> template(t={$text}) "<t>"
687     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
688         -> template(t={$text}) "<t>"
689     ;
690
691 arrayTypeDeclarator
692     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
693         -> template(t={$text}) "<t>"
694     ;
695
696 newExpression
697     :   ^(  STATIC_ARRAY_CREATOR
698             (   primitiveType newArrayConstruction
699             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
700             )
701         )
702         -> template(t={$text}) "<t>"
703     |   ^(NEW qualifiedTypeIdent arguments)
704         -> template(q={$qualifiedTypeIdent.st}, a={$arguments.st}) "new <q>(<a>)"
705     ;
706
707 newArrayConstruction
708     :   arrayDeclaratorList arrayInitializer
709         -> array_construction_with_init(
710                 array_decls={$arrayDeclaratorList.st},
711                 initializer={$arrayInitializer.st})
712     |   (ex+=expression)+ adl=arrayDeclaratorList?
713         -> array_construction(exprs={$ex}, array_decls={$adl.st})
714     ;
715
716 arguments
717     :   ^(ARGUMENT_LIST (ex+=expression)*)
718         -> arguments(exprs={$ex})
719     ;
720
721 literal
722 @init {
723 $st = %{$start.getText()};
724 }
725     :   HEX_LITERAL
726     |   OCTAL_LITERAL
727     |   DECIMAL_LITERAL
728     |   FLOATING_POINT_LITERAL
729     |   CHARACTER_LITERAL
730     |   STRING_LITERAL
731     |   TRUE
732     |   FALSE
733     |   NULL
734     ;
735