50810c78ef4962a155aaaf814020cc25103fa28d
[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' qualifiedIdentifier)  {
99             String packageName = $qualifiedIdentifier.text;
100             PackageScope ps = symtab.resolvePackage(packageName);
101             if (ps == null) {
102                 ps = symtab.definePackage(packageName);
103                 symtab.addScope(ps);
104             }
105             currentPackage = ps;
106             $ScopeStack::current = ps;
107             $qualifiedIdentifier.start.symbol = ps;
108         }
109     ;
110     
111 importDeclarations returns [List<CharjAST> packageNames]
112 @init {
113         packageNames = new ArrayList<CharjAST>();
114 }
115     :   (^('import' qualifiedIdentifier './*'?)
116                 { packageNames.add($qualifiedIdentifier.start); })*
117     ;
118
119
120 typeDeclaration[List<CharjAST> imports] returns [ClassSymbol sym]
121 scope ScopeStack; // top-level type scope
122     :   ^('template' i1=IDENT* typeDeclaration[$imports])
123         {
124             // JL: Need to fill the templateArgs in ClassSymbol, and push this down
125             // to the class subtree
126         }
127     |   ^('class' i2=IDENT (^('extends' type))? (^('implements' type+))? 
128         {
129             Scope outerScope = $ScopeStack[-1]::current;
130             $sym = new ClassSymbol(symtab, $i2.text, null, outerScope);
131             outerScope.define($sym.name, $sym);
132             currentClass = $sym;
133             $sym.definition = $typeDeclaration.start;
134             $sym.definitionTokenStream = input.getTokenStream();
135             $i2.symbol = $sym;
136             $ScopeStack::current = $sym;
137             importPackages($sym, $imports);
138         }
139             classScopeDeclaration*)
140     |   ^('interface' IDENT (^('extends' type+))?  interfaceScopeDeclaration*)
141     |   ^('enum' IDENT (^('implements' type+))? enumConstant+ classScopeDeclaration*)
142     |   ^(chareType IDENT (^('extends' type))? (^('implements' type+))? classScopeDeclaration*)
143     |   ^('chare_array' ARRAY_DIMENSION IDENT (^('extends' type))? (^('implements' type+))? classScopeDeclaration*)
144     ;
145
146 chareType
147     :   'chare'
148     |   'group'
149     |   'nodegroup'
150     ;
151
152 enumConstant
153     :   ^(IDENT arguments?)
154     ;
155     
156 classScopeDeclaration
157     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
158             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
159             b=block?)
160     |   ^(VOID_METHOD_DECL m=modifierList? g=genericTypeParameterList? IDENT 
161             f=formalParameterList b=block?)
162     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList[false])
163     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList[false])
164     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList 
165             b=block)
166         {
167                 if (currentClass != null) {
168                 currentClass.constructor = $classScopeDeclaration.start;
169             } 
170         }
171     ;
172     
173 interfaceScopeDeclaration
174     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? 
175             type IDENT formalParameterList arrayDeclaratorList?)
176     |   ^(VOID_METHOD_DECL modifierList? genericTypeParameterList? IDENT formalParameterList)
177         // Interface constant declarations have been switched to variable
178         // declarations by Charj.g; the parser has already checked that
179         // there's an obligatory initializer.
180     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList[false])
181     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList[false])
182     ;
183
184 variableDeclaratorList[boolean localdef]
185     :   ^(VAR_DECLARATOR_LIST variableDeclarator[localdef]+)
186     ;
187
188 variableDeclarator[boolean localdef]
189     :   ^(VAR_DECLARATOR variableDeclaratorId[localdef] variableInitializer?)
190     ;
191     
192 variableDeclaratorId[boolean localdef]
193     :   ^(IDENT domainExpression? 
194         { 
195             if (currentClass != null && !localdef) {
196                 currentClass.initializers.add($variableDeclaratorId.start);
197             }
198         } )
199     ;
200
201 rangeItem
202     :   DECIMAL_LITERAL
203     |   IDENT
204     ;
205
206 rangeExpression
207     :   ^(RANGE_EXPRESSION rangeItem)
208     |   ^(RANGE_EXPRESSION rangeItem rangeItem)
209     |   ^(RANGE_EXPRESSION rangeItem rangeItem rangeItem)
210     ;
211
212 rangeList
213     :   rangeExpression*
214     ;
215
216 domainExpression
217     :   ^(DOMAIN_EXPRESSION rangeList)
218     ;
219
220 variableInitializer
221     :   arrayInitializer
222     |   newExpression
223     ;
224
225 arrayDeclaratorList
226     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
227     ;
228     
229 arrayInitializer
230     :   ^(ARRAY_INITIALIZER variableInitializer*)
231     ;
232
233 genericTypeParameterList
234     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
235     ;
236
237 genericTypeParameter
238     :   ^(IDENT bound?)
239     ;
240         
241 bound
242     :   ^(EXTENDS_BOUND_LIST type+)
243     ;
244
245 modifierList
246     :   ^(MODIFIER_LIST modifier+)
247     ;
248
249 modifier
250     :   'public'
251     |   'protected'
252     |   'private'
253     |   'entry'
254     |   'abstract'
255     |   'native'
256     |   localModifier
257     ;
258
259 localModifierList
260     :   ^(LOCAL_MODIFIER_LIST localModifier+)
261     ;
262
263 localModifier
264     :   'final'
265     |   'static'
266     |   'volatile'
267     ;
268
269 type
270     :   simpleType
271     |   objectType 
272     ;
273
274 simpleType
275     :   ^(TYPE primitiveType domainExpression?)
276     ;
277     
278 objectType
279     :   ^(TYPE qualifiedTypeIdent domainExpression?)
280     ;
281
282 qualifiedTypeIdent
283     :   ^(QUALIFIED_TYPE_IDENT typeIdent+) 
284     ;
285
286 typeIdent
287     :   ^(IDENT templateInstantiation?)
288     ;
289
290 primitiveType
291     :   'boolean'     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
292     |   'char'        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
293     |   'byte'        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
294     |   'short'       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
295     |   'int'         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
296     |   'long'        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
297     |   'float'       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
298     |   'double'      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
299     ;
300
301 genericTypeArgumentList
302     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
303     ;
304
305 templateArgList
306     :   genericTypeArgument+
307     ;
308
309 templateInstantiation
310     :   ^(TEMPLATE_INST templateArgList)
311     |   ^(TEMPLATE_INST templateInstantiation)
312     ;
313     
314 genericTypeArgument
315     :   type
316     |   '?'
317     ;
318
319 formalParameterList
320     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
321     ;
322     
323 formalParameterStandardDecl
324     :   ^(FORMAL_PARAM_STD_DECL localModifierList? type variableDeclaratorId[false])
325     ;
326     
327 formalParameterVarargDecl
328     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId[false])
329     ;
330     
331 // FIXME: is this rule right? Verify that this is ok, I expected something like:
332 // IDENT (^('.' qualifiedIdentifier IDENT))*
333 qualifiedIdentifier
334     :   IDENT
335     |   ^('.' qualifiedIdentifier IDENT)
336     ;
337     
338 block
339     :   ^(BLOCK (blockStatement)*)
340     ;
341     
342 blockStatement
343     :   localVariableDeclaration
344     |   statement
345     ;
346     
347 localVariableDeclaration
348     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList[true])
349     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList[true])
350     ;
351
352 statement
353     :   block
354     |   ^('assert' expression expression?)
355     |   ^('if' parenthesizedExpression statement statement?)
356     |   ^('for' forInit expression? expression* statement)
357     |   ^(FOR_EACH localModifierList? type IDENT expression statement) 
358     |   ^('while' parenthesizedExpression statement)
359     |   ^('do' statement parenthesizedExpression)
360     |   ^('switch' parenthesizedExpression switchCaseLabel*)
361     |   ^('return' expression?)
362     |   ^('throw' expression)
363     |   ^('break' IDENT?) {
364             if ($IDENT != null) {
365                 translator.error(this, "Labeled break not supported yet, ignoring.", $IDENT);
366             }
367         }
368     |   ^('continue' IDENT?) {
369             if ($IDENT != null) {
370                 translator.error(this, "Labeled continue not supported yet, ignoring.", $IDENT);
371             }
372         }
373     |   ^(LABELED_STATEMENT IDENT statement)
374     |   expression
375     |   ^('embed' STRING_LITERAL EMBED_BLOCK)
376     |   ';' // Empty statement.
377     ;
378         
379 switchCaseLabel
380     :   ^('case' expression blockStatement*)
381     |   ^('default' blockStatement*)
382     ;
383     
384 forInit
385     :   localVariableDeclaration 
386     |   expression+
387     ;
388     
389 // EXPRESSIONS
390
391 parenthesizedExpression
392     :   ^(PAREN_EXPR expression)
393     ;
394
395 expression
396     :   ^(EXPR expr)
397     ;
398
399 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     |   ^('%=' expr expr)
409     |   ^('>>>=' expr expr)
410     |   ^('>>=' expr expr)
411     |   ^('<<=' expr expr)
412     |   ^('?' expr expr expr)
413     |   ^('||' expr expr)
414     |   ^('&&' expr expr)
415     |   ^('|' expr expr)
416     |   ^('^' expr expr)
417     |   ^('&' expr expr)
418     |   ^('==' expr expr)
419     |   ^('!=' expr expr)
420     |   ^('instanceof' expr type)
421     |   ^('<=' expr expr)
422     |   ^('>=' expr expr)
423     |   ^('>>>' expr expr)
424     |   ^('>>' expr expr)
425     |   ^('>' expr expr)
426     |   ^('<<' expr expr)
427     |   ^('<' expr expr)
428     |   ^('+' expr expr)
429     |   ^('-' expr expr)
430     |   ^('*' expr expr)
431     |   ^('/' expr expr)
432     |   ^('%' expr expr)
433     |   ^(UNARY_PLUS expr)
434     |   ^(UNARY_MINUS expr)
435     |   ^(PRE_INC expr)
436     |   ^(PRE_DEC expr)
437     |   ^(POST_INC expr)
438     |   ^(POST_DEC expr)
439     |   ^('~' expr)
440     |   ^('!' expr)
441     |   ^(CAST_EXPR type expr)
442     |   primaryExpression
443     ;
444     
445 primaryExpression
446     :   ^(  '.' primaryExpression
447                 (   IDENT
448                 |   'this'
449                 |   'super'
450                 )
451         )
452     |   parenthesizedExpression
453     |   IDENT
454     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
455     |   explicitConstructorCall
456     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
457     |   literal
458     |   newExpression
459     |   'this'
460     |   arrayTypeDeclarator
461     |   'super'
462     ;
463     
464 explicitConstructorCall
465     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
466     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
467     ;
468
469 arrayTypeDeclarator
470     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
471     ;
472
473 newExpression
474     :   ^(NEW_EXPRESSION arguments? domainExpression)
475         {
476             if (currentClass != null) {
477                 currentClass.initializers.add($newExpression.start);
478             }
479         }
480     ;
481
482 /*newExpression
483     :   ^(  STATIC_ARRAY_CREATOR
484             (   primitiveType newArrayConstruction
485             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
486             )
487         )
488     ;*/
489
490 newArrayConstruction
491     :   arrayDeclaratorList arrayInitializer
492     |   expression+ arrayDeclaratorList?
493     ;
494
495 arguments
496     :   ^(ARGUMENT_LIST expression*)
497     ;
498
499 literal 
500     :   HEX_LITERAL
501     |   OCTAL_LITERAL
502     |   DECIMAL_LITERAL
503     |   FLOATING_POINT_LITERAL
504     |   CHARACTER_LITERAL
505     |   STRING_LITERAL          
506     |   'true'
507     |   'false'
508     |   'null'
509     ;
510