Charj: allow multiple type definitions per file
[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         { $cs = $typeDeclaration.sym; }
91     ;
92
93 // note: no new scope here--this replaces the default scope
94 packageDeclaration
95 @init { 
96     List<String> names = null; 
97     String packageName = "";
98 }
99     :   ^(PACKAGE ((ids+=IDENT) { packageName += "." + $IDENT.text; })+)
100         {
101             packageName = packageName.substring(1);
102             PackageScope ps = symtab.resolvePackage(packageName);
103             if (ps == null) {
104                 ps = symtab.definePackage(packageName);
105                 symtab.addScope(ps);
106             }
107             currentPackage = ps;
108             $ScopeStack::current = ps;
109         }
110     ;
111     
112 importDeclarations returns [List<CharjAST> packageNames]
113 @init {
114     packageNames = new ArrayList<CharjAST>();
115 }
116     :   (^(IMPORT qualifiedIdentifier '.*'?)
117                 { packageNames.add($qualifiedIdentifier.start); })*
118     ;
119
120
121 typeDeclaration[List<CharjAST> imports] returns [ClassSymbol sym]
122 scope ScopeStack; // top-level type scope
123     :   ^(TYPE (CLASS | chareType) IDENT
124             (^('extends' parent=type))? (^('implements' type+))?
125             {
126                 Scope outerScope = $ScopeStack[-1]::current;
127                 $sym = new ClassSymbol(symtab, $IDENT.text, outerScope.resolveType($parent.text), 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             classScopeDeclaration*)
137             {
138                 //System.out.println("Members for type " + $sym.name + ":");
139                 //for (Map.Entry<String, Symbol> entry : $sym.members.entrySet()) {
140                 //    System.out.println(entry.getKey());
141                 //}
142             }
143     |   ^('interface' IDENT (^('extends' type+))?  interfaceScopeDeclaration*)
144     |   ^('enum' IDENT (^('implements' type+))? enumConstant+ classScopeDeclaration*)
145     ;
146
147 chareType
148     :   CHARE
149     |   GROUP
150     |   NODEGROUP
151     |   MAINCHARE
152     |   ^(CHARE_ARRAY ARRAY_DIMENSION)
153     ;
154
155 enumConstant
156     :   ^(IDENT arguments?)
157     ;
158     
159 classScopeDeclaration
160 scope ScopeStack;
161     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
162             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
163             b=block?)
164         {
165             ClassSymbol returnType = currentClass.resolveType($ty.text);
166             MethodSymbol sym = new MethodSymbol(symtab, $IDENT.text, currentClass, returnType);
167             currentMethod = sym;
168             sym.definition = $classScopeDeclaration.start;
169             sym.definitionTokenStream = input.getTokenStream();
170             currentClass.define($IDENT.text, sym);
171             $FUNCTION_METHOD_DECL.symbol = sym;
172         }
173     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType
174             ^(VAR_DECLARATOR_LIST field[$simpleType.type]+))
175     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType
176             ^(VAR_DECLARATOR_LIST field[$objectType.type]+))
177     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList 
178             b=block)
179     ;
180
181 field [ClassSymbol type]
182     :   ^(VAR_DECLARATOR ^(IDENT arrayDeclaratorList?) variableInitializer?)
183     {
184             VariableSymbol sym = new VariableSymbol(symtab, $IDENT.text, $type);
185             sym.definition = $field.start;
186             sym.definitionTokenStream = input.getTokenStream();
187             $VAR_DECLARATOR.symbol = sym;
188             currentClass.define($IDENT.text, sym);
189     }
190     ;
191     
192 interfaceScopeDeclaration
193     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? 
194             type IDENT formalParameterList arrayDeclaratorList?)
195         // Interface constant declarations have been switched to variable
196         // declarations by Charj.g; the parser has already checked that
197         // there's an obligatory initializer.
198     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
199     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
200     ;
201
202 variableDeclaratorList
203     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
204     ;
205
206 variableDeclarator
207     :   ^(VAR_DECLARATOR ^(IDENT arrayDeclaratorList?) variableInitializer?)
208
209     ;
210     
211 variableDeclaratorId
212     :   ^(IDENT arrayDeclaratorList?)
213     ;
214
215 variableInitializer
216     :   arrayInitializer
217     |   expression
218     ;
219
220 arrayDeclaratorList
221     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
222     ;
223     
224 arrayInitializer
225     :   ^(ARRAY_INITIALIZER variableInitializer*)
226     ;
227
228 genericTypeParameterList
229     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
230     ;
231
232 genericTypeParameter
233     :   ^(IDENT bound?)
234     ;
235         
236 bound
237     :   ^(EXTENDS_BOUND_LIST type+)
238     ;
239
240 modifierList
241     :   ^(MODIFIER_LIST modifier+)
242     ;
243
244 modifier
245     :   PUBLIC
246     |   PROTECTED
247     |   ENTRY
248     |   PRIVATE
249     |   ABSTRACT
250     |   NATIVE
251     |   localModifier
252     ;
253
254 localModifierList
255     :   ^(LOCAL_MODIFIER_LIST localModifier+)
256     ;
257
258 localModifier
259     :   FINAL
260     |   STATIC
261     |   VOLATILE
262     ;
263
264 type
265     :   simpleType
266     |   objectType
267     |   VOID
268     ;
269
270 simpleType returns [ClassSymbol type]
271     :   ^(SIMPLE_TYPE primitiveType arrayDeclaratorList?)
272         {
273             $type = symtab.resolveBuiltinType($primitiveType.text);
274         }
275     ;
276     
277 objectType returns [ClassSymbol type]
278     :   ^(OBJECT_TYPE qualifiedTypeIdent arrayDeclaratorList?)
279     |   ^(REFERENCE_TYPE qualifiedTypeIdent arrayDeclaratorList?)
280     |   ^(PROXY_TYPE qualifiedTypeIdent arrayDeclaratorList?)
281     |   ^(POINTER_TYPE qualifiedTypeIdent arrayDeclaratorList?)
282         {
283             $type = currentClass.resolveType($qualifiedTypeIdent.name);
284             if ($type == null) $type = symtab.resolveBuiltinType($qualifiedTypeIdent.name);
285         }
286     ;
287
288 qualifiedTypeIdent returns [String name]
289 @init {
290 $name = "";
291 }
292     :   ^(QUALIFIED_TYPE_IDENT (typeIdent {$name += $typeIdent.name;})+) 
293     ;
294
295 typeIdent returns [String name]
296     :   ^(IDENT genericTypeArgumentList?)
297         { $name = $IDENT.text; }
298     ;
299
300 primitiveType
301     :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
302     |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
303     |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
304     |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
305     |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
306     |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
307     |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
308     |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
309     ;
310
311 genericTypeArgumentList
312     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
313     ;
314     
315 genericTypeArgument
316     :   type
317     |   '?'
318     ;
319
320 formalParameterList
321     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
322     ;
323     
324 formalParameterStandardDecl
325     :   ^(FORMAL_PARAM_STD_DECL localModifierList? type variableDeclaratorId)
326     ;
327     
328 formalParameterVarargDecl
329     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
330     ;
331     
332 // FIXME: is this rule right? Verify that this is ok, I expected something like:
333 // IDENT (^(DOT qualifiedIdentifier IDENT))*
334 qualifiedIdentifier
335     :   IDENT
336     |   ^(DOT qualifiedIdentifier IDENT)
337     ;
338     
339 block
340     :   ^(BLOCK (blockStatement)*)
341     ;
342     
343 blockStatement
344     :   localVariableDeclaration
345     |   statement
346     ;
347     
348 localVariableDeclaration
349     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
350     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
351     ;
352
353 statement
354     : nonBlockStatement
355     | block
356     ;
357
358 nonBlockStatement
359     :   ^(ASSERT expression expression?)
360     |   ^(IF parenthesizedExpression block block?)
361     |   ^(FOR forInit? FOR_EXPR expression? FOR_UPDATE expression* block)
362     |   ^(FOR_EACH localModifierList? type IDENT expression block) 
363     |   ^(WHILE parenthesizedExpression block)
364     |   ^(DO block parenthesizedExpression)
365     |   ^(SWITCH parenthesizedExpression switchCaseLabel*)
366     |   ^(RETURN expression?)
367     |   ^(THROW expression)
368     |   ^(BREAK IDENT?) {
369             if ($IDENT != null) {
370                 translator.error(this, "Labeled break not supported yet, ignoring.", $IDENT);
371             }
372         }
373     |   ^(CONTINUE IDENT?) {
374             if ($IDENT != null) {
375                 translator.error(this, "Labeled continue not supported yet, ignoring.", $IDENT);
376             }
377         }
378     |   ^(LABELED_STATEMENT IDENT statement)
379     |   expression
380     |   ^('delete' qualifiedIdentifier)
381     |   ^(EMBED STRING_LITERAL EMBED_BLOCK)
382     |   ';' // Empty statement.
383     ;
384         
385 switchCaseLabel
386     :   ^(CASE expression blockStatement*)
387     |   ^(DEFAULT blockStatement*)
388     ;
389     
390 forInit
391     :   localVariableDeclaration 
392     |   expression+
393     ;
394     
395 // EXPRESSIONS
396
397 parenthesizedExpression
398     :   ^(PAREN_EXPR expression)
399     ;
400     
401 expression
402     :   ^(EXPR expr)
403     ;
404
405 expr
406     :   ^(ASSIGNMENT expr expr)
407     |   ^(PLUS_EQUALS expr expr)
408     |   ^(MINUS_EQUALS expr expr)
409     |   ^(TIMES_EQUALS expr expr)
410     |   ^(DIVIDE_EQUALS expr expr)
411     |   ^(AND_EQUALS expr expr)
412     |   ^(OR_EQUALS expr expr)
413     |   ^(POWER_EQUALS expr expr)
414     |   ^(MOD_EQUALS expr expr)
415     |   ^('>>>=' expr expr)
416     |   ^('>>=' expr expr)
417     |   ^('<<=' expr expr)
418     |   ^('?' expr expr expr)
419     |   ^(OR expr expr)
420     |   ^(AND expr expr)
421     |   ^(BITWISE_OR expr expr)
422     |   ^(POWER expr expr)
423     |   ^(BITWISE_AND expr expr)
424     |   ^(EQUALS expr expr)
425     |   ^(NOT_EQUALS expr expr)
426     |   ^(INSTANCEOF expr type)
427     |   ^(LTE expr expr)
428     |   ^(GTE expr expr)
429     |   ^('>>>' expr expr)
430     |   ^('>>' expr expr)
431     |   ^(GT expr expr)
432     |   ^('<<' expr expr)
433     |   ^(LT expr expr)
434     |   ^(PLUS expr expr)
435     |   ^(MINUS expr expr)
436     |   ^(TIMES expr expr)
437     |   ^(DIVIDE expr expr)
438     |   ^(MOD expr expr)
439     |   ^(UNARY_PLUS expr)
440     |   ^(UNARY_MINUS expr)
441     |   ^(PRE_INC expr)
442     |   ^(PRE_DEC expr)
443     |   ^(POST_INC expr)
444     |   ^(POST_DEC expr)
445     |   ^(TILDE expr)
446     |   ^(NOT expr)
447     |   ^(CAST_EXPR type expr)
448     |   primaryExpression
449     ;
450     
451 primaryExpression
452     :   ^(DOT primaryExpression
453                 (   IDENT
454                 |   THIS
455                 |   SUPER
456                 )
457         )
458     |   ^(ARROW primaryExpression
459                 (   IDENT
460                 |   THIS
461                 |   SUPER
462                 )
463         )
464     |   parenthesizedExpression
465     |   IDENT
466     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
467     |   ^(ENTRY_METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
468     |   explicitConstructorCall
469     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
470     |   literal
471     |   newExpression
472     |   THIS
473     |   arrayTypeDeclarator
474     |   SUPER
475     ;
476     
477 explicitConstructorCall
478     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
479     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
480     ;
481
482 arrayTypeDeclarator
483     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
484     ;
485
486 newExpression
487     :   ^(  STATIC_ARRAY_CREATOR
488             (   primitiveType newArrayConstruction
489             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
490             )
491         )
492     |   ^(NEW qualifiedTypeIdent arguments)
493     ;
494
495 newArrayConstruction
496     :   arrayDeclaratorList arrayInitializer
497     |   expression+ arrayDeclaratorList?
498     ;
499
500 arguments
501     :   ^(ARGUMENT_LIST expression*)
502     ;
503
504 literal 
505     :   HEX_LITERAL
506     |   OCTAL_LITERAL
507     |   DECIMAL_LITERAL
508     |   FLOATING_POINT_LITERAL
509     |   CHARACTER_LITERAL
510     |   STRING_LITERAL          
511     |   TRUE
512     |   FALSE
513     |   NULL 
514     ;
515