overhaul of statement codegen
[charm.git] / src / langs / charj / src / charj / translator / CharjSemantics.g
1 /**
2  * The semantic phase walks the tree and builds the symbol table, handles
3  * all the imports, and does the semantic checks. The resulting tree and
4  * symbol table are used by the emitter to generate the output. 
5  */
6
7 tree grammar CharjSemantics;
8
9 options {
10     backtrack = true; 
11     memoize = true;
12     tokenVocab = Charj;
13     ASTLabelType = CharjAST;
14 }
15
16 scope ScopeStack {
17     Scope current;
18 }
19
20 @header {
21 package charj.translator;
22 }
23
24 @members {
25     SymbolTable symtab = null;
26     PackageScope currentPackage = null;
27     ClassSymbol currentClass = null;
28     MethodSymbol currentMethod = null;
29     LocalScope currentLocalScope = null;
30     Translator translator;
31
32     /**
33      *  Test a list of CharjAST nodes to see if any of them has the given token
34      *  type.
35      */
36     public boolean listContainsToken(List<CharjAST> list, int tokenType) {
37         if (list == null) return false;
38         for (CharjAST node : list) {
39             if (node.token.getType() == tokenType) {
40                 return true;
41             }
42         }
43         return false;
44     }
45
46     public void importPackages(ClassSymbol cs, List<CharjAST> imports) {
47         if (imports == null) {
48             return;
49         }
50
51         for (CharjAST pkg : imports) {
52             String pkgName = input.getTokenStream().toString(
53                     pkg.getTokenStartIndex(),
54                     pkg.getTokenStopIndex());
55             // find imported class and add to cs.imports
56             PackageScope p = cs.importPackage(pkgName);
57             if (p == null) {
58                 translator.error(
59                     this, 
60                     "package " + pkgName + " not found.",
61                     pkg);
62             }
63         }
64     }
65 }
66
67
68 // Replace default ANTLR generated catch clauses with this action, allowing early failure.
69 @rulecatch {
70     catch (RecognitionException re) {
71         reportError(re);
72         throw re;
73     }
74 }
75
76
77 // Starting point for parsing a Charj file.
78 charjSource[SymbolTable _symtab] returns [ClassSymbol cs]
79 scope ScopeStack; // default scope
80 @init {
81     symtab = _symtab;
82     $ScopeStack::current = symtab.getDefaultPkg();
83 }
84     // TODO: go back to allowing multiple type definitions per file, check that
85     // there is exactly one public type and return that one.
86     :   ^(CHARJ_SOURCE 
87         (packageDeclaration)? 
88         (importDeclarations) 
89         (typeDeclaration[$importDeclarations.packageNames]))
90         //(typeDeclaration)*)
91         { $cs = $typeDeclaration.sym; }
92     ;
93
94 // note: no new scope here--this replaces the default scope
95 packageDeclaration
96 @init { 
97     List<String> names = null; 
98 }
99     :   ^(PACKAGE qualifiedIdentifier)  {
100             String packageName = $qualifiedIdentifier.text;
101             PackageScope ps = symtab.resolvePackage(packageName);
102             if (ps == null) {
103                 ps = symtab.definePackage(packageName);
104                 symtab.addScope(ps);
105             }
106             currentPackage = ps;
107             $ScopeStack::current = ps;
108             $qualifiedIdentifier.start.symbol = ps;
109         }
110     ;
111     
112 importDeclarations returns [List<CharjAST> packageNames]
113 @init {
114         packageNames = new ArrayList<CharjAST>();
115 }
116     :   (^(IMPORT STATIC? qualifiedIdentifier DOTSTAR?)
117                 { packageNames.add($qualifiedIdentifier.start); })*
118     ;
119
120
121 typeDeclaration[List<CharjAST> imports] returns [ClassSymbol sym]
122 scope ScopeStack; // top-level type scope
123     :   ^(CLASS m=modifierList IDENT g=genericTypeParameterList? 
124                 e=classExtendsClause? i=implementsClause? c=classTopLevelScope) 
125         {
126             Scope outerScope = $ScopeStack[-1]::current;
127             $sym = new ClassSymbol(symtab, $IDENT.text, null, outerScope);
128             outerScope.define($sym.name, $sym);
129             currentClass = $sym;
130             $sym.definition = $typeDeclaration.start;
131             $sym.definitionTokenStream = input.getTokenStream();
132             $IDENT.symbol = $sym;
133             $ScopeStack::current = $sym;
134             importPackages($sym, $imports);
135         }
136     |   ^(INTERFACE modifierList IDENT genericTypeParameterList? 
137                 interfaceExtendsClause? interfaceTopLevelScope)
138     |   ^(ENUM modifierList IDENT implementsClause? enumTopLevelScope)
139     ;
140
141
142 classExtendsClause
143     :   ^(EXTENDS_CLAUSE t=type) 
144     ;   
145
146 interfaceExtendsClause 
147     :   ^(EXTENDS_CLAUSE (type)+) 
148     ;   
149     
150 implementsClause
151     :   ^(IMPLEMENTS_CLAUSE type+)
152     ;
153         
154 genericTypeParameterList
155     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
156     ;
157
158 genericTypeParameter
159     :   ^(IDENT bound?)
160     ;
161         
162 bound
163     :   ^(EXTENDS_BOUND_LIST type+)
164     ;
165
166 enumTopLevelScope
167     :   ^(ENUM_TOP_LEVEL_SCOPE enumConstant+ classTopLevelScope?)
168     ;
169     
170 enumConstant
171     :   ^(IDENT arguments? classTopLevelScope?)
172     ;
173     
174     
175 classTopLevelScope
176     :   ^(CLASS_TOP_LEVEL_SCOPE (classScopeDeclarations)*) 
177     ;
178     
179 classScopeDeclarations
180     :   ^(CLASS_INSTANCE_INITIALIZER block)
181     |   ^(CLASS_STATIC_INITIALIZER block)
182     |   ^(FUNCTION_METHOD_DECL m=modifierList g=genericTypeParameterList? 
183             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
184             tc=throwsClause? b=block?)
185     |   ^(VOID_METHOD_DECL m=modifierList g=genericTypeParameterList? IDENT 
186             f=formalParameterList t=throwsClause? b=block?)
187     |   ^(PRIMITIVE_VAR_DECLARATION modifierList simpleType variableDeclaratorList)
188     |   ^(OBJECT_VAR_DECLARATION modifierList objectType variableDeclaratorList)
189     |   ^(CONSTRUCTOR_DECL m=modifierList g=genericTypeParameterList? IDENT f=formalParameterList 
190             t=throwsClause? b=block)
191     |   d=typeDeclaration[null]
192     ;
193     
194 interfaceTopLevelScope
195     :   ^(INTERFACE_TOP_LEVEL_SCOPE interfaceScopeDeclarations*)
196     ;
197     
198 interfaceScopeDeclarations
199     :   ^(FUNCTION_METHOD_DECL modifierList genericTypeParameterList? 
200             type IDENT formalParameterList arrayDeclaratorList? throwsClause?)
201     |   ^(VOID_METHOD_DECL modifierList genericTypeParameterList? IDENT formalParameterList throwsClause?)
202         // Interface constant declarations have been switched to variable
203         // declarations by Charj.g; the parser has already checked that
204         // there's an obligatory initializer.
205     |   ^(PRIMITIVE_VAR_DECLARATION modifierList simpleType variableDeclaratorList)
206     |   ^(OBJECT_VAR_DECLARATION modifierList objectType variableDeclaratorList)
207     |   typeDeclaration[null]
208     ;
209
210 variableDeclaratorList
211     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
212     ;
213
214 variableDeclarator
215     :   ^(VAR_DECLARATOR variableDeclaratorId variableInitializer?)
216     ;
217     
218 variableDeclaratorId
219     :   ^(IDENT arrayDeclaratorList?)
220     ;
221
222 variableInitializer
223     :   arrayInitializer
224     |   expression
225     ;
226
227 arrayDeclarator
228     :   LBRACK RBRACK
229     ;
230
231 arrayDeclaratorList
232     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
233     ;
234     
235 arrayInitializer
236     :   ^(ARRAY_INITIALIZER variableInitializer*)
237     ;
238
239 throwsClause
240     :   ^(THROWS_CLAUSE qualifiedIdentifier+)
241     ;
242
243 modifierList
244     :   ^(MODIFIER_LIST (modifier)*)
245     ;
246
247 modifier
248     :   PUBLIC
249     |   PROTECTED
250     |   PRIVATE
251     |   ENTRY
252     |   STATIC
253     |   ABSTRACT
254     |   NATIVE
255     |   SYNCHRONIZED
256     |   TRANSIENT
257     |   VOLATILE
258     |   localModifier
259     ;
260
261 localModifierList
262     :   ^(LOCAL_MODIFIER_LIST localModifier*)
263     ;
264
265 localModifier
266     :   FINAL
267     ;
268
269 type
270     :   simpleType
271     |   objectType 
272     ;
273
274 simpleType
275     :   ^(TYPE primitiveType arrayDeclaratorList?)
276     ;
277     
278 objectType
279     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
280     ;
281
282 qualifiedTypeIdent
283     :   ^(QUALIFIED_TYPE_IDENT typeIdent+) 
284     ;
285
286 typeIdent
287     :   ^(IDENT genericTypeArgumentList?)
288     ;
289
290 primitiveType
291     :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
292     |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
293     |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
294     |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
295     |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
296     |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
297     |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
298     |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
299     ;
300
301 genericTypeArgumentList
302     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
303     ;
304     
305 genericTypeArgument
306     :   type
307     |   ^(QUESTION genericWildcardBoundType?)
308     ;
309
310 genericWildcardBoundType                                                                                                                      
311     :   ^(EXTENDS type)
312     |   ^(SUPER type)
313     ;
314
315 formalParameterList
316     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
317     ;
318     
319 formalParameterStandardDecl
320     :   ^(FORMAL_PARAM_STD_DECL localModifierList type variableDeclaratorId)
321     ;
322     
323 formalParameterVarargDecl
324     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList type variableDeclaratorId)
325     ;
326     
327 qualifiedIdentifier
328     :   IDENT
329     |   ^(DOT qualifiedIdentifier IDENT)
330     ;
331     
332 block
333     :   ^(BLOCK_SCOPE (blockStatement)*)
334     ;
335     
336 blockStatement
337     :   localVariableDeclaration
338     |   typeDeclaration[null]
339     |   statement
340     ;
341     
342 localVariableDeclaration
343     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList simpleType variableDeclaratorList)
344     |   ^(OBJECT_VAR_DECLARATION localModifierList objectType variableDeclaratorList)
345     ;
346
347
348 statement
349     :   block
350     |   ^(ASSERT expression expression?)
351     |   ^(IF parenthesizedExpression statement statement?)
352     |   ^(FOR forInit forCondition forUpdater statement)
353     |   ^(FOR_EACH localModifierList type IDENT expression statement) 
354     |   ^(WHILE parenthesizedExpression statement)
355     |   ^(DO statement parenthesizedExpression)
356     |   ^(TRY block catches? block?)  // The second optional block is the optional finally block.
357     |   ^(SWITCH parenthesizedExpression switchBlockLabels)
358     |   ^(SYNCHRONIZED parenthesizedExpression block)
359     |   ^(RETURN expression?)
360     |   ^(THROW expression)
361     |   ^(BREAK IDENT?) {
362             if ($IDENT != null) {
363                 translator.error(this, "Labeled break not supported yet, ignoring.", $ID);
364             }
365         }
366     |   ^(CONTINUE IDENT?) {
367             if ($IDENT != null) {
368                 translator.error(this, "Labeled continue not supported yet, ignoring.", $ID);
369             }
370         }
371     |   ^(LABELED_STATEMENT IDENT statement)
372     |   expression
373     |   ^(EMBED STRING_LITERAL EMBED_BLOCK)
374     |   SEMI // Empty statement.
375     ;
376         
377 catches
378     :   ^(CATCH_CLAUSE_LIST catchClause+)
379     ;
380     
381 catchClause
382     :   ^(CATCH formalParameterStandardDecl block)
383     ;
384
385 switchBlockLabels
386     :   ^(SWITCH_BLOCK_LABEL_LIST switchCaseLabel*)
387     ;
388         
389 switchCaseLabel
390     :   ^(CASE expression blockStatement*)
391     |   ^(DEFAULT blockStatement*)
392     ;
393     
394 forInit
395     :   ^(FOR_INIT (localVariableDeclaration | expression*)?)
396     ;
397     
398 forCondition
399     :   ^(FOR_CONDITION expression?)
400     ;
401     
402 forUpdater
403     :   ^(FOR_UPDATE expression*)
404     ;
405     
406 // EXPRESSIONS
407
408 parenthesizedExpression
409     :   ^(PARENTESIZED_EXPR expression)
410     ;
411     
412 expression
413     :   ^(EXPR expr)
414     ;
415
416 expr
417     :   ^(ASSIGN expr expr)
418     |   ^(PLUS_ASSIGN expr expr)
419     |   ^(MINUS_ASSIGN expr expr)
420     |   ^(STAR_ASSIGN expr expr)
421     |   ^(DIV_ASSIGN expr expr)
422     |   ^(AND_ASSIGN expr expr)
423     |   ^(OR_ASSIGN expr expr)
424     |   ^(XOR_ASSIGN expr expr)
425     |   ^(MOD_ASSIGN expr expr)
426     |   ^(BIT_SHIFT_RIGHT_ASSIGN expr expr)
427     |   ^(SHIFT_RIGHT_ASSIGN expr expr)
428     |   ^(SHIFT_LEFT_ASSIGN expr expr)
429     |   ^(QUESTION expr expr expr)
430     |   ^(LOGICAL_OR expr expr)
431     |   ^(LOGICAL_AND expr expr)
432     |   ^(OR expr expr)
433     |   ^(XOR expr expr)
434     |   ^(AND expr expr)
435     |   ^(EQUAL expr expr)
436     |   ^(NOT_EQUAL expr expr)
437     |   ^(INSTANCEOF expr type)
438     |   ^(LESS_OR_EQUAL expr expr)
439     |   ^(GREATER_OR_EQUAL expr expr)
440     |   ^(BIT_SHIFT_RIGHT expr expr)
441     |   ^(SHIFT_RIGHT expr expr)
442     |   ^(GREATER_THAN expr expr)
443     |   ^(SHIFT_LEFT expr expr)
444     |   ^(LESS_THAN expr expr)
445     |   ^(PLUS expr expr)
446     |   ^(MINUS expr expr)
447     |   ^(STAR expr expr)
448     |   ^(DIV expr expr)
449     |   ^(MOD expr expr)
450     |   ^(UNARY_PLUS expr)
451     |   ^(UNARY_MINUS expr)
452     |   ^(PRE_INC expr)
453     |   ^(PRE_DEC expr)
454     |   ^(POST_INC expr)
455     |   ^(POST_DEC expr)
456     |   ^(NOT expr)
457     |   ^(LOGICAL_NOT expr)
458     |   ^(CAST_EXPR type expr)
459     |   primaryExpression
460     ;
461     
462 primaryExpression
463     :   ^(  DOT
464             (   primaryExpression
465                 (   IDENT
466                 |   THIS
467                 |   SUPER
468                 |   innerNewExpression
469                 |   CLASS
470                 )
471             |   primitiveType CLASS
472             |   VOID CLASS
473             )
474         )
475     |   parenthesizedExpression
476     |   IDENT
477     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
478     |   explicitConstructorCall
479     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
480     |   literal
481     |   newExpression
482     |   THIS
483     |   arrayTypeDeclarator
484     |   SUPER
485     ;
486     
487 explicitConstructorCall
488     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
489     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
490     ;
491
492 arrayTypeDeclarator
493     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
494     ;
495
496 newExpression
497     :   ^(  STATIC_ARRAY_CREATOR
498             (   primitiveType newArrayConstruction
499             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
500             )
501         )
502     |   ^(CLASS_CONSTRUCTOR_CALL genericTypeArgumentList? qualifiedTypeIdent arguments classTopLevelScope?)
503     ;
504
505 innerNewExpression // something like 'InnerType innerType = outer.new InnerType();'
506     :   ^(CLASS_CONSTRUCTOR_CALL genericTypeArgumentList? IDENT arguments classTopLevelScope?)
507     ;
508     
509 newArrayConstruction
510     :   arrayDeclaratorList arrayInitializer
511     |   expression+ arrayDeclaratorList?
512     ;
513
514 arguments
515     :   ^(ARGUMENT_LIST expression*)
516     ;
517
518 literal 
519     :   HEX_LITERAL
520     |   OCTAL_LITERAL
521     |   DECIMAL_LITERAL
522     |   FLOATING_POINT_LITERAL
523     |   CHARACTER_LITERAL
524     |   STRING_LITERAL          
525     |   TRUE
526     |   FALSE
527     |   NULL
528     ;
529