Template declaration, semantics still need some work
[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* ^('class' i2=IDENT (^('extends' type))? (^('implements' type+))? classScopeDeclaration*))
123         {
124             // JL: Need to fill the templateArgs in ClassSymbol
125             Scope outerScope = $ScopeStack[-1]::current;
126             $sym = new ClassSymbol(symtab, $i2.text, null, outerScope);
127             outerScope.define($sym.name, $sym);
128             currentClass = $sym;
129             $sym.definition = $typeDeclaration.start;
130             $sym.definitionTokenStream = input.getTokenStream();
131             $i2.symbol = $sym;
132             $ScopeStack::current = $sym;
133             importPackages($sym, $imports);
134         }
135     |   ^('interface' IDENT (^('extends' type+))?  interfaceScopeDeclaration*)
136     |   ^('enum' IDENT (^('implements' type+))? enumConstant+ classScopeDeclaration*)
137     |   ^(chareType IDENT (^('extends' type))? (^('implements' type+))? classScopeDeclaration*)
138     |   ^('chare_array' ARRAY_DIMENSION IDENT (^('extends' type))? (^('implements' type+))? classScopeDeclaration*)
139     ;
140
141 chareType
142     :   'chare'
143     |   'group'
144     |   'nodegroup'
145     ;
146
147 enumConstant
148     :   ^(IDENT arguments?)
149     ;
150     
151 classScopeDeclaration
152     :   ^(FUNCTION_METHOD_DECL m=modifierList? g=genericTypeParameterList? 
153             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
154             b=block?)
155     |   ^(VOID_METHOD_DECL m=modifierList? g=genericTypeParameterList? IDENT 
156             f=formalParameterList b=block?)
157     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
158     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
159     |   ^(CONSTRUCTOR_DECL m=modifierList? g=genericTypeParameterList? IDENT f=formalParameterList 
160             b=block)
161     ;
162     
163 interfaceScopeDeclaration
164     :   ^(FUNCTION_METHOD_DECL modifierList? genericTypeParameterList? 
165             type IDENT formalParameterList arrayDeclaratorList?)
166     |   ^(VOID_METHOD_DECL modifierList? genericTypeParameterList? IDENT formalParameterList)
167         // Interface constant declarations have been switched to variable
168         // declarations by Charj.g; the parser has already checked that
169         // there's an obligatory initializer.
170     |   ^(PRIMITIVE_VAR_DECLARATION modifierList? simpleType variableDeclaratorList)
171     |   ^(OBJECT_VAR_DECLARATION modifierList? objectType variableDeclaratorList)
172     ;
173
174 variableDeclaratorList
175     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
176     ;
177
178 variableDeclarator
179     :   ^(VAR_DECLARATOR variableDeclaratorId variableInitializer?)
180     ;
181     
182 variableDeclaratorId
183     :   ^(IDENT arrayDeclaratorList?)
184     ;
185
186 variableInitializer
187     :   arrayInitializer
188     |   expression
189     ;
190
191 arrayDeclaratorList
192     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
193     ;
194     
195 arrayInitializer
196     :   ^(ARRAY_INITIALIZER variableInitializer*)
197     ;
198
199 genericTypeParameterList
200     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
201     ;
202
203 genericTypeParameter
204     :   ^(IDENT bound?)
205     ;
206         
207 bound
208     :   ^(EXTENDS_BOUND_LIST type+)
209     ;
210
211 modifierList
212     :   ^(MODIFIER_LIST modifier+)
213     ;
214
215 modifier
216     :   'public'
217     |   'protected'
218     |   'private'
219     |   'entry'
220     |   'abstract'
221     |   'native'
222     |   localModifier
223     ;
224
225 localModifierList
226     :   ^(LOCAL_MODIFIER_LIST localModifier+)
227     ;
228
229 localModifier
230     :   'final'
231     |   'static'
232     |   'volatile'
233     ;
234
235 type
236     :   simpleType
237     |   objectType 
238     ;
239
240 simpleType
241     :   ^(TYPE primitiveType arrayDeclaratorList?)
242     ;
243     
244 objectType
245     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
246     ;
247
248 qualifiedTypeIdent
249     :   ^(QUALIFIED_TYPE_IDENT typeIdent+) 
250     ;
251
252 typeIdent
253     :   ^(IDENT genericTypeArgumentList?)
254     ;
255
256 primitiveType
257     :   'boolean'     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
258     |   'char'        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
259     |   'byte'        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
260     |   'short'       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
261     |   'int'         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
262     |   'long'        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
263     |   'float'       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
264     |   'double'      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
265     ;
266
267 genericTypeArgumentList
268     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
269     ;
270     
271 genericTypeArgument
272     :   type
273     |   '?'
274     ;
275
276 formalParameterList
277     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
278     ;
279     
280 formalParameterStandardDecl
281     :   ^(FORMAL_PARAM_STD_DECL localModifierList? type variableDeclaratorId)
282     ;
283     
284 formalParameterVarargDecl
285     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList? type variableDeclaratorId)
286     ;
287     
288 // FIXME: is this rule right? Verify that this is ok, I expected something like:
289 // IDENT (^('.' qualifiedIdentifier IDENT))*
290 qualifiedIdentifier
291     :   IDENT
292     |   ^('.' qualifiedIdentifier IDENT)
293     ;
294     
295 block
296     :   ^(BLOCK (blockStatement)*)
297     ;
298     
299 blockStatement
300     :   localVariableDeclaration
301     |   statement
302     ;
303     
304 localVariableDeclaration
305     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList? simpleType variableDeclaratorList)
306     |   ^(OBJECT_VAR_DECLARATION localModifierList? objectType variableDeclaratorList)
307     ;
308
309 statement
310     :   block
311     |   ^('assert' expression expression?)
312     |   ^('if' parenthesizedExpression statement statement?)
313     |   ^('for' forInit expression? expression* statement)
314     |   ^(FOR_EACH localModifierList? type IDENT expression statement) 
315     |   ^('while' parenthesizedExpression statement)
316     |   ^('do' statement parenthesizedExpression)
317     |   ^('switch' parenthesizedExpression switchCaseLabel*)
318     |   ^('return' expression?)
319     |   ^('throw' expression)
320     |   ^('break' IDENT?) {
321             if ($IDENT != null) {
322                 translator.error(this, "Labeled break not supported yet, ignoring.", $IDENT);
323             }
324         }
325     |   ^('continue' IDENT?) {
326             if ($IDENT != null) {
327                 translator.error(this, "Labeled continue not supported yet, ignoring.", $IDENT);
328             }
329         }
330     |   ^(LABELED_STATEMENT IDENT statement)
331     |   expression
332     |   ^('embed' STRING_LITERAL EMBED_BLOCK)
333     |   ';' // Empty statement.
334     ;
335         
336 switchCaseLabel
337     :   ^('case' expression blockStatement*)
338     |   ^('default' blockStatement*)
339     ;
340     
341 forInit
342     :   localVariableDeclaration 
343     |   expression+
344     ;
345     
346 // EXPRESSIONS
347
348 parenthesizedExpression
349     :   ^(PAREN_EXPR expression)
350     ;
351     
352 expression
353     :   ^(EXPR expr)
354     ;
355
356 expr
357     :   ^('=' expr expr)
358     |   ^('+=' expr expr)
359     |   ^('-=' expr expr)
360     |   ^('*=' expr expr)
361     |   ^('/=' expr expr)
362     |   ^('&=' expr expr)
363     |   ^('|=' expr expr)
364     |   ^('^=' expr expr)
365     |   ^('%=' expr expr)
366     |   ^('>>>=' expr expr)
367     |   ^('>>=' expr expr)
368     |   ^('<<=' expr expr)
369     |   ^('?' expr expr expr)
370     |   ^('||' expr expr)
371     |   ^('&&' expr expr)
372     |   ^('|' expr expr)
373     |   ^('^' expr expr)
374     |   ^('&' expr expr)
375     |   ^('==' expr expr)
376     |   ^('!=' expr expr)
377     |   ^('instanceof' expr type)
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)
388     |   ^('/' expr expr)
389     |   ^('%' expr expr)
390     |   ^(UNARY_PLUS expr)
391     |   ^(UNARY_MINUS expr)
392     |   ^(PRE_INC expr)
393     |   ^(PRE_DEC expr)
394     |   ^(POST_INC expr)
395     |   ^(POST_DEC expr)
396     |   ^('~' expr)
397     |   ^('!' expr)
398     |   ^(CAST_EXPR type expr)
399     |   primaryExpression
400     ;
401     
402 primaryExpression
403     :   ^(  '.' primaryExpression
404                 (   IDENT
405                 |   'this'
406                 |   'super'
407                 )
408         )
409     |   parenthesizedExpression
410     |   IDENT
411     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
412     |   explicitConstructorCall
413     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
414     |   literal
415     |   newExpression
416     |   'this'
417     |   arrayTypeDeclarator
418     |   'super'
419     ;
420     
421 explicitConstructorCall
422     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
423     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
424     ;
425
426 arrayTypeDeclarator
427     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
428     ;
429
430 newExpression
431     :   ^(  STATIC_ARRAY_CREATOR
432             (   primitiveType newArrayConstruction
433             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
434             )
435         )
436     ;
437
438 newArrayConstruction
439     :   arrayDeclaratorList arrayInitializer
440     |   expression+ arrayDeclaratorList?
441     ;
442
443 arguments
444     :   ^(ARGUMENT_LIST expression*)
445     ;
446
447 literal 
448     :   HEX_LITERAL
449     |   OCTAL_LITERAL
450     |   DECIMAL_LITERAL
451     |   FLOATING_POINT_LITERAL
452     |   CHARACTER_LITERAL
453     |   STRING_LITERAL          
454     |   'true'
455     |   'false'
456     |   'null'
457     ;
458