1906b4f612fc0e712df2424a2528529933d65e0d
[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     List<CharjAST> imports = new ArrayList<CharjAST>();
32     AstModifier astmod = new AstModifier();
33
34     /**
35      *  Test a list of CharjAST nodes to see if any of them has the given token
36      *  type.
37      */
38     public boolean listContainsToken(List<CharjAST> list, int tokenType) {
39         if (list == null) return false;
40         for (CharjAST node : list) {
41             if (node.token.getType() == tokenType) {
42                 return true;
43             }
44         }
45         return false;
46     }
47
48     public void importPackages(ClassSymbol cs, List<CharjAST> imports) {
49         if (imports == null) {
50             return;
51         }
52
53         for (CharjAST pkg : imports) {
54             String pkgName = input.getTokenStream().toString(
55                     pkg.getTokenStartIndex(),
56                     pkg.getTokenStopIndex());
57             // find imported class and add to cs.imports
58             PackageScope p = cs.importPackage(pkgName);
59             if (p == null) {
60                 translator.error(
61                     this, 
62                     "package " + pkgName + " not found.",
63                     pkg);
64             }
65         }
66     }
67
68     public void addImport(CharjAST importNode) {
69         imports.add(importNode);
70     }
71 }
72
73
74 // Replace default ANTLR generated catch clauses with this action, allowing early failure.
75 @rulecatch {
76     catch (RecognitionException re) {
77         reportError(re);
78         throw re;
79     }
80 }
81
82
83 // Starting point for parsing a Charj file.
84 charjSource[SymbolTable _symtab] returns [ClassSymbol cs]
85 scope ScopeStack; // default scope
86 @init {
87     symtab = _symtab;
88     $ScopeStack::current = symtab.getDefaultPkg();
89 }
90     :   ^(CHARJ_SOURCE 
91         (packageDeclaration)? 
92         (importDeclaration
93         | typeDeclaration { $cs = $typeDeclaration.sym; }
94         | readonlyDeclaration)*)
95     ;
96
97 // note: no new scope here--this replaces the default scope
98 packageDeclaration
99 @init { 
100     List<String> names = null; 
101     String packageName = "";
102 }
103     :   ^(PACKAGE ((ids+=IDENT) { packageName += "." + $IDENT.text; })+)
104         {
105             packageName = packageName.substring(1);
106             PackageScope ps = symtab.resolvePackage(packageName);
107             if (ps == null) {
108                 ps = symtab.definePackage(packageName);
109                 symtab.addScope(ps);
110             }
111             currentPackage = ps;
112             $ScopeStack::current = ps;
113         }
114     ;
115     
116 importDeclaration
117     :   ^(IMPORT qualifiedIdentifier '.*'?)
118         { addImport($qualifiedIdentifier.start); }
119     ;
120
121 readonlyDeclaration
122     :   ^(READONLY localVariableDeclaration)
123     ;
124
125 typeDeclaration returns [ClassSymbol sym]
126 scope ScopeStack; // top-level type scope
127     :   ^(TYPE classType IDENT
128             (^('extends' parent=type))? (^('implements' type+))?
129             {
130                 Scope outerScope = $ScopeStack[-1]::current;
131                 $sym = new ClassSymbol(symtab, $IDENT.text, outerScope.resolveType($parent.text), outerScope);
132                 outerScope.define($sym.name, $sym);
133                 currentClass = $sym;
134                 $sym.definition = $typeDeclaration.start;
135                 $sym.definitionTokenStream = input.getTokenStream();
136                 $IDENT.symbol = $sym;
137                 $ScopeStack::current = $sym;
138                 String classTypeName = $classType.text;
139                 if (classTypeName.equals("class")) {
140                 } else if (classTypeName.equals("chare")) {
141                     currentClass.isChare = true;
142                 } else if (classTypeName.equals("group")) {
143                     currentClass.isChare = true;
144                 } else if (classTypeName.equals("nodegroup")) {
145                     currentClass.isChare = true;
146                 } else if (classTypeName.equals("chare_array")) {
147                     currentClass.isChare = true;
148                 } else if (classTypeName.equals("mainchare")) {
149                     currentClass.isChare = true;
150                     currentClass.isMainChare = true;
151                 } else System.out.println("Error: type " + classTypeName + " not recognized.");
152                 importPackages($sym, imports);
153             }
154             classScopeDeclaration*)
155             {
156                 //System.out.println("Members for type " + $sym.name + ":");
157                 //for (Map.Entry<String, Symbol> entry : $sym.members.entrySet()) {
158                 //    System.out.println(entry.getKey());
159                 //}
160             }
161     |   ^('interface' IDENT (^('extends' type+))?  interfaceScopeDeclaration*)
162     |   ^('enum' IDENT (^('implements' type+))? enumConstant+ classScopeDeclaration*)
163     ;
164
165 classType
166     :   CLASS
167     |   chareType
168     ;
169
170 chareType
171     :   CHARE
172     |   GROUP
173     |   NODEGROUP
174     |   MAINCHARE
175     |   ^(CHARE_ARRAY ARRAY_DIMENSION)
176     ;
177
178 enumConstant
179     :   ^(IDENT arguments?)
180     ;
181     
182 classScopeDeclaration
183 scope ScopeStack;
184     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
185             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
186             b=block?)
187         {
188             ClassSymbol returnType = currentClass.resolveType($ty.text);
189             MethodSymbol sym = new MethodSymbol(symtab, $IDENT.text, currentClass, returnType);
190             currentMethod = sym;
191             sym.definition = $classScopeDeclaration.start;
192             sym.definitionTokenStream = input.getTokenStream();
193             currentClass.define($IDENT.text, sym);
194             $FUNCTION_METHOD_DECL.symbol = sym;
195         }
196     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType
197             ^(VAR_DECLARATOR_LIST field[$simpleType.type]+))
198     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType
199             ^(VAR_DECLARATOR_LIST field[$objectType.type]+))
200     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList 
201             b=block)
202         {
203             if (astmod.isMigrationCtor($CONSTRUCTOR_DECL)) currentClass.migrationCtor = $CONSTRUCTOR_DECL;
204         }
205     ;
206
207 field [ClassSymbol type]
208     :   ^(VAR_DECLARATOR ^(IDENT arrayDeclaratorList?) variableInitializer?)
209     {
210             VariableSymbol sym = new VariableSymbol(symtab, $IDENT.text, $type);
211             sym.definition = $field.start;
212             sym.definitionTokenStream = input.getTokenStream();
213             $VAR_DECLARATOR.symbol = sym;
214             currentClass.define($IDENT.text, sym);
215     }
216     ;
217     
218 interfaceScopeDeclaration
219     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? 
220             type IDENT formalParameterList arrayDeclaratorList?)
221         // Interface constant declarations have been switched to variable
222         // declarations by Charj.g; the parser has already checked that
223         // there's an obligatory initializer.
224     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
225     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
226     ;
227
228 variableDeclaratorList
229     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
230     ;
231
232 variableDeclarator
233     :   ^(VAR_DECLARATOR ^(IDENT arrayDeclaratorList?) variableInitializer?)
234
235     ;
236     
237 variableDeclaratorId
238     :   ^(IDENT arrayDeclaratorList?)
239     ;
240
241 variableInitializer
242     :   arrayInitializer
243     |   expression
244     ;
245
246 arrayDeclaratorList
247     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
248     ;
249     
250 arrayInitializer
251     :   ^(ARRAY_INITIALIZER variableInitializer*)
252     ;
253
254 genericTypeParameterList
255     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
256     ;
257
258 genericTypeParameter
259     :   ^(IDENT bound?)
260     ;
261         
262 bound
263     :   ^(EXTENDS_BOUND_LIST type+)
264     ;
265
266 modifierList
267     :   ^(MODIFIER_LIST accessModifierList? localModifierList? charjModifierList? otherModifierList?)
268     ;
269
270 modifier
271     :   accessModifier
272     |   localModifier
273     |   charjModifier
274     |   otherModifier
275     ;
276
277 localModifierList
278     :   ^(LOCAL_MODIFIER_LIST localModifier+)
279     ;
280
281 accessModifierList
282     :   ^(ACCESS_MODIFIER_LIST accessModifier+)
283     ;
284
285 charjModifierList
286     :   ^(CHARJ_MODIFIER_LIST charjModifier+)
287     ;
288
289 otherModifierList
290     :   ^(OTHER_MODIFIER_LIST otherModifier+)
291     ;
292     
293 localModifier
294     :   FINAL
295     |   STATIC
296     |   VOLATILE
297     ;
298
299 accessModifier
300     :   PUBLIC
301     |   PROTECTED
302     |   PRIVATE
303     ;
304
305 charjModifier
306     :   ENTRY
307     ;
308
309 otherModifier
310     :   ABSTRACT
311     |   NATIVE
312     ;
313
314 type
315     :   simpleType
316     |   objectType
317     |   VOID
318     ;
319
320 simpleType returns [ClassSymbol type]
321     :   ^(SIMPLE_TYPE primitiveType arrayDeclaratorList?)
322         {
323             $type = symtab.resolveBuiltinType($primitiveType.text);
324         }
325     ;
326     
327 objectType returns [ClassSymbol type]
328     :   ^(OBJECT_TYPE qualifiedTypeIdent arrayDeclaratorList?)
329     |   ^(REFERENCE_TYPE qualifiedTypeIdent arrayDeclaratorList?)
330     |   ^(PROXY_TYPE qualifiedTypeIdent arrayDeclaratorList?)
331     |   ^(POINTER_TYPE qualifiedTypeIdent arrayDeclaratorList?)
332         {
333             $type = $qualifiedTypeIdent.type;
334         }
335     ;
336
337 qualifiedTypeIdent returns [ClassSymbol type]
338 @init {
339 String name = "";
340 }
341     :   ^(QUALIFIED_TYPE_IDENT (typeIdent {name += $typeIdent.name;})+) 
342         {
343             $type = null;
344             //System.out.println("trying to resolve type " + name + " in type " + currentClass);
345             if (currentClass != null) $type = currentClass.resolveType(name);
346             //System.out.println("got " + $type);
347             //if ($type == null) $type = symtab.resolveBuiltinType(name);
348             $QUALIFIED_TYPE_IDENT.symbol = $type;
349         }
350     ;
351
352 typeIdent returns [String name]
353     :   ^(IDENT genericTypeArgumentList?)
354         { $name = $IDENT.text; }
355     ;
356
357 primitiveType
358     :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
359     |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
360     |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
361     |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
362     |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
363     |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
364     |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
365     |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
366     ;
367
368 genericTypeArgumentList
369     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
370     ;
371     
372 genericTypeArgument
373     :   type
374     |   '?'
375     ;
376
377 formalParameterList
378     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
379     ;
380     
381 formalParameterStandardDecl
382     :   ^(FORMAL_PARAM_STD_DECL localModifierList? type variableDeclaratorId)
383     ;
384     
385 formalParameterVarargDecl
386     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
387     ;
388     
389 // FIXME: is this rule right? Verify that this is ok, I expected something like:
390 // IDENT (^(DOT qualifiedIdentifier IDENT))*
391 qualifiedIdentifier
392     :   IDENT
393     |   ^(DOT qualifiedIdentifier IDENT)
394     ;
395     
396 block
397     :   ^(BLOCK (blockStatement)*)
398     ;
399     
400 blockStatement
401     :   localVariableDeclaration
402     |   statement
403     ;
404     
405 localVariableDeclaration
406     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
407     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
408     ;
409
410 statement
411     : nonBlockStatement
412     | block
413     ;
414
415 nonBlockStatement
416     :   ^(ASSERT expression expression?)
417     |   ^(IF parenthesizedExpression block block?)
418     |   ^(FOR forInit? FOR_EXPR expression? FOR_UPDATE expression* block)
419     |   ^(FOR_EACH localModifierList? type IDENT expression block) 
420     |   ^(WHILE parenthesizedExpression block)
421     |   ^(DO block parenthesizedExpression)
422     |   ^(SWITCH parenthesizedExpression switchCaseLabel*)
423     |   ^(RETURN expression?)
424     |   ^(THROW expression)
425     |   ^(BREAK IDENT?) {
426             if ($IDENT != null) {
427                 translator.error(this, "Labeled break not supported yet, ignoring.", $IDENT);
428             }
429         }
430     |   ^(CONTINUE IDENT?) {
431             if ($IDENT != null) {
432                 translator.error(this, "Labeled continue not supported yet, ignoring.", $IDENT);
433             }
434         }
435     |   ^(LABELED_STATEMENT IDENT statement)
436     |   expression
437     |   ^('delete' qualifiedIdentifier)
438     |   ^(EMBED STRING_LITERAL EMBED_BLOCK)
439     |   ';' // Empty statement.
440     ;
441         
442 switchCaseLabel
443     :   ^(CASE expression blockStatement*)
444     |   ^(DEFAULT blockStatement*)
445     ;
446     
447 forInit
448     :   localVariableDeclaration 
449     |   expression+
450     ;
451     
452 // EXPRESSIONS
453
454 parenthesizedExpression
455     :   ^(PAREN_EXPR expression)
456     ;
457     
458 expression
459     :   ^(EXPR expr)
460     ;
461
462 expr
463     :   ^(ASSIGNMENT expr expr)
464     |   ^(PLUS_EQUALS expr expr)
465     |   ^(MINUS_EQUALS expr expr)
466     |   ^(TIMES_EQUALS expr expr)
467     |   ^(DIVIDE_EQUALS expr expr)
468     |   ^(AND_EQUALS expr expr)
469     |   ^(OR_EQUALS expr expr)
470     |   ^(POWER_EQUALS expr expr)
471     |   ^(MOD_EQUALS expr expr)
472     |   ^('>>>=' expr expr)
473     |   ^('>>=' expr expr)
474     |   ^('<<=' expr expr)
475     |   ^('?' expr expr expr)
476     |   ^(OR expr expr)
477     |   ^(AND expr expr)
478     |   ^(BITWISE_OR expr expr)
479     |   ^(POWER expr expr)
480     |   ^(BITWISE_AND expr expr)
481     |   ^(EQUALS expr expr)
482     |   ^(NOT_EQUALS expr expr)
483     |   ^(INSTANCEOF expr type)
484     |   ^(LTE expr expr)
485     |   ^(GTE expr expr)
486     |   ^('>>>' expr expr)
487     |   ^('>>' expr expr)
488     |   ^(GT expr expr)
489     |   ^('<<' expr expr)
490     |   ^(LT expr expr)
491     |   ^(PLUS expr expr)
492     |   ^(MINUS expr expr)
493     |   ^(TIMES expr expr)
494     |   ^(DIVIDE expr expr)
495     |   ^(MOD expr expr)
496     |   ^(UNARY_PLUS expr)
497     |   ^(UNARY_MINUS expr)
498     |   ^(PRE_INC expr)
499     |   ^(PRE_DEC expr)
500     |   ^(POST_INC expr)
501     |   ^(POST_DEC expr)
502     |   ^(TILDE expr)
503     |   ^(NOT expr)
504     |   ^(CAST_EXPR type expr)
505     |   primaryExpression
506     ;
507     
508 primaryExpression
509     :   ^(DOT primaryExpression
510                 (   IDENT
511                 |   THIS
512                 |   SUPER
513                 )
514         )
515     |   ^(ARROW primaryExpression
516                 (   IDENT
517                 |   THIS
518                 |   SUPER
519                 )
520         )
521     |   parenthesizedExpression
522     |   IDENT
523     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
524     |   ^(ENTRY_METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
525     |   explicitConstructorCall
526     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
527     |   literal
528     |   newExpression
529     |   THIS
530     |   arrayTypeDeclarator
531     |   SUPER
532     ;
533     
534 explicitConstructorCall
535     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
536     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
537     ;
538
539 arrayTypeDeclarator
540     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
541     ;
542
543 newExpression
544     :   ^(  STATIC_ARRAY_CREATOR
545             (   primitiveType newArrayConstruction
546             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
547             )
548         )
549     |   ^(NEW type arguments)
550     ;
551
552 newArrayConstruction
553     :   arrayDeclaratorList arrayInitializer
554     |   expression+ arrayDeclaratorList?
555     ;
556
557 arguments
558     :   ^(ARGUMENT_LIST expression*)
559     ;
560
561 literal 
562     :   HEX_LITERAL
563     |   OCTAL_LITERAL
564     |   DECIMAL_LITERAL
565     |   FLOATING_POINT_LITERAL
566     |   CHARACTER_LITERAL
567     |   STRING_LITERAL          
568     |   TRUE
569     |   FALSE
570     |   NULL 
571     ;
572