6096d1e6ec5f58f355a5775dc84bf486e36e544c
[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
27     PackageScope currentPackage = null;
28     ClassSymbol currentClass = null;
29     MethodSymbol currentMethod = null;
30     LocalScope currentLocalScope = null;
31
32     Translator translator;
33
34     boolean m_messageCollectionEnabled = false;
35     private boolean m_hasErrors = false;
36     List<String> m_messages;
37
38     /**
39      *  Switches error message collection on or off.
40      *
41      *  The standard destination for parser error messages is 
42      *  <code>System.err</code>.
43      *  However, if <code>true</code> gets passed to this method this default
44      *  behaviour will be switched off and all error messages will be collected
45      *  instead of written to anywhere.
46      *
47      *  The default value is <code>false</code>.
48      *
49      *  @param newState  <code>true</code> if error messages should be collected.
50      */
51     public void enableErrorMessageCollection(boolean newState) {
52         m_messageCollectionEnabled = newState;
53         if (m_messages == null && m_messageCollectionEnabled) {
54             m_messages = new ArrayList<String>();
55         }
56     }
57     
58     /**
59      *  Collects an error message or passes the error message to <code>
60      *  super.emitErrorMessage(...)</code>.
61      *
62      *  The actual behaviour depends on whether collecting error messages
63      *  has been enabled or not.
64      *
65      *  @param message  The error message.
66      */
67      @Override
68     public void emitErrorMessage(String message) {
69         if (m_messageCollectionEnabled) {
70             m_messages.add(message);
71         } else {
72             super.emitErrorMessage(message);
73         }
74     }
75     
76     /**
77      *  Returns collected error messages.
78      *
79      *  @return  A list holding collected error messages or <code>null</code> if
80      *           collecting error messages hasn't been enabled. Of course, this
81      *           list may be empty if no error message has been emited.
82      */
83     public List<String> getMessages() {
84         return m_messages;
85     }
86     
87     /**
88      *  Tells if parsing a Charj source has caused any error messages.
89      *
90      *  @return  <code>true</code> if parsing a Charj source has caused at 
91      *           least one error message.
92      */
93     public boolean hasErrors() {
94         return m_hasErrors;
95     }
96
97     /**
98      *  Test a list of CharjAST nodes to see if any of them has the given token
99      *  type.
100      */
101     public boolean listContainsToken(List<CharjAST> list, int tokenType) {
102         for (CharjAST node : list) {
103             if (node.token.getType() == tokenType) {
104                 return true;
105             }
106         }
107         return false;
108     }
109
110     public void importPackages(ClassSymbol cs, List<CharjAST> imports) {
111         if (imports == null) {
112             return;
113         }
114
115         for (CharjAST pkg : imports) {
116             String pkgName = input.getTokenStream().toString(
117                     pkg.getTokenStartIndex(),
118                     pkg.getTokenStopIndex());
119             // find imported class and add to cs.imports
120             PackageScope p = cs.importPackage(pkgName);
121             if (p == null) {
122                 translator.error(
123                     this, 
124                     "package " + pkgName + " not found.",
125                     pkg);
126             }
127         }
128     }
129
130 }
131
132 // Starting point for parsing a Charj file.
133 charjSource[SymbolTable _symtab] returns [ClassSymbol cs]
134 scope ScopeStack; // default scope
135 @init {
136     symtab = _symtab;
137     $ScopeStack::current = symtab.getDefaultPkg();
138 }
139     // TODO: go back to allowing multiple type definitions per file, check that
140     // there is exactly one public type and return that one.
141     :   ^(CHARJ_SOURCE 
142         (packageDeclaration)? 
143         (importDeclarations) 
144         (typeDeclaration[$importDeclarations.packageNames]))
145         //(typeDeclaration)*)
146         { $cs = $typeDeclaration.sym; }
147     ;
148
149 // note: no new scope here--this replaces the default scope
150 packageDeclaration
151 @init { 
152     List<String> names = null; 
153 }
154     :   ^(PACKAGE qualifiedIdentifier)  {
155             String packageName = $qualifiedIdentifier.text;
156             PackageScope ps = symtab.resolvePackage(packageName);
157             if (ps == null) {
158                 ps = symtab.definePackage(packageName);
159                 symtab.addScope(ps);
160             }
161             currentPackage = ps;
162             $ScopeStack::current = ps;
163             $qualifiedIdentifier.start.symbol = ps;
164         }
165     ;
166     
167 importDeclarations returns [List<CharjAST> packageNames]
168 @init {
169         packageNames = new ArrayList<CharjAST>();
170 }
171     :   (^(IMPORT STATIC? qualifiedIdentifier DOTSTAR?)
172                 { packageNames.add($qualifiedIdentifier.start); })*
173     ;
174
175
176 typeDeclaration[List<CharjAST> imports] returns [ClassSymbol sym]
177 scope ScopeStack; // top-level type scope
178     :   ^(CLASS m=modifierList IDENT g=genericTypeParameterList? 
179                 e=classExtendsClause? i=implementsClause? c=classTopLevelScope) 
180         {
181             Scope outerScope = $ScopeStack[-1]::current;
182             $sym = new ClassSymbol(symtab, $IDENT.text, null, outerScope);
183             outerScope.define($sym.name, $sym);
184             currentClass = $sym;
185             $sym.definition = $typeDeclaration.start;
186             $sym.definitionTokenStream = input.getTokenStream();
187             $IDENT.symbol = $sym;
188             $ScopeStack::current = $sym;
189                         importPackages($sym, $imports);
190         }
191     |   ^(INTERFACE modifierList IDENT genericTypeParameterList? 
192                 interfaceExtendsClause? interfaceTopLevelScope)
193     |   ^(ENUM modifierList IDENT implementsClause? enumTopLevelScope)
194     ;
195
196
197 classExtendsClause
198     :   ^(EXTENDS_CLAUSE t=type) 
199     ;   
200
201 interfaceExtendsClause 
202     :   ^(EXTENDS_CLAUSE (type)+) 
203     ;   
204     
205 implementsClause
206     :   ^(IMPLEMENTS_CLAUSE type+)
207     ;
208         
209 genericTypeParameterList
210     :   ^(GENERIC_TYPE_PARAM_LIST genericTypeParameter+)
211     ;
212
213 genericTypeParameter
214     :   ^(IDENT bound?)
215     ;
216         
217 bound
218     :   ^(EXTENDS_BOUND_LIST type+)
219     ;
220
221 enumTopLevelScope
222     :   ^(ENUM_TOP_LEVEL_SCOPE enumConstant+ classTopLevelScope?)
223     ;
224     
225 enumConstant
226     :   ^(IDENT arguments? classTopLevelScope?)
227     ;
228     
229     
230 classTopLevelScope
231     :   ^(CLASS_TOP_LEVEL_SCOPE (classScopeDeclarations)*) 
232     ;
233     
234 classScopeDeclarations
235     :   ^(CLASS_INSTANCE_INITIALIZER block)
236     |   ^(CLASS_STATIC_INITIALIZER block)
237     |   ^(FUNCTION_METHOD_DECL m=modifierList g=genericTypeParameterList? 
238             ty=type IDENT f=formalParameterList a=arrayDeclaratorList? 
239             tc=throwsClause? b=block?)
240     |   ^(VOID_METHOD_DECL m=modifierList g=genericTypeParameterList? IDENT 
241             f=formalParameterList t=throwsClause? b=block?)
242     |   ^(PRIMITIVE_VAR_DECLARATION modifierList simpleType variableDeclaratorList)
243     |   ^(OBJECT_VAR_DECLARATION modifierList objectType variableDeclaratorList)
244     |   ^(CONSTRUCTOR_DECL m=modifierList g=genericTypeParameterList? IDENT f=formalParameterList 
245             t=throwsClause? b=block)
246     |   d=typeDeclaration[null]
247     ;
248     
249 interfaceTopLevelScope
250     :   ^(INTERFACE_TOP_LEVEL_SCOPE interfaceScopeDeclarations*)
251     ;
252     
253 interfaceScopeDeclarations
254     :   ^(FUNCTION_METHOD_DECL modifierList genericTypeParameterList? 
255             type IDENT formalParameterList arrayDeclaratorList? throwsClause?)
256     |   ^(VOID_METHOD_DECL modifierList genericTypeParameterList? IDENT formalParameterList throwsClause?)
257         // Interface constant declarations have been switched to variable
258         // declarations by Charj.g; the parser has already checked that
259         // there's an obligatory initializer.
260     |   ^(PRIMITIVE_VAR_DECLARATION modifierList simpleType variableDeclaratorList)
261     |   ^(OBJECT_VAR_DECLARATION modifierList objectType variableDeclaratorList)
262     |   typeDeclaration[null]
263     ;
264
265 variableDeclaratorList
266     :   ^(VAR_DECLARATOR_LIST variableDeclarator+)
267     ;
268
269 variableDeclarator
270     :   ^(VAR_DECLARATOR variableDeclaratorId variableInitializer?)
271     ;
272     
273 variableDeclaratorId
274     :   ^(IDENT arrayDeclaratorList?)
275     ;
276
277 variableInitializer
278     :   arrayInitializer
279     |   expression
280     ;
281
282 arrayDeclarator
283     :   LBRACK RBRACK
284     ;
285
286 arrayDeclaratorList
287     :   ^(ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR*)  
288     ;
289     
290 arrayInitializer
291     :   ^(ARRAY_INITIALIZER variableInitializer*)
292     ;
293
294 throwsClause
295     :   ^(THROWS_CLAUSE qualifiedIdentifier+)
296     ;
297
298 modifierList
299     :   ^(MODIFIER_LIST (modifier)*)
300     ;
301
302 modifier
303     :   PUBLIC
304     |   PROTECTED
305     |   PRIVATE
306     |   ENTRY
307     |   STATIC
308     |   ABSTRACT
309     |   NATIVE
310     |   SYNCHRONIZED
311     |   TRANSIENT
312     |   VOLATILE
313     |   localModifier
314     ;
315
316 localModifierList
317     :   ^(LOCAL_MODIFIER_LIST localModifier*)
318     ;
319
320 localModifier
321     :   FINAL
322     ;
323
324 type
325     :   simpleType
326     |   objectType 
327     ;
328
329 simpleType
330     :   ^(TYPE primitiveType arrayDeclaratorList?)
331     ;
332     
333 objectType
334     :   ^(TYPE qualifiedTypeIdent arrayDeclaratorList?)
335     ;
336
337 qualifiedTypeIdent
338     :   ^(QUALIFIED_TYPE_IDENT typeIdent+) 
339     ;
340
341 typeIdent
342     :   ^(IDENT genericTypeArgumentList?)
343     ;
344
345 primitiveType
346     :   BOOLEAN     { $start.symbol = new Symbol(symtab, "bool_primitive", symtab.resolveBuiltinType("bool")); }
347     |   CHAR        { $start.symbol = new Symbol(symtab, "char_primitive", symtab.resolveBuiltinType("char")); }
348     |   BYTE        { $start.symbol = new Symbol(symtab, "byte_primitive", symtab.resolveBuiltinType("char")); }
349     |   SHORT       { $start.symbol = new Symbol(symtab, "short_primitive", symtab.resolveBuiltinType("short")); }
350     |   INT         { $start.symbol = new Symbol(symtab, "int_primitive", symtab.resolveBuiltinType("int")); }
351     |   LONG        { $start.symbol = new Symbol(symtab, "long_primitive", symtab.resolveBuiltinType("long")); }
352     |   FLOAT       { $start.symbol = new Symbol(symtab, "float_primitive", symtab.resolveBuiltinType("float")); }
353     |   DOUBLE      { $start.symbol = new Symbol(symtab, "double_primitive", symtab.resolveBuiltinType("double")); }
354     ;
355
356 genericTypeArgumentList
357     :   ^(GENERIC_TYPE_ARG_LIST genericTypeArgument+)
358     ;
359     
360 genericTypeArgument
361     :   type
362     |   ^(QUESTION genericWildcardBoundType?)
363     ;
364
365 genericWildcardBoundType                                                                                                                      
366     :   ^(EXTENDS type)
367     |   ^(SUPER type)
368     ;
369
370 formalParameterList
371     :   ^(FORMAL_PARAM_LIST formalParameterStandardDecl* formalParameterVarargDecl?) 
372     ;
373     
374 formalParameterStandardDecl
375     :   ^(FORMAL_PARAM_STD_DECL localModifierList type variableDeclaratorId)
376     ;
377     
378 formalParameterVarargDecl
379     :   ^(FORMAL_PARAM_VARARG_DECL localModifierList type variableDeclaratorId)
380     ;
381     
382 qualifiedIdentifier
383     :   IDENT
384     |   ^(DOT qualifiedIdentifier IDENT)
385     ;
386     
387 block
388     :   ^(BLOCK_SCOPE (blockStatement)*)
389     ;
390     
391 blockStatement
392     :   localVariableDeclaration
393     |   typeDeclaration[null]
394     |   statement
395     ;
396     
397 localVariableDeclaration
398     :   ^(PRIMITIVE_VAR_DECLARATION localModifierList simpleType variableDeclaratorList)
399     |   ^(OBJECT_VAR_DECLARATION localModifierList objectType variableDeclaratorList)
400     ;
401
402
403 statement
404     :   block
405     |   ^(ASSERT expression expression?)
406     |   ^(IF parenthesizedExpression statement statement?)
407     |   ^(FOR forInit forCondition forUpdater statement)
408     |   ^(FOR_EACH localModifierList type IDENT expression statement) 
409     |   ^(WHILE parenthesizedExpression statement)
410     |   ^(DO statement parenthesizedExpression)
411     |   ^(TRY block catches? block?)  // The second optional block is the optional finally block.
412     |   ^(SWITCH parenthesizedExpression switchBlockLabels)
413     |   ^(SYNCHRONIZED parenthesizedExpression block)
414     |   ^(RETURN expression?)
415     |   ^(THROW expression)
416     |   ^(BREAK IDENT?)
417     |   ^(CONTINUE IDENT?)
418     |   ^(LABELED_STATEMENT IDENT statement)
419     |   expression
420     |   ^(EMBED STRING_LITERAL EMBED_BLOCK)
421     |   SEMI // Empty statement.
422     ;
423         
424 catches
425     :   ^(CATCH_CLAUSE_LIST catchClause+)
426     ;
427     
428 catchClause
429     :   ^(CATCH formalParameterStandardDecl block)
430     ;
431
432 switchBlockLabels
433     :   ^(SWITCH_BLOCK_LABEL_LIST switchCaseLabel* switchDefaultLabel? switchCaseLabel*)
434     ;
435         
436 switchCaseLabel
437     :   ^(CASE expression blockStatement*)
438     ;
439     
440 switchDefaultLabel
441     :   ^(DEFAULT blockStatement*)
442     ;
443     
444 forInit
445     :   ^(FOR_INIT (localVariableDeclaration | expression*)?)
446     ;
447     
448 forCondition
449     :   ^(FOR_CONDITION expression?)
450     ;
451     
452 forUpdater
453     :   ^(FOR_UPDATE expression*)
454     ;
455     
456 // EXPRESSIONS
457
458 parenthesizedExpression
459     :   ^(PARENTESIZED_EXPR expression)
460     ;
461     
462 expression
463     :   ^(EXPR expr)
464     ;
465
466 expr
467     :   ^(ASSIGN expr expr)
468     |   ^(PLUS_ASSIGN expr expr)
469     |   ^(MINUS_ASSIGN expr expr)
470     |   ^(STAR_ASSIGN expr expr)
471     |   ^(DIV_ASSIGN expr expr)
472     |   ^(AND_ASSIGN expr expr)
473     |   ^(OR_ASSIGN expr expr)
474     |   ^(XOR_ASSIGN expr expr)
475     |   ^(MOD_ASSIGN expr expr)
476     |   ^(BIT_SHIFT_RIGHT_ASSIGN expr expr)
477     |   ^(SHIFT_RIGHT_ASSIGN expr expr)
478     |   ^(SHIFT_LEFT_ASSIGN expr expr)
479     |   ^(QUESTION expr expr expr)
480     |   ^(LOGICAL_OR expr expr)
481     |   ^(LOGICAL_AND expr expr)
482     |   ^(OR expr expr)
483     |   ^(XOR expr expr)
484     |   ^(AND expr expr)
485     |   ^(EQUAL expr expr)
486     |   ^(NOT_EQUAL expr expr)
487     |   ^(INSTANCEOF expr type)
488     |   ^(LESS_OR_EQUAL expr expr)
489     |   ^(GREATER_OR_EQUAL expr expr)
490     |   ^(BIT_SHIFT_RIGHT expr expr)
491     |   ^(SHIFT_RIGHT expr expr)
492     |   ^(GREATER_THAN expr expr)
493     |   ^(SHIFT_LEFT expr expr)
494     |   ^(LESS_THAN expr expr)
495     |   ^(PLUS expr expr)
496     |   ^(MINUS expr expr)
497     |   ^(STAR expr expr)
498     |   ^(DIV expr expr)
499     |   ^(MOD expr expr)
500     |   ^(UNARY_PLUS expr)
501     |   ^(UNARY_MINUS expr)
502     |   ^(PRE_INC expr)
503     |   ^(PRE_DEC expr)
504     |   ^(POST_INC expr)
505     |   ^(POST_DEC expr)
506     |   ^(NOT expr)
507     |   ^(LOGICAL_NOT expr)
508     |   ^(CAST_EXPR type expr)
509     |   primaryExpression
510     ;
511     
512 primaryExpression
513     :   ^(  DOT
514             (   primaryExpression
515                 (   IDENT
516                 |   THIS
517                 |   SUPER
518                 |   innerNewExpression
519                 |   CLASS
520                 )
521             |   primitiveType CLASS
522             |   VOID CLASS
523             )
524         )
525     |   parenthesizedExpression
526     |   IDENT
527     |   ^(METHOD_CALL primaryExpression genericTypeArgumentList? arguments)
528     |   explicitConstructorCall
529     |   ^(ARRAY_ELEMENT_ACCESS primaryExpression expression)
530     |   literal
531     |   newExpression
532     |   THIS
533     |   arrayTypeDeclarator
534     |   SUPER
535     ;
536     
537 explicitConstructorCall
538     :   ^(THIS_CONSTRUCTOR_CALL genericTypeArgumentList? arguments)
539     |   ^(SUPER_CONSTRUCTOR_CALL primaryExpression? genericTypeArgumentList? arguments)
540     ;
541
542 arrayTypeDeclarator
543     :   ^(ARRAY_DECLARATOR (arrayTypeDeclarator | qualifiedIdentifier | primitiveType))
544     ;
545
546 newExpression
547     :   ^(  STATIC_ARRAY_CREATOR
548             (   primitiveType newArrayConstruction
549             |   genericTypeArgumentList? qualifiedTypeIdent newArrayConstruction
550             )
551         )
552     |   ^(CLASS_CONSTRUCTOR_CALL genericTypeArgumentList? qualifiedTypeIdent arguments classTopLevelScope?)
553     ;
554
555 innerNewExpression // something like 'InnerType innerType = outer.new InnerType();'
556     :   ^(CLASS_CONSTRUCTOR_CALL genericTypeArgumentList? IDENT arguments classTopLevelScope?)
557     ;
558     
559 newArrayConstruction
560     :   arrayDeclaratorList arrayInitializer
561     |   expression+ arrayDeclaratorList?
562     ;
563
564 arguments
565     :   ^(ARGUMENT_LIST expression*)
566     ;
567
568 literal 
569     :   HEX_LITERAL
570     |   OCTAL_LITERAL
571     |   DECIMAL_LITERAL
572     |   FLOATING_POINT_LITERAL
573     |   CHARACTER_LITERAL
574     |   STRING_LITERAL          
575     |   TRUE
576     |   FALSE
577     |   NULL
578     ;