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