2130bc5df5d238ceeaa302472bb67e1bd7711266
[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+))? classScopeDeclaration*)
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     |   ^('interface' IDENT (^('extends' type+))?  interfaceScopeDeclaration*)
139     |   ^('enum' IDENT (^('implements' type+))? enumConstant+ classScopeDeclaration*)
140     ;
141
142 chareType
143     :   CHARE
144     |   GROUP
145     |   NODEGROUP
146     |   ^(CHARE_ARRAY ARRAY_DIMENSION)
147     ;
148
149 enumConstant
150     :   ^(IDENT arguments?)
151     ;
152     
153 classScopeDeclaration
154 scope ScopeStack;
155     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
156             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
157             b=block?)
158         {
159             /*
160             ClassSymbol returnType = currentClass.resolveType($ty.text);
161             MethodSymbol sym = new MethodSymbol(symtab, $IDENT.text, currentClass, returnType);
162             currentMethod = sym;
163             sym.definition = $classScopeDeclaration.start;
164             sym.definitionTokenStream = input.getTokenStream();
165             currentClass.members.put($IDENT.text, sym);
166             $FUNCTION_METHOD_DECL.symbol = sym;
167             */
168         }
169     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
170     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
171     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList 
172             b=block)
173     ;
174     
175 interfaceScopeDeclaration
176     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? 
177             type IDENT formalParameterList arrayDeclaratorList?)
178         // Interface constant declarations have been switched to variable
179         // declarations by Charj.g; the parser has already checked that
180         // there's an obligatory initializer.
181     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
182     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
183     ;
184
185 variableDeclaratorList
186     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
187     ;
188
189 variableDeclarator
190     :   ^(VAR_DECLARATOR variableDeclaratorId variableInitializer?)
191     ;
192     
193 variableDeclaratorId
194     :   ^(IDENT arrayDeclaratorList?)
195     ;
196
197 variableInitializer
198     :   arrayInitializer
199     |   expression
200     ;
201
202 arrayDeclaratorList
203     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
204     ;
205     
206 arrayInitializer
207     :   ^(ARRAY_INITIALIZER variableInitializer*)
208     ;
209
210 genericTypeParameterList
211     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
212     ;
213
214 genericTypeParameter
215     :   ^(IDENT bound?)
216     ;
217         
218 bound
219     :   ^(EXTENDS_BOUND_LIST type+)
220     ;
221
222 modifierList
223     :   ^(MODIFIER_LIST modifier+)
224     ;
225
226 modifier
227     :   PUBLIC
228     |   PROTECTED
229     |   ENTRY
230     |   PRIVATE
231     |   ABSTRACT
232     |   NATIVE
233     |   localModifier
234     ;
235
236 localModifierList
237     :   ^(LOCAL_MODIFIER_LIST localModifier+)
238     ;
239
240 localModifier
241     :   FINAL
242     |   STATIC
243     |   VOLATILE
244     ;
245
246 type
247     :   simpleType
248     |   objectType
249     |   VOID
250     ;
251
252 simpleType
253     :   ^(TYPE primitiveType arrayDeclaratorList?)
254     ;
255     
256 objectType
257     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
258     ;
259
260 qualifiedTypeIdent
261     :   ^(QUALIFIED_TYPE_IDENT typeIdent+) 
262     ;
263
264 typeIdent
265     :   ^(IDENT genericTypeArgumentList?)
266     ;
267
268 primitiveType
269     :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
270     |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
271     |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
272     |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
273     |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
274     |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
275     |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
276     |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
277     ;
278
279 genericTypeArgumentList
280     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
281     ;
282     
283 genericTypeArgument
284     :   type
285     |   '?'
286     ;
287
288 formalParameterList
289     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
290     ;
291     
292 formalParameterStandardDecl
293     :   ^(FORMAL_PARAM_STD_DECL localModifierList? type variableDeclaratorId)
294     ;
295     
296 formalParameterVarargDecl
297     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
298     ;
299     
300 // FIXME: is this rule right? Verify that this is ok, I expected something like:
301 // IDENT (^('.' qualifiedIdentifier IDENT))*
302 qualifiedIdentifier
303     :   IDENT
304     |   ^('.' qualifiedIdentifier IDENT)
305     ;
306     
307 block
308     :   ^(BLOCK (blockStatement)*)
309     ;
310     
311 blockStatement
312     :   localVariableDeclaration
313     |   statement
314     ;
315     
316 localVariableDeclaration
317     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
318     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
319     ;
320
321 statement
322     :   block
323     |   ^(ASSERT expression expression?)
324     |   ^(IF parenthesizedExpression statement statement?)
325     |   ^(FOR forInit? FOR_EXPR expression? FOR_UPDATE expression* statement)
326     |   ^(FOR_EACH localModifierList? type IDENT expression statement) 
327     |   ^(WHILE parenthesizedExpression statement)
328     |   ^(DO statement parenthesizedExpression)
329     |   ^(SWITCH parenthesizedExpression switchCaseLabel*)
330     |   ^(RETURN expression?)
331     |   ^(THROW expression)
332     |   ^(BREAK IDENT?) {
333             if ($IDENT != null) {
334                 translator.error(this, "Labeled break not supported yet, ignoring.", $IDENT);
335             }
336         }
337     |   ^(CONTINUE IDENT?) {
338             if ($IDENT != null) {
339                 translator.error(this, "Labeled continue not supported yet, ignoring.", $IDENT);
340             }
341         }
342     |   ^(LABELED_STATEMENT IDENT statement)
343     |   expression
344     |   ^(EMBED STRING_LITERAL EMBED_BLOCK)
345     |   ';' // Empty statement.
346     ;
347         
348 switchCaseLabel
349     :   ^(CASE expression blockStatement*)
350     |   ^(DEFAULT blockStatement*)
351     ;
352     
353 forInit
354     :   localVariableDeclaration 
355     |   expression+
356     ;
357     
358 // EXPRESSIONS
359
360 parenthesizedExpression
361     :   ^(PAREN_EXPR expression)
362     ;
363     
364 expression
365     :   ^(EXPR expr)
366     ;
367
368 expr
369     :   ^('=' expr expr)
370     |   ^('+=' expr expr)
371     |   ^('-=' expr expr)
372     |   ^('*=' expr expr)
373     |   ^('/=' expr expr)
374     |   ^('&=' expr expr)
375     |   ^('|=' expr expr)
376     |   ^('^=' expr expr)
377     |   ^('%=' expr expr)
378     |   ^('>>>=' expr expr)
379     |   ^('>>=' expr expr)
380     |   ^('<<=' expr expr)
381     |   ^('?' expr expr expr)
382     |   ^('||' expr expr)
383     |   ^('&&' expr expr)
384     |   ^('|' expr expr)
385     |   ^('^' expr expr)
386     |   ^('&' expr expr)
387     |   ^('==' expr expr)
388     |   ^('!=' expr expr)
389     |   ^('instanceof' expr type)
390     |   ^('<=' expr expr)
391     |   ^('>=' expr expr)
392     |   ^('>>>' expr expr)
393     |   ^('>>' expr expr)
394     |   ^('>' expr expr)
395     |   ^('<<' expr expr)
396     |   ^('<' expr expr)
397     |   ^('+' expr expr)
398     |   ^('-' expr expr)
399     |   ^('*' expr expr)
400     |   ^('/' expr expr)
401     |   ^('%' expr expr)
402     |   ^(UNARY_PLUS expr)
403     |   ^(UNARY_MINUS expr)
404     |   ^(PRE_INC expr)
405     |   ^(PRE_DEC expr)
406     |   ^(POST_INC expr)
407     |   ^(POST_DEC expr)
408     |   ^('~' expr)
409     |   ^('!' expr)
410     |   ^(CAST_EXPR type expr)
411     |   primaryExpression
412     ;
413     
414 primaryExpression
415     :   ^(  '.' primaryExpression
416                 (   IDENT
417                 |   THIS
418                 |   SUPER
419                 )
420         )
421     |   parenthesizedExpression
422     |   IDENT
423     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
424     |   explicitConstructorCall
425     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
426     |   literal
427     |   newExpression
428     |   THIS
429     |   arrayTypeDeclarator
430     |   SUPER
431     ;
432     
433 explicitConstructorCall
434     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
435     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
436     ;
437
438 arrayTypeDeclarator
439     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
440     ;
441
442 newExpression
443     :   ^(  STATIC_ARRAY_CREATOR
444             (   primitiveType newArrayConstruction
445             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
446             )
447         )
448     ;
449
450 newArrayConstruction
451     :   arrayDeclaratorList arrayInitializer
452     |   expression+ arrayDeclaratorList?
453     ;
454
455 arguments
456     :   ^(ARGUMENT_LIST expression*)
457     ;
458
459 literal 
460     :   HEX_LITERAL
461     |   OCTAL_LITERAL
462     |   DECIMAL_LITERAL
463     |   FLOATING_POINT_LITERAL
464     |   CHARACTER_LITERAL
465     |   STRING_LITERAL          
466     |   TRUE
467     |   FALSE
468     |   NULL 
469     ;
470