Charj: added some provisions for handling mainchares
[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 variableDeclaratorList)
176     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
177     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList 
178             b=block)
179     ;
180     
181 interfaceScopeDeclaration
182     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? 
183             type IDENT formalParameterList arrayDeclaratorList?)
184         // Interface constant declarations have been switched to variable
185         // declarations by Charj.g; the parser has already checked that
186         // there's an obligatory initializer.
187     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
188     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
189     ;
190
191 variableDeclaratorList
192     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
193     ;
194
195 variableDeclarator
196     :   ^(VAR_DECLARATOR variableDeclaratorId variableInitializer?)
197     ;
198     
199 variableDeclaratorId
200     :   ^(IDENT arrayDeclaratorList?)
201     ;
202
203 variableInitializer
204     :   arrayInitializer
205     |   expression
206     ;
207
208 arrayDeclaratorList
209     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
210     ;
211     
212 arrayInitializer
213     :   ^(ARRAY_INITIALIZER variableInitializer*)
214     ;
215
216 genericTypeParameterList
217     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
218     ;
219
220 genericTypeParameter
221     :   ^(IDENT bound?)
222     ;
223         
224 bound
225     :   ^(EXTENDS_BOUND_LIST type+)
226     ;
227
228 modifierList
229     :   ^(MODIFIER_LIST modifier+)
230     ;
231
232 modifier
233     :   'public'
234     |   'protected'
235     |   'private'
236     |   'entry'
237     |   'abstract'
238     |   'native'
239     |   localModifier
240     ;
241
242 localModifierList
243     :   ^(LOCAL_MODIFIER_LIST localModifier+)
244     ;
245
246 localModifier
247     :   'final'
248     |   'static'
249     |   'volatile'
250     ;
251
252 type
253     :   simpleType
254     |   objectType 
255     |   'void'
256     ;
257
258 simpleType
259     :   ^(TYPE primitiveType arrayDeclaratorList?)
260     ;
261     
262 objectType
263     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
264     ;
265
266 qualifiedTypeIdent
267     :   ^(QUALIFIED_TYPE_IDENT typeIdent+) 
268     ;
269
270 typeIdent
271     :   ^(IDENT genericTypeArgumentList?)
272     ;
273
274 primitiveType
275     :   'boolean'     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
276     |   'char'        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
277     |   'byte'        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
278     |   'short'       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
279     |   'int'         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
280     |   'long'        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
281     |   'float'       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
282     |   'double'      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
283     ;
284
285 genericTypeArgumentList
286     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
287     ;
288     
289 genericTypeArgument
290     :   type
291     |   '?'
292     ;
293
294 formalParameterList
295     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
296     ;
297     
298 formalParameterStandardDecl
299     :   ^(FORMAL_PARAM_STD_DECL localModifierList? type variableDeclaratorId)
300     ;
301     
302 formalParameterVarargDecl
303     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
304     ;
305     
306 // FIXME: is this rule right? Verify that this is ok, I expected something like:
307 // IDENT (^('.' qualifiedIdentifier IDENT))*
308 qualifiedIdentifier
309     :   IDENT
310     |   ^('.' qualifiedIdentifier IDENT)
311     ;
312     
313 block
314     :   ^(BLOCK (blockStatement)*)
315     ;
316     
317 blockStatement
318     :   localVariableDeclaration
319     |   statement
320     ;
321     
322 localVariableDeclaration
323     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
324     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
325     ;
326
327 statement
328     :   block
329     |   ^('assert' expression expression?)
330     |   ^('if' parenthesizedExpression statement statement?)
331     |   ^('for' forInit? FOR_EXPR expression? FOR_UPDATE expression* statement)
332     |   ^(FOR_EACH localModifierList? type IDENT expression statement) 
333     |   ^('while' parenthesizedExpression statement)
334     |   ^('do' statement parenthesizedExpression)
335     |   ^('switch' parenthesizedExpression switchCaseLabel*)
336     |   ^('return' expression?)
337     |   ^('throw' expression)
338     |   ^('break' IDENT?) {
339             if ($IDENT != null) {
340                 translator.error(this, "Labeled break not supported yet, ignoring.", $IDENT);
341             }
342         }
343     |   ^('continue' IDENT?) {
344             if ($IDENT != null) {
345                 translator.error(this, "Labeled continue not supported yet, ignoring.", $IDENT);
346             }
347         }
348     |   ^(LABELED_STATEMENT IDENT statement)
349     |   expression
350     |   ^('embed' STRING_LITERAL EMBED_BLOCK)
351     |   ';' // Empty statement.
352     ;
353         
354 switchCaseLabel
355     :   ^('case' expression blockStatement*)
356     |   ^('default' blockStatement*)
357     ;
358     
359 forInit
360     :   localVariableDeclaration 
361     |   expression+
362     ;
363     
364 // EXPRESSIONS
365
366 parenthesizedExpression
367     :   ^(PAREN_EXPR expression)
368     ;
369     
370 expression
371     :   ^(EXPR expr)
372     ;
373
374 expr
375     :   ^('=' expr expr)
376     |   ^('+=' expr expr)
377     |   ^('-=' expr expr)
378     |   ^('*=' expr expr)
379     |   ^('/=' expr expr)
380     |   ^('&=' expr expr)
381     |   ^('|=' expr expr)
382     |   ^('^=' expr expr)
383     |   ^('%=' expr expr)
384     |   ^('>>>=' expr expr)
385     |   ^('>>=' expr expr)
386     |   ^('<<=' expr expr)
387     |   ^('?' expr expr expr)
388     |   ^('||' expr expr)
389     |   ^('&&' expr expr)
390     |   ^('|' expr expr)
391     |   ^('^' expr expr)
392     |   ^('&' expr expr)
393     |   ^('==' expr expr)
394     |   ^('!=' expr expr)
395     |   ^('instanceof' expr type)
396     |   ^('<=' expr expr)
397     |   ^('>=' expr expr)
398     |   ^('>>>' expr expr)
399     |   ^('>>' expr expr)
400     |   ^('>' expr expr)
401     |   ^('<<' expr expr)
402     |   ^('<' expr expr)
403     |   ^('+' expr expr)
404     |   ^('-' expr expr)
405     |   ^('*' expr expr)
406     |   ^('/' expr expr)
407     |   ^('%' expr expr)
408     |   ^(UNARY_PLUS expr)
409     |   ^(UNARY_MINUS expr)
410     |   ^(PRE_INC expr)
411     |   ^(PRE_DEC expr)
412     |   ^(POST_INC expr)
413     |   ^(POST_DEC expr)
414     |   ^('~' expr)
415     |   ^('!' expr)
416     |   ^(CAST_EXPR type expr)
417     |   primaryExpression
418     ;
419     
420 primaryExpression
421     :   ^(  '.' primaryExpression
422                 (   IDENT
423                 |   'this'
424                 |   'super'
425                 )
426         )
427     |   parenthesizedExpression
428     |   IDENT
429     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
430     |   explicitConstructorCall
431     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
432     |   literal
433     |   newExpression
434     |   'this'
435     |   arrayTypeDeclarator
436     |   'super'
437     ;
438     
439 explicitConstructorCall
440     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
441     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
442     ;
443
444 arrayTypeDeclarator
445     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
446     ;
447
448 newExpression
449     :   ^(  STATIC_ARRAY_CREATOR
450             (   primitiveType newArrayConstruction
451             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
452             )
453         )
454     ;
455
456 newArrayConstruction
457     :   arrayDeclaratorList arrayInitializer
458     |   expression+ arrayDeclaratorList?
459     ;
460
461 arguments
462     :   ^(ARGUMENT_LIST expression*)
463     ;
464
465 literal 
466     :   HEX_LITERAL
467     |   OCTAL_LITERAL
468     |   DECIMAL_LITERAL
469     |   FLOATING_POINT_LITERAL
470     |   CHARACTER_LITERAL
471     |   STRING_LITERAL          
472     |   'true'
473     |   'false'
474     |   'null'
475     ;
476