Charj : added support for exit and exitAll (exit and CkExit)
[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         {
201             ClassSymbol type = $objectType.type;
202             if (type != null && type.isChare) currentClass.addExtern(type.getName());
203         }
204     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList 
205             b=block)
206         {
207             if (astmod.isMigrationCtor($CONSTRUCTOR_DECL)) currentClass.migrationCtor = $CONSTRUCTOR_DECL;
208         }
209     ;
210
211 field [ClassSymbol type]
212     :   ^(VAR_DECLARATOR ^(IDENT arrayDeclaratorList?) variableInitializer?)
213     {
214             VariableSymbol sym = new VariableSymbol(symtab, $IDENT.text, $type);
215             sym.definition = $field.start;
216             sym.definitionTokenStream = input.getTokenStream();
217             $VAR_DECLARATOR.symbol = sym;
218             currentClass.define($IDENT.text, sym);
219     }
220     ;
221     
222 interfaceScopeDeclaration
223     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? 
224             type IDENT formalParameterList arrayDeclaratorList?)
225         // Interface constant declarations have been switched to variable
226         // declarations by Charj.g; the parser has already checked that
227         // there's an obligatory initializer.
228     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
229     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
230     ;
231
232 variableDeclaratorList
233     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
234     ;
235
236 variableDeclarator
237     :   ^(VAR_DECLARATOR ^(IDENT arrayDeclaratorList?) variableInitializer?)
238
239     ;
240     
241 variableDeclaratorId
242     :   ^(IDENT arrayDeclaratorList?)
243     ;
244
245 variableInitializer
246     :   arrayInitializer
247     |   expression
248     ;
249
250 arrayDeclaratorList
251     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
252     ;
253     
254 arrayInitializer
255     :   ^(ARRAY_INITIALIZER variableInitializer*)
256     ;
257
258 genericTypeParameterList
259     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
260     ;
261
262 genericTypeParameter
263     :   ^(IDENT bound?)
264     ;
265         
266 bound
267     :   ^(EXTENDS_BOUND_LIST type+)
268     ;
269
270 modifierList
271     :   ^(MODIFIER_LIST accessModifierList? localModifierList? charjModifierList? otherModifierList?)
272     ;
273
274 modifier
275     :   accessModifier
276     |   localModifier
277     |   charjModifier
278     |   otherModifier
279     ;
280
281 localModifierList
282     :   ^(LOCAL_MODIFIER_LIST localModifier+)
283     ;
284
285 accessModifierList
286     :   ^(ACCESS_MODIFIER_LIST accessModifier+)
287     ;
288
289 charjModifierList
290     :   ^(CHARJ_MODIFIER_LIST charjModifier+)
291     ;
292
293 otherModifierList
294     :   ^(OTHER_MODIFIER_LIST otherModifier+)
295     ;
296     
297 localModifier
298     :   FINAL
299     |   STATIC
300     |   VOLATILE
301     ;
302
303 accessModifier
304     :   PUBLIC
305     |   PROTECTED
306     |   PRIVATE
307     ;
308
309 charjModifier
310     :   ENTRY
311     ;
312
313 otherModifier
314     :   ABSTRACT
315     |   NATIVE
316     ;
317
318 type
319     :   simpleType
320     |   objectType
321     |   VOID
322     ;
323
324 simpleType returns [ClassSymbol type]
325     :   ^(SIMPLE_TYPE primitiveType arrayDeclaratorList?)
326         {
327             $type = symtab.resolveBuiltinType($primitiveType.text);
328         }
329     ;
330     
331 objectType returns [ClassSymbol type]
332     :   ^(OBJECT_TYPE qualifiedTypeIdent arrayDeclaratorList?)
333     |   ^(REFERENCE_TYPE qualifiedTypeIdent arrayDeclaratorList?)
334     |   ^(PROXY_TYPE qualifiedTypeIdent arrayDeclaratorList?)
335     |   ^(POINTER_TYPE qualifiedTypeIdent arrayDeclaratorList?)
336         {
337             $type = $qualifiedTypeIdent.type;
338         }
339     ;
340
341 qualifiedTypeIdent returns [ClassSymbol type]
342 @init {
343 String name = "";
344 }
345     :   ^(QUALIFIED_TYPE_IDENT (typeIdent {name += $typeIdent.name;})+) 
346         {
347             $type = null;
348             /*System.out.println("trying to resolve type " + name + " in type " + currentClass);*/
349             if (currentClass != null) $type = currentClass.resolveType(name);
350             /*System.out.println("got " + $type);*/
351             if ($type == null) $type = symtab.resolveBuiltinType(name);
352             $QUALIFIED_TYPE_IDENT.symbol = $type;
353         }
354     ;
355
356 typeIdent returns [String name]
357     :   ^(IDENT genericTypeArgumentList?)
358         { $name = $IDENT.text; }
359     ;
360
361 primitiveType
362     :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
363     |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
364     |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
365     |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
366     |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
367     |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
368     |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
369     |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
370     ;
371
372 genericTypeArgumentList
373     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
374     ;
375     
376 genericTypeArgument
377     :   type
378     |   '?'
379     ;
380
381 formalParameterList
382     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
383     ;
384     
385 formalParameterStandardDecl
386     :   ^(FORMAL_PARAM_STD_DECL localModifierList? type variableDeclaratorId)
387     ;
388     
389 formalParameterVarargDecl
390     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
391     ;
392     
393 // FIXME: is this rule right? Verify that this is ok, I expected something like:
394 // IDENT (^(DOT qualifiedIdentifier IDENT))*
395 qualifiedIdentifier
396     :   IDENT
397     |   ^(DOT qualifiedIdentifier IDENT)
398     ;
399     
400 block
401     :   ^(BLOCK (blockStatement)*)
402     ;
403     
404 blockStatement
405     :   localVariableDeclaration
406     |   statement
407     ;
408     
409 localVariableDeclaration
410     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
411     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
412         {
413             ClassSymbol type = $objectType.type;
414             /*System.out.println("looked up type " + type + " for declaration " + $objectType.text);*/
415             if (type != null && type.isChare && currentClass != null) currentClass.addExtern(type.getName());
416         }
417     ;
418
419 statement
420     : nonBlockStatement
421     | block
422     ;
423
424 nonBlockStatement
425     :   ^(ASSERT expression expression?)
426     |   ^(IF parenthesizedExpression block block?)
427     |   ^(FOR forInit? FOR_EXPR expression? FOR_UPDATE expression* block)
428     |   ^(FOR_EACH localModifierList? type IDENT expression block) 
429     |   ^(WHILE parenthesizedExpression block)
430     |   ^(DO block parenthesizedExpression)
431     |   ^(SWITCH parenthesizedExpression switchCaseLabel*)
432     |   ^(RETURN expression?)
433     |   ^(THROW expression)
434     |   ^(BREAK IDENT?) {
435             if ($IDENT != null) {
436                 translator.error(this, "Labeled break not supported yet, ignoring.", $IDENT);
437             }
438         }
439     |   ^(CONTINUE IDENT?) {
440             if ($IDENT != null) {
441                 translator.error(this, "Labeled continue not supported yet, ignoring.", $IDENT);
442             }
443         }
444     |   ^(LABELED_STATEMENT IDENT statement)
445     |   expression
446     |   ^('delete' qualifiedIdentifier)
447     |   ^(EMBED STRING_LITERAL EMBED_BLOCK)
448     |   ';' // Empty statement.
449     |   ^(PRINT expression*)
450     |   ^(PRINTLN expression*)
451     |   ^(EXIT expression?)
452     |   EXITALL
453     ;
454         
455 switchCaseLabel
456     :   ^(CASE expression blockStatement*)
457     |   ^(DEFAULT blockStatement*)
458     ;
459     
460 forInit
461     :   localVariableDeclaration 
462     |   expression+
463     ;
464     
465 // EXPRESSIONS
466
467 parenthesizedExpression
468     :   ^(PAREN_EXPR expression)
469     ;
470     
471 expression
472     :   ^(EXPR expr)
473     ;
474
475 expr
476     :   ^(ASSIGNMENT expr expr)
477     |   ^(PLUS_EQUALS expr expr)
478     |   ^(MINUS_EQUALS expr expr)
479     |   ^(TIMES_EQUALS expr expr)
480     |   ^(DIVIDE_EQUALS expr expr)
481     |   ^(AND_EQUALS expr expr)
482     |   ^(OR_EQUALS expr expr)
483     |   ^(POWER_EQUALS expr expr)
484     |   ^(MOD_EQUALS expr expr)
485     |   ^('>>>=' expr expr)
486     |   ^('>>=' expr expr)
487     |   ^('<<=' expr expr)
488     |   ^('?' expr expr expr)
489     |   ^(OR expr expr)
490     |   ^(AND expr expr)
491     |   ^(BITWISE_OR expr expr)
492     |   ^(POWER expr expr)
493     |   ^(BITWISE_AND expr expr)
494     |   ^(EQUALS expr expr)
495     |   ^(NOT_EQUALS expr expr)
496     |   ^(INSTANCEOF expr type)
497     |   ^(LTE expr expr)
498     |   ^(GTE expr expr)
499     |   ^('>>>' expr expr)
500     |   ^('>>' expr expr)
501     |   ^(GT expr expr)
502     |   ^('<<' expr expr)
503     |   ^(LT expr expr)
504     |   ^(PLUS expr expr)
505     |   ^(MINUS expr expr)
506     |   ^(TIMES expr expr)
507     |   ^(DIVIDE expr expr)
508     |   ^(MOD expr expr)
509     |   ^(UNARY_PLUS expr)
510     |   ^(UNARY_MINUS expr)
511     |   ^(PRE_INC expr)
512     |   ^(PRE_DEC expr)
513     |   ^(POST_INC expr)
514     |   ^(POST_DEC expr)
515     |   ^(TILDE expr)
516     |   ^(NOT expr)
517     |   ^(CAST_EXPR type expr)
518     |   primaryExpression
519     ;
520     
521 primaryExpression
522     :   ^(DOT primaryExpression
523                 (   IDENT
524                 |   THIS
525                 |   SUPER
526                 )
527         )
528     |   ^(ARROW primaryExpression
529                 (   IDENT
530                 |   THIS
531                 |   SUPER
532                 )
533         )
534     |   parenthesizedExpression
535     |   IDENT
536     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
537     |   ^(ENTRY_METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
538     |   explicitConstructorCall
539     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
540     |   literal
541     |   newExpression
542     |   THIS
543     |   arrayTypeDeclarator
544     |   SUPER
545     ;
546     
547 explicitConstructorCall
548     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
549     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
550     ;
551
552 arrayTypeDeclarator
553     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
554     ;
555
556 newExpression
557     :   ^(  STATIC_ARRAY_CREATOR
558             (   primitiveType newArrayConstruction
559             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
560             )
561         )
562     |   ^(NEW type arguments)
563     ;
564
565 newArrayConstruction
566     :   arrayDeclaratorList arrayInitializer
567     |   expression+ arrayDeclaratorList?
568     ;
569
570 arguments
571     :   ^(ARGUMENT_LIST expression*)
572     ;
573
574 literal 
575     :   HEX_LITERAL
576     |   OCTAL_LITERAL
577     |   DECIMAL_LITERAL
578     |   FLOATING_POINT_LITERAL
579     |   CHARACTER_LITERAL
580     |   STRING_LITERAL          
581     |   TRUE
582     |   FALSE
583     |   NULL 
584     ;
585