Update changes.
[castle.git] / Experiments / Rook / Castle.Rook / lang.g
blob2b59acf18c679bac71924d620b3dd245236c163c
1 header \r
2 {\r
3         // using CommonAST                                      = antlr.CommonAST; \r
4         using System.Text;\r
5         using System.Collections;\r
6         using Castle.Rook.AST;\r
7 }\r
8 options \r
9 {       \r
10         language = "CSharp";\r
11         namespace = "Castle.Rook.Parse";\r
12 }\r
14 class RookLangParser extends Parser;\r
16 options \r
17 {\r
18         k = 2;                                  // two token lookahead\r
19         defaultErrorHandler = true;             // Don't generate parser error handlers\r
20         buildAST = false;   \r
21         exportVocab=Rook;\r
22 }\r
23 tokens\r
24 {\r
25         CLASS_DEF = "class";\r
26         MIXIN_DEF = "mixin";\r
27         NAMESPACE = "namespace";\r
28         INTERFACE = "interface";\r
29         INIT      = "initialize";\r
30         INIT2     = "init";\r
31         END       = "end";\r
32         DEF       = "def";\r
33         ATTR      = "attr";\r
34         GET       = "get";\r
35         SET       = "set";\r
36         INC       = "++";\r
37         DEC       = "--";\r
38         SELF      = "self";\r
39         BASE      = "base";\r
40         COLON     = ":";\r
41         DO        = "do";\r
42 }\r
44 {\r
45         AccessLevel currentAccessLevel = AccessLevel.Public;\r
46         \r
47         public override void reportError(RecognitionException ex)\r
48         {\r
49                 throw ex;\r
50         }\r
51 }\r
53 compilation_unit returns[CompilationUnitNode unit]\r
54         {\r
55                 unit = new CompilationUnitNode();\r
56         }\r
57         :       \r
58         (options { greedy=true;}: EOS!)*\r
59         (declaration[unit])*\r
60         EOF!\r
61         ;\r
62         \r
63 declaration[AbstractDeclarationContainer container]\r
64         :\r
65         mixin_declaration[container.MixinTypes] \r
66         | \r
67         class_declaration[container.ClassesTypes] \r
68         | \r
69         namespace_member_declaration[container.Namespaces]\r
70         ;\r
72 namespace_member_declaration[IList namespaces]\r
73         :       \r
74         namespace_declaration[namespaces]\r
75         ;\r
77 namespace_declaration![IList namespaces]\r
78         {\r
79                 NamespaceNode ns = null;\r
80                 Identifier qi = null;\r
81         }\r
82         :       \r
83         NAMESPACE qi=qualified_identifier \r
84         { \r
85                 ns = new NamespaceNode( qi );\r
86         }\r
87         namespace_body[ns]\r
88         {\r
89                 namespaces.Add(ns);\r
90         }\r
91         ;\r
92         \r
93 namespace_body[NamespaceNode ns]\r
94         :       \r
95         (declaration[ns])* END!\r
96         ;\r
98 class_declaration![IList types]\r
99         {\r
100                 ClassDefinitionStatement classNode = null;\r
101                 Identifier id = null;\r
102         }\r
103         :\r
104         /* TODO:visibility public/private/etc */ \r
105         CLASS_DEF! id=identifier \r
106         {\r
107                 classNode = new ClassDefinitionStatement(id.Name);\r
108                 types.Add(classNode);\r
109         }\r
110         (baseTypes[classNode])?\r
111         class_body[classNode]\r
112         ;\r
114 mixin_declaration![IList mixins]\r
115         {\r
116                 MixinDefinitionStatement mixinNode = null;\r
117                 Identifier id = null;\r
118         }\r
119         :\r
120         MIXIN_DEF! id=identifier \r
121         {\r
122                 mixinNode = new MixinDefinitionStatement(id.Name);\r
123                 mixins.Add(mixinNode);\r
124         }\r
125         mixin_body[mixinNode]\r
126         ;\r
128 mixin_body[MixinDefinitionStatement mixinNode]\r
129         :\r
130         END!\r
131         ;\r
133 class_body[ClassDefinitionStatement classNode]\r
134         {\r
135                 // Default access level for the method body\r
136                 currentAccessLevel = AccessLevel.Public;\r
137         }\r
138         :\r
139         (access_level class_level_supported_statements[classNode.Statements])* END!\r
140         ;\r
142 protected\r
143 baseTypes![TypeDefinitionStatement type]\r
144         {\r
145                 Identifier qi = null;\r
146         }\r
147         :\r
148         LESSTHAN! qi=qualified_identifier \r
149         {\r
150                 type.BaseTypes.Add( qi );\r
151         }\r
152         (COMMA! qi=qualified_identifier\r
153         {\r
154                 type.BaseTypes.Add( qi );\r
155         })*\r
156         ;\r
158 protected\r
159 access_level!\r
160         :\r
161         "public"    { currentAccessLevel = AccessLevel.Public; }\r
162         |\r
163         "private"   { currentAccessLevel = AccessLevel.Private; }\r
164         |\r
165         "protected" { currentAccessLevel = AccessLevel.Protected; }\r
166         | \r
167         "internal"  { currentAccessLevel = AccessLevel.Internal; }\r
168         |\r
169                 /* nothing - inherits the access level defined previously */  \r
170         ;\r
172 protected\r
173 identifier! returns [Identifier ident]\r
174         {\r
175                 ident = null;\r
176         }\r
177         :       \r
178         id:IDENTIFIER \r
179         { ident = new Identifier(id.getText()); }\r
180         ;\r
182 protected\r
183 qualified_identifier returns [Identifier ident]\r
184         {\r
185                 ident = null;\r
186                 StringBuilder sb = new StringBuilder();\r
187                 Identifier id = null;\r
188         }\r
189         :       \r
190         id=identifier\r
191         {\r
192                 sb.Append(id.Name);\r
193         }\r
194         ( options { greedy=true; } : DOT! id=identifier\r
195         {\r
196                 sb.Append('.');\r
197                 sb.Append(id.Name);\r
198         }\r
199         )*\r
200         {\r
201                 ident = new Identifier( sb.ToString() );\r
202         }\r
203         ;\r
205 protected\r
206 method_name returns [String[] parts]\r
207         {\r
208                 parts = new String[2];\r
209                 Identifier id = null;\r
210         }\r
211         :       \r
212         (\r
213                 id=identifier\r
214                 {\r
215                         parts[0] = id.Name;\r
216                 }\r
217                 |\r
218                 SELF\r
219                 {\r
220                         parts[0] = "self";\r
221                 }\r
222         )\r
223         (DOT! id=identifier\r
224         {\r
225                 parts[1] = id.Name;\r
226         }\r
227         )?\r
228         ;\r
230 protected\r
231 type_name returns [Identifier qi]\r
232         {\r
233                 qi = null;\r
234         }\r
235         :       \r
236         (COLON qi=qualified_identifier)?\r
237         ;\r
239 ///\r
240 /// Statements\r
241 ///\r
243 block_statement returns [BlockStatement block]\r
244         {\r
245                 block = new BlockStatement();\r
246         }\r
247         :\r
248         DO\r
249                 statement_list[block.Statements]\r
250         END     (SEMI)?\r
251         ;\r
253 method_def_stmt returns [MethodDefinitionStatement method]\r
254         {\r
255                 String[] nameParts;\r
256                 Identifier retType = null;\r
257                 method = null;\r
258         }\r
259         :\r
260         DEF! nameParts=method_name \r
261         {\r
262                 method = new MethodDefinitionStatement(currentAccessLevel, nameParts);\r
263         }\r
264         formal_param_list[method]\r
265         retType=type_name\r
266         {\r
267                 method.ReturnType = retType;\r
268         }\r
269         method_body[method]\r
270         (SEMI)?\r
271         ;\r
272         \r
273 protected\r
274 formal_param_list[MethodDefinitionStatement method]\r
275         :\r
276         LPAREN! ( method_param[method] (COMMA! method_param[method])* )? RPAREN!\r
277         ;\r
278         \r
279 protected\r
280 method_param[MethodDefinitionStatement method]\r
281         {\r
282                 Identifier id = null;\r
283                 Identifier qi = null;\r
284         }\r
285         :\r
286         (REF|OUT)? id=identifier qi=type_name\r
287         {\r
288                 method.Parameters.Add( new MethodParameterNode(id.Name, qi) );\r
289         }\r
290         ;\r
292 protected\r
293 method_body[MethodDefinitionStatement method]\r
294         :\r
295         statement_list[method.Statements]\r
296         END!\r
297         ;\r
299 protected \r
300 statement returns [Statement stmt]\r
301         {\r
302                 stmt = null;\r
303         }\r
304         :\r
305         stmt=method_def_stmt\r
306         |\r
307         stmt=expression_statement\r
308         |\r
309         stmt=block_statement\r
310         |\r
311         stmt=simple_field_decl_stmt\r
312         ;\r
314 protected\r
315 statement_list[IList statements]\r
316         {\r
317                 Statement stmt = null;\r
318         }\r
319         :\r
320         (stmt=statement { statements.Add( stmt ); } )*\r
321         ;\r
322         \r
323 protected\r
324 class_level_supported_statements[IList statements]\r
325         {\r
326                 Statement stmt = null;\r
327         }\r
328         :\r
329         (\r
330                 stmt=field_decl_stmt\r
331                 |\r
332                 stmt=method_def_stmt\r
333         )\r
334         {\r
335                 statements.Add( stmt );\r
336         }\r
337         ;\r
339 protected\r
340 var_reference returns [IdentifierReferenceExpression exp]\r
341         {\r
342                 Identifier qi = null; exp = null;\r
343         }\r
344         :\r
345         id:STATIC_IDENTIFIER { exp = new StaticFieldReferenceExpression(id.getText()); }\r
346         |\r
347         id2:INSTANCE_IDENTIFIER { exp = new InstanceFieldReferenceExpression(id2.getText()); }\r
348         |\r
349         qi=qualified_identifier { exp = new IdentifierReferenceExpression(qi); }\r
350         ;       \r
352 protected\r
353 simple_field_decl_stmt returns [FieldDeclarationStatement stmt]\r
354         {\r
355                 stmt = null; IdentifierReferenceExpression var; \r
356                 Expression initializer = null; Identifier tn = null;\r
357         } \r
358         :\r
359         var=var_reference tn=type_name (ASSIGN initializer=expression)?\r
360         {\r
361                 stmt = new FieldDeclarationStatement(currentAccessLevel, var, tn, initializer);\r
362         }\r
363         ;\r
365 protected\r
366 field_decl_stmt returns [FieldDeclarationStatement stmt]\r
367         {\r
368                 stmt = null; IdentifierReferenceExpression var; \r
369                 Expression initializer = null; Identifier tn = null;\r
370         } \r
371         :\r
372         var=var_reference tn=type_name (ASSIGN initializer=expression)?\r
373         {\r
374                 stmt = new FieldDeclarationStatement(currentAccessLevel, var, tn, initializer);\r
375         }\r
376         ;\r
378 /*\r
379 protected\r
380 assign_stmt returns [AssignmentStatement stmt]\r
381         {\r
382                 stmt = null; IdentifierReferenceExpression target; Expression value;\r
383         } \r
384         :\r
385         target=var_reference ASSIGN value=expression\r
386         {\r
387                 stmt = new AssignmentStatement(currentAccessLevel, target, value);\r
388         }\r
389         ;\r
390 */\r
392 protected\r
393 expression_statement returns [ExpressionStatement stmt]\r
394         {\r
395                 stmt = null;\r
396                 Expression exp = null;\r
397         }\r
398         :\r
399         (\r
400                 (assign_exp) => exp=assign_exp\r
401                 |\r
402                 exp=unary_exp\r
403         )\r
404         {\r
405                 stmt = new ExpressionStatement(exp);\r
406         }\r
407         ;\r
408         \r
409 ///     \r
410 /// Expressions\r
411 /// \r
413 protected \r
414 assign_exp returns [AssignmentExpression ue]\r
415         {\r
416                 Expression target, value = null; ue = null;\r
417         }\r
418         :\r
419         target=unary_exp ASSIGN value=expression\r
420         {\r
421                 ue = new AssignmentExpression(target, value);\r
422         }\r
423         ;\r
425 protected\r
426 unary_exp returns [Expression exp]\r
427         { exp = null; }\r
428         :\r
429         exp=primary_exp\r
430         ;\r
432 protected\r
433 expression returns [Expression exp]\r
434         { exp = null; }\r
435         :\r
436         exp=primary_exp\r
437         ;\r
439 literal_exp returns [LiteralExpression le]\r
440         { le = null; }\r
441         :       \r
442         t:INTEGER_LITERAL\r
443         {\r
444                 le = new LiteralIntegerExpression( t.getText() );\r
445         }\r
446         ;\r
448 /*\r
449 symbol_exp returns [SymbolExpression se]\r
450         { se = null; }\r
451         :       \r
452         t:SYMBOLID\r
453         {\r
454                 se = new SymbolExpression( t.getText() );\r
455         }\r
456         ;\r
457 */\r
458         \r
459 protected \r
460 method_invoke_exp[Expression target] returns [MethodInvokeExpression mie]\r
461         {\r
462                 mie = new MethodInvokeExpression(target);\r
463                 Expression exp;\r
464         }\r
465         :\r
466         LPAREN ( exp=expression { mie.Arguments.Add( exp ); }\r
467         (COMMA! exp=expression { mie.Arguments.Add( exp ); } )* )? RPAREN\r
468         ( options {greedy=true;} :  SEMI)?\r
469         ;\r
470         \r
471 protected\r
472 primary_start returns [Expression exp]\r
473         { exp = null; }\r
474         :\r
475         /* \r
476         exp=symbol_exp\r
477         |\r
478         */\r
479         exp=literal_exp\r
480         |\r
481         exp=var_reference\r
482         |\r
483         SELF { exp = SelfReferenceExpression.Instance; }\r
484         |\r
485         BASE { exp = BaseReferenceExpression.Instance; }\r
486         ;\r
488 protected\r
489 primary_exp returns [Expression exp]\r
490         {\r
491                 Expression ps = null; exp = null;\r
492         }\r
493         :\r
494         (\r
495                 ps=primary_start\r
496                 (       options {greedy=true;}: \r
497                         exp=postfix_exp[ps]\r
498                         |\r
499                         exp=method_invoke_exp[ps]\r
500                         |       \r
501                         exp=member_access[ps]\r
502                 )*\r
503         )\r
504         {\r
505                 if (exp == null) exp = ps;\r
506         }\r
507         ;       \r
509 protected\r
510 member_access[Expression target] returns [MemberAccessExpression mae]\r
511         {\r
512                 mae = null;\r
513                 Identifier id;\r
514         }\r
515         :       \r
516         DOT id=identifier \r
517         {\r
518                 mae = new MemberAccessExpression(target, id);\r
519         }\r
520         ;\r
523 protected\r
524 postfix_exp[Expression target] returns [PostFixExpression pfe]\r
525         {\r
526                 pfe = null;\r
527         }\r
528         :\r
529         INC     { pfe = new PostFixExpression( target, 1 ); }\r
530         | \r
531         DEC     { pfe = new PostFixExpression( target, 2 ); }\r
532         ;       \r
534 /// \r
535 /// Lexer\r
536 ///     \r
537                 \r
538 class RookLexer extends Lexer;\r
540 options \r
542         k=4;                       // four characters of lookahead\r
543         charVocabulary='\u0003'..'\u7FFF';      // to avoid hanging eof on comments (eof = -1)\r
544     importVocab=Rook;\r
545         testLiterals=false;\r
546         filter=true;\r
549 ASSIGN                  :   '='         ;\r
550 SEMI                    :   ';'         ;\r
551 COMMA                   :   ','         ;\r
552 LPAREN                  :       '('             ;
553 RPAREN                  :       ')'             ;
554 LBRACK                  :       '['             ;
555 RBRACK                  :       ']'             ;
556 LCURLY                  :       '{'             ;
557 RCURLY                  :       '}'             ;
558 COLON                   :       ':'             ;
559 DOT             :   '.'     ;\r
560 LESSTHAN        :   '<'     ;\r
562         \r
563 // ***** A.1.1 LINE TERMINATORS *****\r
564 protected\r
565 NEW_LINE\r
566         :       (       // carriage return character followed by possible line feed character   \r
567                         { LA(2)=='\u000A' }? '\u000D' '\u000A'                  \r
568                 |       '\u000D'                        // line feed character                                                  \r
569                 |       '\u000A'                        // line feed character                                                  \r
570                 |       '\u2028'                        // line separator character\r
571                 |       '\u2029'                        // paragraph separator character\r
572                 )\r
573                 {newline();}\r
574         ;\r
575         \r
576 protected\r
577 NEW_LINE_CHARACTER\r
578         :       ('\u000D' | '\u000A' | '\u2028' | '\u2029')\r
579         ;\r
580         \r
581 protected\r
582 NOT_NEW_LINE\r
583         :       ~( '\u000D' | '\u000A' | '\u2028' | '\u2029')\r
584         ;\r
585         \r
586 // ***** A.1.2 WHITESPACE *****\r
587 WHITESPACE\r
588         :       (       ' '\r
589                 |       '\u0009' // horizontal tab character\r
590                 |       '\u000B' // vertical tab character\r
591                 |       '\u000C' // form feed character \r
592                 |       NEW_LINE \r
593                 )+\r
594                 { _ttype = Token.SKIP; }\r
595         ;       \r
596         \r
597         \r
598 // ***** A.1.3 COMMENTS *****\r
599 SINGLE_LINE_COMMENT\r
600         :       "#" \r
601                 (NOT_NEW_LINE)* \r
602                 (NEW_LINE)? // may be eof\r
603                 {_ttype = Token.SKIP;}\r
604         ;\r
606                 \r
607 // ***** A.1.6 IDENTIFIERS *****\r
609 IDENTIFIER\r
610 options \r
611         {\r
612          testLiterals=true; \r
613          paraphrase = "an identifier";\r
614         }\r
615         :       \r
616         IDENTIFIER_START_CHARACTER (IDENTIFIER_PART_CHARACTER)*\r
617         ;\r
618         \r
619         /*\r
620 SYMBOLID\r
621 options \r
622         {\r
623          testLiterals=false; \r
624          paraphrase = "a symbol";\r
625         }\r
626         :       \r
627         COLON IDENTIFIER\r
628         ;\r
629         */\r
630         \r
631 protected\r
632 IDENTIFIER_START_CHARACTER\r
633         :       ('a'..'z'|'A'..'Z'|'_'|'$') \r
634         ;\r
635         \r
636 protected\r
637 IDENTIFIER_PART_CHARACTER\r
638         :       ('a'..'z'|'A'..'Z'|'_'|'0'..'9') \r
639         ;\r
640         \r
641 STATIC_IDENTIFIER\r
642 options \r
643         {\r
644          testLiterals=false; \r
645          paraphrase = "an static variable name";\r
646         }\r
647         :       \r
648         "@@" IDENTIFIER_START_CHARACTER (IDENTIFIER_PART_CHARACTER)*\r
649         ;\r
651 INSTANCE_IDENTIFIER\r
652 options \r
653         {\r
654          testLiterals=false; \r
655          paraphrase = "an instance variable name";\r
656         }\r
657         :       \r
658         "@" IDENTIFIER_START_CHARACTER (IDENTIFIER_PART_CHARACTER)*\r
659         ;\r
661 NUMERIC_LITERAL\r
662         :\r
663         // integer\r
664         (DECIMAL_DIGIT)+ \r
665         {\r
666                 $setType(INTEGER_LITERAL);\r
667         }\r
668         ;\r
670 // nums\r
671 protected\r
672 DECIMAL_DIGIT\r
673         :       \r
674         ('0'..'9')\r
675         ;\r