2001-09-12 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
1 %{\r
2 //\r
3 // cs-parser.jay: The Parser for the C# compiler\r
4 //\r
5 // Author: Miguel de Icaza (miguel@gnu.org)\r
6 //\r
7 // Licensed under the terms of the GNU GPL\r
8 //\r
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)\r
10 //\r
11 // TODO:\r
12 //   (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM\r
13 //       And come to think of it, it is not that great, it duplicates a lot of code\r
14 //       for something which is not really needed.  We still have piles of typecasts\r
15 //       anwyays (due to the nature of the stack being a collection of Objects).\r
16 //\r
17 //   (2) Figure out why error productions dont work.  `type-declaration' is a\r
18 //       great spot to put an `error' because you can reproduce it with this input:\r
19 //       "public X { }"\r
20 //\r
21 //   (3) Move Modifier checking from each object into the parser itself, that will\r
22 //       get rid of the global "error" symbol that we use now to report errors. \r
23 //       We still need to pass a pointer to the tree.ErrorHandler, but that is a \r
24 //       separate problem\r
25 //\r
26 using System.Text;\r
27 using CIR;\r
28 using System;\r
29 \r
30 namespace CIR\r
31 {\r
32         using System.Collections;\r
33         using Mono.Languages;\r
34 \r
35         /// <summary>\r
36         ///    The C# Parser\r
37         /// </summary>\r
38         public class CSharpParser : GenericParser {\r
39                 Namespace     current_namespace;\r
40                 TypeContainer current_container;\r
41         \r
42                 // <summary>\r
43                 //   Current block is used to add statements as we find\r
44                 //   them.  \r
45                 // </summary>\r
46 \r
47                 Block      current_block;\r
48 \r
49                 // <summary>\r
50                 //   Current interface is used by the various declaration\r
51                 //   productions in the interface declaration to "add"\r
52                 //   the interfaces as we find them.\r
53                 // </summary>\r
54                 Interface  current_interface;\r
55 \r
56                 // <summary>\r
57                 //   This is used by the unary_expression code to resolve\r
58                 //   a name against a parameter.  \r
59                 // </summary>\r
60                 Parameters current_local_parameters;\r
61 \r
62                 // <summary>\r
63                 //   Using during property parsing to describe the implicit\r
64                 //   value parameter that is passed to the "set" accesor\r
65                 //   method\r
66                 // </summary>\r
67                 Parameter [] implicit_value_parameters;\r
68 \r
69                 // <summary>\r
70                 //   Used to determine if we are parsing the get/set pair\r
71                 //   of an indexer or a property\r
72                 // </summmary>\r
73                 bool  parsing_indexer;\r
74 \r
75                 // <summary>\r
76                 //   Used to record all types defined\r
77                 // </summary>\r
78                 Tree tree;\r
79                 RootContext rc;\r
80 \r
81 %}\r
82 \r
83 %token EOF\r
84 %token NONE   /* This token is never returned by our lexer */\r
85 %token ERROR            // This is used not by the parser, but by the tokenizer.\r
86                         // do not remove.\r
87 \r
88 /*\r
89  *These are the C# keywords\r
90  */\r
91 %token ABSTRACT \r
92 %token AS\r
93 %token ADD\r
94 %token BASE     \r
95 %token BOOL     \r
96 %token BREAK    \r
97 %token BYTE     \r
98 %token CASE     \r
99 %token CATCH    \r
100 %token CHAR     \r
101 %token CHECKED  \r
102 %token CLASS    \r
103 %token CONST    \r
104 %token CONTINUE \r
105 %token DECIMAL  \r
106 %token DEFAULT  \r
107 %token DELEGATE \r
108 %token DO       \r
109 %token DOUBLE   \r
110 %token ELSE     \r
111 %token ENUM     \r
112 %token EVENT    \r
113 %token EXPLICIT \r
114 %token EXTERN   \r
115 %token FALSE    \r
116 %token FINALLY  \r
117 %token FIXED    \r
118 %token FLOAT    \r
119 %token FOR      \r
120 %token FOREACH  \r
121 %token GOTO     \r
122 %token IF       \r
123 %token IMPLICIT \r
124 %token IN       \r
125 %token INT      \r
126 %token INTERFACE\r
127 %token INTERNAL \r
128 %token IS       \r
129 %token LOCK     \r
130 %token LONG     \r
131 %token NAMESPACE\r
132 %token NEW      \r
133 %token NULL     \r
134 %token OBJECT   \r
135 %token OPERATOR \r
136 %token OUT      \r
137 %token OVERRIDE \r
138 %token PARAMS   \r
139 %token PRIVATE  \r
140 %token PROTECTED\r
141 %token PUBLIC   \r
142 %token READONLY \r
143 %token REF      \r
144 %token RETURN   \r
145 %token REMOVE\r
146 %token SBYTE    \r
147 %token SEALED   \r
148 %token SHORT    \r
149 %token SIZEOF   \r
150 %token STATIC   \r
151 %token STRING   \r
152 %token STRUCT   \r
153 %token SWITCH   \r
154 %token THIS     \r
155 %token THROW    \r
156 %token TRUE     \r
157 %token TRY      \r
158 %token TYPEOF   \r
159 %token UINT     \r
160 %token ULONG    \r
161 %token UNCHECKED\r
162 %token UNSAFE   \r
163 %token USHORT   \r
164 %token USING    \r
165 %token VIRTUAL  \r
166 %token VOID     \r
167 %token WHILE    \r
168 \r
169 /* C# keywords which are not really keywords */\r
170 %token GET           "get"\r
171 %token SET           "set"\r
172 \r
173 /* C# single character operators/punctuation. */\r
174 %token OPEN_BRACE    "{"\r
175 %token CLOSE_BRACE   "}"\r
176 %token OPEN_BRACKET  "["\r
177 %token CLOSE_BRACKET "]"\r
178 %token OPEN_PARENS   "("\r
179 %token CLOSE_PARENS  ")"\r
180 %token DOT           "."\r
181 %token COMMA         ","\r
182 %token COLON         ":"\r
183 %token SEMICOLON     ";"\r
184 %token TILDE         "~"\r
185 \r
186 %token PLUS           "+"\r
187 %token MINUS          "-"\r
188 %token BANG           "!"\r
189 %token ASSIGN         "="\r
190 %token OP_LT          "<"\r
191 %token OP_GT          ">"\r
192 %token BITWISE_AND    "&"\r
193 %token BITWISE_OR     "|"\r
194 %token STAR           "*"\r
195 %token PERCENT        "%"\r
196 %token DIV            "/"\r
197 %token CARRET         "^"\r
198 %token INTERR         "?"\r
199 \r
200 /* C# multi-character operators. */\r
201 %token OP_INC                 "++"\r
202 %token OP_DEC                 "--"\r
203 %token OP_SHIFT_LEFT          "<<"\r
204 %token OP_SHIFT_RIGHT         ">>"\r
205 %token OP_LE                  "<="\r
206 %token OP_GE                  ">="\r
207 %token OP_EQ                  "=="\r
208 %token OP_NE                  "!="\r
209 %token OP_AND                 "&&"\r
210 %token OP_OR                  "||"\r
211 %token OP_MULT_ASSIGN         "*="\r
212 %token OP_DIV_ASSIGN          "/="\r
213 %token OP_MOD_ASSIGN          "%="\r
214 %token OP_ADD_ASSIGN          "+="\r
215 %token OP_SUB_ASSIGN          "-="\r
216 %token OP_SHIFT_LEFT_ASSIGN   "<<="\r
217 %token OP_SHIFT_RIGHT_ASSIGN  ">>="\r
218 %token OP_AND_ASSIGN          "&="\r
219 %token OP_XOR_ASSIGN          "^="\r
220 %token OP_OR_ASSIGN           "|="\r
221 %token OP_PTR                 "->"\r
222 \r
223 /* Numbers */\r
224 %token LITERAL_INTEGER           "int literal"\r
225 %token LITERAL_FLOAT             "float literal"\r
226 %token LITERAL_DOUBLE            "double literal"\r
227 %token LITERAL_DECIMAL           "decimal literal"\r
228 %token LITERAL_CHARACTER         "character literal"\r
229 %token LITERAL_STRING            "string literal"\r
230 \r
231 %token IDENTIFIER\r
232 \r
233 /* Add precedence rules to solve dangling else s/r conflict */\r
234 %nonassoc LOWPREC\r
235 %nonassoc IF\r
236 %nonassoc ELSE\r
237 %right ASSIGN\r
238 %left OP_OR\r
239 %left OP_AND\r
240 %left BITWISE_OR\r
241 %left BITWISE_AND\r
242 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT\r
243 %left PLUS MINUS\r
244 %left STAR DIV PERCENT\r
245 %right BANG CARRET UMINUS\r
246 %nonassoc OP_INC OP_DEC\r
247 %left OPEN_PARENS\r
248 %left OPEN_BRACKET OPEN_BRACE\r
249 %left DOT\r
250 %nonassoc HIGHPREC\r
251 \r
252 %start compilation_unit\r
253 /*%start namespace_declaration */\r
254 %%\r
255 \r
256 compilation_unit\r
257         : opt_using_directives opt_attributes opt_namespace_member_declarations EOF\r
258           {\r
259                 // Check that using comes only before namespace elements\r
260           }\r
261         ;\r
262 \r
263 using_directives\r
264         : using_directive \r
265         | using_directives using_directive\r
266         ;\r
267 \r
268 using_directive\r
269         : using_alias_directive\r
270         | using_namespace_directive\r
271         ;\r
272 \r
273 using_alias_directive\r
274         : USING IDENTIFIER ASSIGN \r
275           namespace_or_type_name SEMICOLON\r
276           {\r
277                   // FIXME : Need to implement actual action.\r
278           }\r
279         ;\r
280 \r
281 using_namespace_directive\r
282         : USING namespace_name SEMICOLON \r
283           {\r
284                 current_namespace.Using ((string) $2);\r
285           }\r
286         ;\r
287 \r
288 //  namespace_declarations\r
289 //      : namespace_declaration\r
290 //      | namespace_declarations namespace_declaration\r
291 \r
292 namespace_declaration\r
293         : NAMESPACE qualified_identifier \r
294           {\r
295                 current_namespace = new Namespace (current_namespace, (string) $2); \r
296           } \r
297           namespace_body opt_semicolon\r
298           { \r
299                 current_namespace = current_namespace.Parent;\r
300           }\r
301         ;\r
302 \r
303 opt_semicolon\r
304         : /* empty */\r
305         | SEMICOLON\r
306         ;\r
307 \r
308 opt_comma\r
309         : /* empty */\r
310         | COMMA\r
311         ;\r
312 \r
313 qualified_identifier\r
314         : IDENTIFIER\r
315         | qualified_identifier DOT IDENTIFIER { \r
316             $$ = (($1).ToString ()) + "." + ($3.ToString ()); }\r
317         ;\r
318 \r
319 \r
320 namespace_name\r
321         : namespace_or_type_name\r
322         ;\r
323 \r
324 namespace_body\r
325         : OPEN_BRACE\r
326           opt_using_directives\r
327           opt_namespace_member_declarations\r
328           CLOSE_BRACE\r
329           {\r
330           }\r
331         ;\r
332 \r
333 opt_using_directives\r
334         : /* empty */\r
335         | using_directives\r
336         ;\r
337 \r
338 opt_namespace_member_declarations\r
339         : /* empty */\r
340         | namespace_member_declarations\r
341         ;\r
342 \r
343 namespace_member_declarations\r
344         : namespace_member_declaration\r
345         | namespace_member_declarations namespace_member_declaration\r
346         ;\r
347 \r
348 namespace_member_declaration\r
349         : type_declaration\r
350           {\r
351                 int mod_flags = 0;\r
352                 string name = "";\r
353 \r
354                 if ($1 is Class){\r
355                         Class c = (Class) $1;\r
356                         mod_flags = c.ModFlags;\r
357                         name = c.Name;\r
358                 } else if ($1 is Struct){\r
359                         Struct s = (Struct) $1;\r
360                         mod_flags = s.ModFlags;\r
361                         name = s.Name;\r
362                 } else\r
363                         break;\r
364 \r
365                 //\r
366                 // We remove this error until we can \r
367                 //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){\r
368                 //      error (1527, "Namespace elements cant be explicitly " +\r
369                 //                   "declared private or protected in `" + name + "'");\r
370                 //}\r
371           }\r
372         | namespace_declaration\r
373         ;\r
374 \r
375 type_declaration\r
376         : class_declaration             \r
377         | struct_declaration            \r
378         | interface_declaration         \r
379         | enum_declaration              \r
380         | delegate_declaration         \r
381         ;\r
382 \r
383 //\r
384 // Attributes 17.2\r
385 //\r
386 opt_attributes\r
387         : /* empty */ { $$ = null; }\r
388         | attribute_section opt_attributes\r
389           {\r
390                 Attributes attrs;\r
391                 \r
392                 if ($2 != null) {\r
393                         attrs = (Attributes) $2;\r
394                         attrs.AddAttribute ((Attribute) $1);\r
395                 } else\r
396                         attrs = new Attributes ((Attribute) $1);\r
397                 \r
398                 $$ = attrs;\r
399           }\r
400         ;\r
401 \r
402 attribute_section\r
403         : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET\r
404           {\r
405                 string target = null;\r
406                 \r
407                 if ($2 != null)\r
408                         target = (string) $2;\r
409                 \r
410                 $$ = new Attribute (target, (ArrayList) $3);\r
411           }\r
412         | OPEN_BRACKET attribute_list CLOSE_BRACKET\r
413           {\r
414                 $$ = new Attribute (null, (ArrayList) $2);\r
415           }\r
416         ;\r
417  \r
418 attribute_target_specifier\r
419         : attribute_target COLON\r
420           {\r
421                 $$ = $1;\r
422           }\r
423         ;\r
424 \r
425 attribute_target\r
426         : IDENTIFIER\r
427           {\r
428                 CheckAttributeTarget ((string) $1);\r
429                 $$ = $1;\r
430           }\r
431         | EVENT  { $$ = "event"; }        \r
432         | RETURN { $$ = "return"; }\r
433         ;\r
434 \r
435 attribute_list\r
436         : attribute\r
437           {\r
438                 ArrayList attrs = new ArrayList ();\r
439                 attrs.Add ($1);\r
440 \r
441                 $$ = attrs;\r
442                \r
443           }\r
444         | attribute_list COMMA attribute\r
445           {\r
446                 ArrayList attrs = (ArrayList) $1;\r
447                 attrs.Add ($3);\r
448 \r
449                 $$ = attrs;\r
450           }\r
451         ;\r
452 \r
453 attribute\r
454         : attribute_name opt_attribute_arguments\r
455           {\r
456                 $$ = new DictionaryEntry ($1, $2);\r
457           }\r
458         ;\r
459 \r
460 attribute_name\r
461         : type_name  { /* reserved attribute name or identifier: 17.4 */ }\r
462         ;\r
463 \r
464 opt_attribute_arguments\r
465         : /* empty */   { $$ = null; }\r
466         | OPEN_PARENS attribute_arguments CLOSE_PARENS\r
467           {\r
468                 $$ = $2;\r
469           }\r
470         ;\r
471 \r
472 attribute_arguments\r
473         : expression\r
474           {\r
475                 ArrayList args = new ArrayList ();\r
476                 args.Add ($1);\r
477                 \r
478                 $$ = args;\r
479           }\r
480         | attribute_arguments COMMA expression\r
481           {\r
482                 ArrayList args = (ArrayList) $1;\r
483                 args.Add ($3);\r
484 \r
485                 $$ = args;\r
486           }\r
487         ;\r
488 \r
489 \r
490 class_body\r
491         :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE\r
492         ;\r
493 \r
494 opt_class_member_declarations\r
495         : /* empty */\r
496         | class_member_declarations\r
497         ;\r
498 \r
499 class_member_declarations\r
500         : class_member_declaration\r
501         | class_member_declarations \r
502           class_member_declaration\r
503         ;\r
504 \r
505 class_member_declaration\r
506         : constant_declaration                  // done\r
507         | field_declaration                     // done\r
508         | method_declaration                    // done\r
509         | property_declaration                  // done\r
510         | event_declaration                     // done\r
511         | indexer_declaration                   // done\r
512         | operator_declaration                  // done\r
513         | constructor_declaration               // done\r
514         | destructor_declaration                // done\r
515         | type_declaration\r
516         ;\r
517 \r
518 struct_declaration\r
519         : opt_attributes\r
520           opt_modifiers\r
521           STRUCT IDENTIFIER\r
522           { \r
523                 Struct new_struct;\r
524                 string full_struct_name = MakeName ((string) $4);\r
525 \r
526                 new_struct = new Struct (rc, current_container, full_struct_name, (int) $2, (Attributes) $1);\r
527                 current_container = new_struct;\r
528                 current_container.Namespace = current_namespace;\r
529                 tree.RecordStruct (full_struct_name, new_struct);\r
530           }\r
531           opt_struct_interfaces\r
532           struct_body\r
533           opt_semicolon\r
534           {\r
535                 Struct new_struct = (Struct) current_container;\r
536 \r
537                 current_container = current_container.Parent;\r
538                 CheckDef (current_container.AddStruct (new_struct), new_struct.Name);\r
539                 $$ = new_struct;\r
540           }\r
541         ;\r
542 \r
543 opt_struct_interfaces\r
544         : /* empty */\r
545         | struct_interfaces\r
546         ;\r
547 \r
548 struct_interfaces\r
549         : struct_interface\r
550         | struct_interfaces struct_interface\r
551         ; \r
552 \r
553 struct_interface\r
554         : COLON type_list\r
555         ;\r
556 \r
557 struct_body\r
558         : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE\r
559         ;\r
560 \r
561 opt_struct_member_declarations\r
562         : /* empty */\r
563         | struct_member_declarations\r
564         ;\r
565 \r
566 struct_member_declarations\r
567         : struct_member_declaration\r
568         | struct_member_declarations struct_member_declaration\r
569         ;\r
570 \r
571 struct_member_declaration\r
572         : constant_declaration\r
573         | field_declaration\r
574         | method_declaration\r
575         | property_declaration\r
576         | event_declaration\r
577         | indexer_declaration\r
578         | operator_declaration\r
579         | constructor_declaration\r
580         | type_declaration\r
581         ;\r
582 \r
583 constant_declaration\r
584         : opt_attributes \r
585           opt_modifiers\r
586           CONST\r
587           type\r
588           constant_declarators\r
589           SEMICOLON\r
590           {\r
591                 foreach (DictionaryEntry constant in (ArrayList) $5){\r
592                         Constant c = new Constant (\r
593                                 (string) $4, (string) constant.Key, \r
594                                 (Expression) constant.Value, (int) $2, (Attributes) $1);\r
595 \r
596                         CheckDef (current_container.AddConstant (c), c.Name);\r
597                 }\r
598           }\r
599         ;\r
600 \r
601 constant_declarators\r
602         : constant_declarator \r
603           {\r
604                 ArrayList constants = new ArrayList ();\r
605                 constants.Add ($1);\r
606                 $$ = constants;\r
607           }\r
608         | constant_declarators COMMA constant_declarator\r
609           {\r
610                 ArrayList constants = (ArrayList) $1;\r
611 \r
612                 constants.Add ($3);\r
613           }\r
614         ;\r
615 \r
616 constant_declarator\r
617         : IDENTIFIER ASSIGN constant_expression\r
618           {\r
619                 $$ = new DictionaryEntry ($1, $3);\r
620           }\r
621         ;\r
622 \r
623 field_declaration\r
624         : opt_attributes\r
625           opt_modifiers\r
626           type \r
627           variable_declarators\r
628           SEMICOLON\r
629         { \r
630                 string type = (string) $3;\r
631                 int mod = (int) $2;\r
632 \r
633                 foreach (VariableDeclaration var in (ArrayList) $4){\r
634                         Field field = new Field (type, mod, var.identifier, \r
635                                                  var.expression_or_array_initializer, (Attributes) $1);\r
636 \r
637                         CheckDef (current_container.AddField (field), field.Name);\r
638                 }\r
639         }\r
640 \r
641         ;\r
642 \r
643 variable_declarators\r
644         : variable_declarator \r
645           {\r
646                 ArrayList decl = new ArrayList ();\r
647                 decl.Add ($1);\r
648                 $$ = decl;\r
649           }\r
650         | variable_declarators COMMA variable_declarator\r
651           {\r
652                 ArrayList decls = (ArrayList) $1;\r
653                 decls.Add ($3);\r
654                 $$ = $1;\r
655           }\r
656         ;\r
657 \r
658 variable_declarator\r
659         : IDENTIFIER ASSIGN variable_initializer\r
660           {\r
661                 $$ = new VariableDeclaration ((string) $1, $3);\r
662           }\r
663         | IDENTIFIER\r
664           {\r
665                 $$ = new VariableDeclaration ((string) $1, null);\r
666           }\r
667         ;\r
668 \r
669 variable_initializer\r
670         : expression\r
671           {\r
672                 $$ = $$;\r
673           }\r
674         | array_initializer\r
675         {\r
676                 $$ = $1;\r
677         }\r
678         ;\r
679 \r
680 method_declaration\r
681         : method_header\r
682           method_body\r
683           {\r
684                 Method method = (Method) $1;\r
685 \r
686                 method.Block = (Block) $2;\r
687                 CheckDef (current_container.AddMethod (method), method.Name);\r
688 \r
689                 current_local_parameters = null;\r
690           }\r
691         ;\r
692 \r
693 method_header\r
694         : opt_attributes\r
695           opt_modifiers\r
696           type\r
697           member_name\r
698           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
699           {\r
700                 Method method = new Method ((string) $3, (int) $2, (string) $4, (Parameters) $6, (Attributes) $1);\r
701 \r
702                 current_local_parameters = (Parameters) $6;\r
703 \r
704                 $$ = method;\r
705           }\r
706         | opt_attributes\r
707           opt_modifiers\r
708           VOID\r
709           member_name\r
710           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
711           {\r
712                 Method method = new Method ("System.Void", (int) $2, (string) $4, (Parameters) $6, (Attributes) $1);\r
713 \r
714                 current_local_parameters = (Parameters) $6;\r
715                 $$ = method;\r
716           }\r
717         ;\r
718 \r
719 method_body\r
720         : block\r
721         | SEMICOLON             { $$ = null; }\r
722         ;\r
723 \r
724 opt_formal_parameter_list\r
725         : /* empty */                   { $$ = new Parameters (null, null); }\r
726         | formal_parameter_list\r
727         ;\r
728 \r
729 formal_parameter_list\r
730         : fixed_parameters              \r
731           { \r
732                 ArrayList pars_list = (ArrayList) $1;\r
733 \r
734                 Parameter [] pars = new Parameter [pars_list.Count];\r
735                 pars_list.CopyTo (pars);\r
736 \r
737                 $$ = new Parameters (pars, null); \r
738           } \r
739         | fixed_parameters COMMA parameter_array\r
740           {\r
741                 ArrayList pars_list = (ArrayList) $1;\r
742 \r
743                 Parameter [] pars = new Parameter [pars_list.Count];\r
744                 pars_list.CopyTo (pars);\r
745 \r
746                 $$ = new Parameters (pars, (Parameter) $3); \r
747           }\r
748         | parameter_array \r
749           {\r
750                 $$ = new Parameters (null, (Parameter) $1);\r
751           }\r
752         ;\r
753 \r
754 fixed_parameters\r
755         : fixed_parameter       \r
756           {\r
757                 ArrayList pars = new ArrayList ();\r
758 \r
759                 pars.Add ($1);\r
760                 $$ = pars;\r
761           }\r
762         | fixed_parameters COMMA fixed_parameter\r
763           {\r
764                 ArrayList pars = (ArrayList) $1;\r
765 \r
766                 pars.Add ($3);\r
767                 $$ = $1;\r
768           }\r
769         ;\r
770 \r
771 fixed_parameter\r
772         : opt_attributes\r
773           opt_parameter_modifier\r
774           type\r
775           IDENTIFIER\r
776           {\r
777                 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);\r
778           }\r
779         ;\r
780 \r
781 opt_parameter_modifier\r
782         : /* empty */           { $$ = Parameter.Modifier.NONE; }\r
783         | parameter_modifier\r
784         ;\r
785 \r
786 parameter_modifier\r
787         : REF                   { $$ = Parameter.Modifier.REF; }\r
788         | OUT                   { $$ = Parameter.Modifier.OUT; }\r
789         ;\r
790 \r
791 parameter_array\r
792         : opt_attributes PARAMS type IDENTIFIER\r
793           { \r
794                 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);\r
795                 note ("type must be a single-dimension array type"); \r
796           }\r
797         ;\r
798 \r
799 member_name \r
800         : IDENTIFIER { $$ = $1.ToString (); }\r
801         | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }\r
802         ;\r
803 \r
804 property_declaration\r
805         : opt_attributes\r
806           opt_modifiers\r
807           type member_name\r
808           OPEN_BRACE \r
809           {\r
810                 Parameter implicit_value_parameter;\r
811                 implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE, null);\r
812 \r
813                 lexer.properties = true;\r
814                 \r
815                 implicit_value_parameters = new Parameter [1];\r
816                 implicit_value_parameters [0] = implicit_value_parameter;\r
817           }\r
818           accessor_declarations \r
819           {\r
820                 lexer.properties = false;\r
821           }\r
822           CLOSE_BRACE\r
823           { \r
824                 Property prop;\r
825                 DictionaryEntry pair = (DictionaryEntry) $7;\r
826                 Block get_block = null;\r
827                 Block set_block = null;\r
828 \r
829                 if (pair.Key != null)\r
830                         get_block = (Block) pair.Key;\r
831                 if (pair.Value != null)\r
832                         set_block = (Block) pair.Value;\r
833 \r
834                 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block, (Attributes) $1);\r
835                 \r
836                 CheckDef (current_container.AddProperty (prop), prop.Name);\r
837                 implicit_value_parameters = null;\r
838           }\r
839         ;\r
840 \r
841 accessor_declarations\r
842         : get_accessor_declaration opt_set_accessor_declaration\r
843           { \r
844                 $$ = new DictionaryEntry ($1, $2);\r
845           }\r
846         | set_accessor_declaration opt_get_accessor_declaration\r
847           {\r
848                 $$ = new DictionaryEntry ($2, $1);\r
849           }\r
850         ;\r
851 \r
852 opt_get_accessor_declaration\r
853         : /* empty */                   { $$ = null; }\r
854         | get_accessor_declaration\r
855         ;\r
856 \r
857 opt_set_accessor_declaration\r
858         : /* empty */                   { $$ = null; }\r
859         | set_accessor_declaration\r
860         ;\r
861 \r
862 get_accessor_declaration\r
863         : opt_attributes GET\r
864           {\r
865                 // If this is not the case, then current_local_parameters has already\r
866                 // been set in indexer_declaration\r
867                   if (parsing_indexer == false)\r
868                           current_local_parameters = new Parameters (implicit_value_parameters, null);\r
869 \r
870                 \r
871           }\r
872           accessor_body\r
873           {\r
874                 $$ = $4;\r
875                 current_local_parameters = null;\r
876           }\r
877         ;\r
878 \r
879 set_accessor_declaration\r
880         : opt_attributes SET \r
881           {\r
882                   if (parsing_indexer == false)  \r
883                           current_local_parameters = new Parameters (implicit_value_parameters, null);\r
884           }\r
885           accessor_body\r
886           {\r
887                 $$ = $4;\r
888                 current_local_parameters = null;\r
889           }\r
890         ;\r
891 \r
892 accessor_body\r
893         : block \r
894         | SEMICOLON             { $$ = new Block (null); }\r
895         ;\r
896 \r
897 interface_declaration\r
898         : opt_attributes\r
899           opt_modifiers\r
900           INTERFACE IDENTIFIER\r
901           {\r
902                 Interface new_interface;\r
903                 string full_interface_name = MakeName ((string) $4);\r
904 \r
905                 new_interface = new Interface (current_container, full_interface_name, (int) $2, (Attributes) $1);\r
906                 if (current_interface != null) {\r
907                         Location l = lexer.Location;\r
908                         rc.Report.Error (-2, l, "Internal compiler error: interface inside interface");\r
909                 }\r
910                 current_interface = new_interface;\r
911                 tree.RecordInterface (full_interface_name, new_interface);\r
912           }\r
913           opt_interface_base\r
914           interface_body\r
915           { \r
916                 Interface new_interface = (Interface) current_interface;\r
917 \r
918                 if ($6 != null)\r
919                         new_interface.Bases = (ArrayList) $6;\r
920 \r
921                 current_interface = null;\r
922                 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);\r
923           }\r
924         ;\r
925 \r
926 opt_interface_base\r
927         : /* empty */                     { $$ = null; }\r
928         | interface_base\r
929         ;\r
930 \r
931 interface_base\r
932         : COLON interface_type_list       { $$ = $2; }\r
933         ;\r
934 \r
935 interface_type_list\r
936         : interface_type\r
937           {\r
938                 ArrayList interfaces = new ArrayList ();\r
939 \r
940                 interfaces.Add ($1);\r
941                 $$ = interfaces;\r
942           }\r
943         | interface_type_list COMMA interface_type\r
944           {\r
945                 ArrayList interfaces = (ArrayList) $1;\r
946                 interfaces.Add ($3);\r
947                 $$ = interfaces;\r
948           }\r
949         ;\r
950 \r
951 interface_body\r
952         : OPEN_BRACE\r
953           opt_interface_member_declarations\r
954           CLOSE_BRACE\r
955         ;\r
956 \r
957 opt_interface_member_declarations\r
958         : /* empty */\r
959         | interface_member_declarations\r
960         ;\r
961 \r
962 interface_member_declarations\r
963         : interface_member_declaration\r
964         | interface_member_declarations interface_member_declaration\r
965         ;\r
966 \r
967 interface_member_declaration\r
968         : interface_method_declaration          \r
969           { \r
970                 InterfaceMethod m = (InterfaceMethod) $1;\r
971 \r
972                 CheckDef (current_interface.AddMethod (m), m.Name);\r
973           }\r
974         | interface_property_declaration        \r
975           { \r
976                 InterfaceProperty p = (InterfaceProperty) $1;\r
977 \r
978                 CheckDef (current_interface.AddProperty (p), p.Name);\r
979           }\r
980         | interface_event_declaration \r
981           { \r
982                 InterfaceEvent e = (InterfaceEvent) $1;\r
983 \r
984                 CheckDef (current_interface.AddEvent (e), e.Name);\r
985           }\r
986         | interface_indexer_declaration\r
987           { \r
988                 InterfaceIndexer i = (InterfaceIndexer) $1;\r
989 \r
990                 CheckDef (current_interface.AddIndexer (i), "indexer");\r
991           }\r
992         ;\r
993 \r
994 opt_new\r
995         : /* empty */   { $$ = false; }\r
996         | NEW           { $$ = true; }\r
997         ;\r
998 \r
999 interface_method_declaration\r
1000         : opt_attributes opt_new type IDENTIFIER \r
1001           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS\r
1002           SEMICOLON\r
1003           {\r
1004                 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);\r
1005           }\r
1006         | opt_attributes opt_new VOID IDENTIFIER \r
1007           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS\r
1008           SEMICOLON\r
1009           {\r
1010                 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);\r
1011           }\r
1012         ;\r
1013 \r
1014 interface_property_declaration\r
1015         : opt_attributes\r
1016           opt_new\r
1017           type IDENTIFIER \r
1018           OPEN_BRACE \r
1019           { lexer.properties = true; }\r
1020           interface_accesors \r
1021           { lexer.properties = false; }\r
1022           CLOSE_BRACE\r
1023           {\r
1024                 int gs = (int) $7;\r
1025 \r
1026                 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2, \r
1027                                             (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1);\r
1028           }\r
1029         ;\r
1030 \r
1031 interface_accesors\r
1032         : opt_attributes GET SEMICOLON          { $$ = 1; }\r
1033         | opt_attributes SET SEMICOLON          { $$ = 2; }\r
1034         | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON \r
1035           { $$ = 3; }\r
1036         | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON\r
1037           { $$ = 3; }\r
1038         ;\r
1039 \r
1040 interface_event_declaration\r
1041         : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON\r
1042           {\r
1043                 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);\r
1044           }\r
1045         ;\r
1046 \r
1047 interface_indexer_declaration \r
1048         : opt_attributes opt_new type THIS \r
1049           OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
1050           OPEN_BRACE \r
1051           { lexer.properties = true; }\r
1052           interface_accesors \r
1053           { lexer.properties = false; }\r
1054           CLOSE_BRACE\r
1055           {\r
1056                 int a_flags = (int) $10;\r
1057 \r
1058                 bool do_get = (a_flags & 1) == 1;\r
1059                 bool do_set = (a_flags & 2) == 2;\r
1060 \r
1061                 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2, (Attributes) $1);\r
1062           }\r
1063         ;\r
1064 \r
1065 operator_declaration\r
1066         : opt_attributes opt_modifiers operator_declarator block\r
1067           {\r
1068                 OperatorDeclaration decl = (OperatorDeclaration) $3;\r
1069                 \r
1070                 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,\r
1071                                             decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1);\r
1072 \r
1073                 // Note again, checking is done in semantic analysis\r
1074                 current_container.AddOperator (op);\r
1075           }\r
1076         ;\r
1077 \r
1078 operator_declarator\r
1079         : type OPERATOR overloadable_operator \r
1080           OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
1081         {\r
1082                 CheckUnaryOperator ((Operator.OpType) $3);\r
1083 \r
1084                 $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6, null, null);\r
1085         }\r
1086         | type OPERATOR overloadable_operator\r
1087           OPEN_PARENS \r
1088                 type IDENTIFIER COMMA\r
1089                 type IDENTIFIER \r
1090           CLOSE_PARENS\r
1091         {\r
1092                CheckBinaryOperator ((Operator.OpType) $3);\r
1093                \r
1094                $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,\r
1095                                              (string) $8, (string) $9);\r
1096         }\r
1097         | conversion_operator_declarator\r
1098         ;\r
1099 \r
1100 overloadable_operator\r
1101 // Unary operators:\r
1102         : BANG   { $$ = Operator.OpType.Bang; }\r
1103         | TILDE  { $$ = Operator.OpType.Tilde; }  \r
1104         | OP_INC { $$ = Operator.OpType.Increment; }\r
1105         | OP_DEC { $$ = Operator.OpType.Decrement; }\r
1106         | TRUE   { $$ = Operator.OpType.True; }\r
1107         | FALSE  { $$ = Operator.OpType.False; }\r
1108 // Unary and binary:\r
1109         | PLUS { $$ = Operator.OpType.Plus; }\r
1110         | MINUS { $$ = Operator.OpType.Minus; }\r
1111 // Binary:\r
1112         | STAR { $$ = Operator.OpType.Star; }\r
1113         | DIV {  $$ = Operator.OpType.Div; }\r
1114         | PERCENT { $$ = Operator.OpType.Percent; }\r
1115         | BITWISE_AND { $$ = Operator.OpType.BitAnd; }\r
1116         | BITWISE_OR { $$ = Operator.OpType.BitOr; }\r
1117         | CARRET { $$ = Operator.OpType.Carret; }\r
1118         | OP_SHIFT_LEFT { $$ = Operator.OpType.ShiftLeft; }\r
1119         | OP_SHIFT_RIGHT { $$ = Operator.OpType.ShiftRight; }\r
1120         | OP_EQ { $$ = Operator.OpType.Eq; }\r
1121         | OP_NE { $$ = Operator.OpType.NotEq; }\r
1122         | OP_GT { $$ = Operator.OpType.GreaterThan; }\r
1123         | OP_LT { $$ = Operator.OpType.LesserThan; }\r
1124         | OP_GE { $$ = Operator.OpType.GreaterOrEq; }\r
1125         | OP_LE { $$ = Operator.OpType.LesserOrEq; }\r
1126         ;\r
1127 \r
1128 conversion_operator_declarator\r
1129         : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
1130           {\r
1131                 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,\r
1132                                               null, null);\r
1133           }\r
1134         | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
1135           {\r
1136                 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,\r
1137                                               null, null);\r
1138           }\r
1139         ;\r
1140 \r
1141 constructor_declaration\r
1142         : opt_attributes\r
1143           opt_modifiers\r
1144           constructor_declarator\r
1145           block\r
1146           { \r
1147                 Constructor c = (Constructor) $3;\r
1148                 c.Block = (Block) $4;\r
1149                 c.ModFlags = (int) $2;\r
1150 \r
1151                 if ((c.ModFlags & Modifiers.STATIC) != 0){\r
1152                         if ((c.ModFlags & Modifiers.Accessibility) != 0) {\r
1153                                 Location l = lexer.Location;\r
1154                                 rc.Report.Error (515, l, "Access modifiers are not allowed on static constructors");\r
1155                         }\r
1156                 }\r
1157                 CheckDef (current_container.AddConstructor (c), c.Name);\r
1158 \r
1159                 current_local_parameters = null;\r
1160           }\r
1161         ;\r
1162 \r
1163 constructor_declarator\r
1164         : IDENTIFIER \r
1165           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
1166           opt_constructor_initializer\r
1167           {\r
1168                 ConstructorInitializer i = null;\r
1169 \r
1170                 if ($5 == null)\r
1171                         i = new ConstructorBaseInitializer (null);\r
1172                 else \r
1173                         i = (ConstructorInitializer) $5;\r
1174 \r
1175                 $$ = new Constructor ((string) $1, (Parameters) $3, i);\r
1176         \r
1177                 current_local_parameters = (Parameters) $3;\r
1178           }\r
1179         ;\r
1180 \r
1181 opt_constructor_initializer\r
1182         : /* empty */                   { $$ = null; }\r
1183         | constructor_initializer\r
1184         ;\r
1185 \r
1186 constructor_initializer\r
1187         : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1188           {\r
1189                 $$ = new ConstructorBaseInitializer ((ArrayList) $4);\r
1190           }\r
1191         | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1192           {\r
1193                 $$ = new ConstructorThisInitializer ((ArrayList) $4);\r
1194           }\r
1195         ;\r
1196 \r
1197 destructor_declaration\r
1198         : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block\r
1199           {\r
1200                 Method d = new Method ("System.Void", 0, "Finalize", new Parameters (null, null), (Attributes) $1);\r
1201                   \r
1202                 d.Block = (Block) $6;\r
1203                 CheckDef (current_container.AddMethod (d), d.Name);\r
1204           }\r
1205         ;\r
1206 \r
1207 event_declaration\r
1208         : opt_attributes\r
1209           opt_modifiers\r
1210           EVENT type variable_declarators SEMICOLON\r
1211           {\r
1212                 foreach (VariableDeclaration var in (ArrayList) $5) {\r
1213 \r
1214                         // FIXME : Is this right ?\r
1215                         Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,\r
1216                                              (int) $2, null, null, (Attributes) $1);\r
1217 \r
1218                         CheckDef (current_container.AddEvent (e), e.Name);\r
1219                                        \r
1220                 }\r
1221           }\r
1222         | opt_attributes\r
1223           opt_modifiers\r
1224           EVENT type member_name \r
1225           OPEN_BRACE event_accessor_declarations CLOSE_BRACE\r
1226         {\r
1227                 DictionaryEntry pair = (DictionaryEntry) $7;\r
1228                 Block add_block = null;\r
1229                 Block rem_block = null;\r
1230 \r
1231                 if (pair.Key != null)\r
1232                         add_block = (Block) pair.Key;\r
1233                 if (pair.Value != null)\r
1234                         rem_block = (Block) pair.Value;\r
1235                 \r
1236                 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block, (Attributes) $1);\r
1237                 \r
1238                 CheckDef (current_container.AddEvent (e), e.Name);\r
1239         }\r
1240         ;\r
1241 \r
1242 event_accessor_declarations\r
1243         : add_accessor_declaration remove_accessor_declaration\r
1244         {\r
1245                 $$ = new DictionaryEntry ($1, $2);\r
1246         }\r
1247         | remove_accessor_declaration add_accessor_declaration\r
1248         {\r
1249                 $$ = new DictionaryEntry ($2, $1);\r
1250         }       \r
1251         ;\r
1252 \r
1253 add_accessor_declaration\r
1254         : opt_attributes ADD block\r
1255           {\r
1256                 $$ = $3;\r
1257           }\r
1258         ;\r
1259 \r
1260 remove_accessor_declaration\r
1261         : opt_attributes REMOVE block\r
1262         {\r
1263                 $$ = $3;\r
1264         }\r
1265         ;\r
1266 \r
1267 indexer_declaration\r
1268         : opt_attributes opt_modifiers indexer_declarator \r
1269           OPEN_BRACE \r
1270           {\r
1271                 IndexerDeclaration decl = (IndexerDeclaration) $3;\r
1272                   \r
1273                 lexer.properties = true;\r
1274                 parsing_indexer  = true;\r
1275                 \r
1276                 current_local_parameters = decl.param_list;\r
1277           }\r
1278           accessor_declarations \r
1279           {\r
1280                   lexer.properties = false;\r
1281                   parsing_indexer  = false;\r
1282           }\r
1283           CLOSE_BRACE\r
1284           { \r
1285                 // The signature is computed from the signature of the indexer.  Look\r
1286                 // at section 3.6 on the spec\r
1287 \r
1288                 Indexer indexer;\r
1289                 IndexerDeclaration decl = (IndexerDeclaration) $3;\r
1290                 DictionaryEntry pair = (DictionaryEntry) $6;\r
1291                 Block get_block = null;\r
1292                 Block set_block = null;\r
1293 \r
1294                 if (pair.Key != null)\r
1295                         get_block = (Block) pair.Key;\r
1296                 if (pair.Value != null)\r
1297                         set_block = (Block) pair.Value;\r
1298 \r
1299                 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,\r
1300                                        get_block, set_block, (Attributes) $1);\r
1301 \r
1302                 // Note that there is no equivalent of CheckDef for this case\r
1303                 // We shall handle this in semantic analysis\r
1304                 \r
1305                 current_container.AddIndexer (indexer);\r
1306                 \r
1307                 current_local_parameters = null;\r
1308           }\r
1309         ;\r
1310 \r
1311 indexer_declarator\r
1312         : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
1313           {\r
1314                 $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);\r
1315           }\r
1316         | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
1317           {\r
1318                 $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);\r
1319           }\r
1320         ;\r
1321 \r
1322 enum_declaration\r
1323         : opt_attributes\r
1324           opt_modifiers\r
1325           ENUM IDENTIFIER\r
1326           opt_enum_base\r
1327           enum_body\r
1328           opt_semicolon\r
1329           { \r
1330                 string name = (string) $4;\r
1331                 Enum e = new Enum ((string) $5, (int) $2, name, (Attributes) $1);\r
1332 \r
1333                 foreach (VariableDeclaration ev in (ArrayList) $6){\r
1334                         CheckDef (e.AddEnumMember (ev.identifier, \r
1335                                                    (Expression) ev.expression_or_array_initializer),\r
1336                                   ev.identifier);\r
1337                 }\r
1338 \r
1339                 CheckDef (current_container.AddEnum (e), name);\r
1340           }\r
1341         ;\r
1342 \r
1343 opt_enum_base\r
1344         : /* empty */                   { $$ = "System.Int32"; }\r
1345         | COLON integral_type           { $$ = $2;   }\r
1346         ;\r
1347 \r
1348 enum_body\r
1349         : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE\r
1350           {\r
1351                 $$ = $2;\r
1352           }\r
1353         ;\r
1354 \r
1355 opt_enum_member_declarations\r
1356         : /* empty */                   { $$ = new ArrayList (); }\r
1357         | enum_member_declarations opt_comma { $$ = $1; }\r
1358         ;\r
1359 \r
1360 enum_member_declarations\r
1361         : enum_member_declaration \r
1362           {\r
1363                 ArrayList l = new ArrayList ();\r
1364 \r
1365                 l.Add ($1);\r
1366                 $$ = l;\r
1367           }\r
1368         | enum_member_declarations COMMA enum_member_declaration\r
1369           {\r
1370                 ArrayList l = (ArrayList) $1;\r
1371 \r
1372                 l.Add ($3);\r
1373 \r
1374                 $$ = l;\r
1375           }\r
1376         ;\r
1377 \r
1378 enum_member_declaration\r
1379         : opt_attributes IDENTIFIER \r
1380           {\r
1381                 $$ = new VariableDeclaration ((string) $2, null);\r
1382           }\r
1383         | opt_attributes IDENTIFIER ASSIGN expression\r
1384           { \r
1385                 $$ = new VariableDeclaration ((string) $2, $4);\r
1386           }\r
1387         ;\r
1388 \r
1389 delegate_declaration\r
1390         : opt_attributes\r
1391           opt_modifiers\r
1392           DELEGATE type   \r
1393           IDENTIFIER OPEN_PARENS \r
1394           formal_parameter_list\r
1395           CLOSE_PARENS \r
1396           SEMICOLON\r
1397           {\r
1398                 Delegate del = new Delegate ((string) $4, (int) $2, (string) $5, (Parameters) $7, (Attributes) $1);\r
1399 \r
1400                 CheckDef (current_container.AddDelegate (del), del.Name);\r
1401           }     \r
1402         | opt_attributes\r
1403           opt_modifiers\r
1404           DELEGATE VOID   \r
1405           IDENTIFIER OPEN_PARENS \r
1406           formal_parameter_list\r
1407           CLOSE_PARENS \r
1408           SEMICOLON\r
1409           {\r
1410                 Delegate del = new Delegate (null, (int) $2, (string) $5, (Parameters) $7, (Attributes) $1);\r
1411 \r
1412                 CheckDef (current_container.AddDelegate (del), del.Name);\r
1413           }\r
1414         ;\r
1415 \r
1416 type_name\r
1417         : namespace_or_type_name\r
1418         ;\r
1419 \r
1420 namespace_or_type_name\r
1421         : qualified_identifier\r
1422         ;\r
1423 \r
1424 /* \r
1425  * Before you think of adding a return_type, notice that we have been\r
1426  * using two rules in the places where it matters (one rule using type\r
1427  * and another identical one that uses VOID as the return type).  This\r
1428  * gets rid of a shift/reduce couple\r
1429  */\r
1430 type\r
1431         : type_name {   /* class_type */\r
1432                 /* \r
1433                    This does interfaces, delegates, struct_types, class_types, \r
1434                    parent classes, and more! 4.2 \r
1435                  */\r
1436                 $$ = $1; \r
1437           }\r
1438         | builtin_types\r
1439         | array_type\r
1440         ;\r
1441 \r
1442 type_list\r
1443         : type\r
1444           {\r
1445                 ArrayList types = new ArrayList ();\r
1446 \r
1447                 types.Add ($1);\r
1448                 $$ = types;\r
1449           }\r
1450         | type_list COMMA type\r
1451           {\r
1452                 ArrayList types = (ArrayList) $1;\r
1453 \r
1454                 types.Add ($3);\r
1455                 $$ = types;\r
1456           }\r
1457         ;\r
1458 \r
1459 /*\r
1460  * replaces all the productions for isolating the various\r
1461  * simple types, but we need this to reuse it easily in local_variable_type\r
1462  */\r
1463 builtin_types\r
1464         : OBJECT        { $$ = "System.Object"; }\r
1465         | STRING        { $$ = "System.String"; }\r
1466         | BOOL          { $$ = "System.Boolean"; }\r
1467         | DECIMAL       { $$ = "System.Decimal"; }\r
1468         | FLOAT         { $$ = "System.Single"; }\r
1469         | DOUBLE        { $$ = "System.Double"; }\r
1470         | integral_type\r
1471         ;\r
1472 \r
1473 integral_type\r
1474         : SBYTE         { $$ = "System.SByte"; }\r
1475         | BYTE          { $$ = "System.Byte"; }\r
1476         | SHORT         { $$ = "System.Int16"; }\r
1477         | USHORT        { $$ = "System.UInt16"; }\r
1478         | INT           { $$ = "System.Int32"; }\r
1479         | UINT          { $$ = "System.UInt32"; }\r
1480         | LONG          { $$ = "System.Int64"; }\r
1481         | ULONG         { $$ = "System.UInt64"; }\r
1482         | CHAR          { $$ = "System.Char"; }\r
1483         ;\r
1484 \r
1485 interface_type\r
1486         : type_name\r
1487         ;\r
1488 \r
1489 array_type\r
1490         : type rank_specifiers\r
1491           {\r
1492                   $$ = (string) $1 + (string) $2;\r
1493           }\r
1494         ;\r
1495 \r
1496 //\r
1497 // Expressions, section 7.5\r
1498 //\r
1499 primary_expression\r
1500         : literal\r
1501           {\r
1502                 // 7.5.1: Literals\r
1503                 \r
1504           }\r
1505  \r
1506         | qualified_identifier\r
1507           {\r
1508                 string name = (string) $1;\r
1509 \r
1510                 $$ = null;\r
1511                 if (name.IndexOf ('.') == -1){\r
1512                         //\r
1513                         // we need to check against current_block not being null\r
1514                         // as `expression' is allowed in argument_lists, which \r
1515                         // do not exist inside a block.  \r
1516                         //\r
1517                         if (current_block != null){\r
1518                                 if (current_block.IsVariableDefined (name))\r
1519                                         $$ = new LocalVariableReference (current_block, name);\r
1520                         }\r
1521                         if (($$ == null) && (current_local_parameters != null)){\r
1522                                 int idx;\r
1523                                 Parameter par = current_local_parameters.GetParameterByName (name, out idx);\r
1524                                 if (par != null)\r
1525                                         $$ = new ParameterReference (current_local_parameters, idx, name);\r
1526                         }\r
1527                 }\r
1528                 if ($$ == null)\r
1529                         $$ = new SimpleName (name);\r
1530           }\r
1531         | parenthesized_expression\r
1532         | member_access\r
1533         | invocation_expression\r
1534         | element_access\r
1535         | this_access\r
1536         | base_access\r
1537         | post_increment_expression\r
1538         | post_decrement_expression\r
1539         | new_expression\r
1540         | typeof_expression\r
1541         | sizeof_expression\r
1542         | checked_expression\r
1543         | unchecked_expression\r
1544         ;\r
1545 \r
1546 literal\r
1547         : boolean_literal\r
1548         | integer_literal\r
1549         | real_literal\r
1550         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }\r
1551         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }\r
1552         | NULL                  { $$ = new NullLiteral (); }\r
1553         ;\r
1554 \r
1555 real_literal\r
1556         : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }\r
1557         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }\r
1558         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }\r
1559         ;\r
1560 \r
1561 integer_literal\r
1562         : LITERAL_INTEGER       { $$ = new IntLiteral ((Int32) lexer.Value); }\r
1563         ;\r
1564 \r
1565 boolean_literal\r
1566         : TRUE                  { $$ = new BoolLiteral (true); }\r
1567         | FALSE                 { $$ = new BoolLiteral (false); }\r
1568         ;\r
1569 \r
1570 parenthesized_expression\r
1571         : OPEN_PARENS expression CLOSE_PARENS\r
1572           { $$ = $2; }\r
1573         ;\r
1574 \r
1575 member_access\r
1576         : primary_expression DOT IDENTIFIER\r
1577           {\r
1578                 $$ = new MemberAccess ((Expression) $1, (string) $3);\r
1579           }\r
1580         | predefined_type DOT IDENTIFIER\r
1581           {\r
1582                 $$ = new BuiltinTypeAccess ((string) $1, (string) $3);\r
1583           }\r
1584         ;\r
1585 \r
1586 predefined_type\r
1587         : builtin_types\r
1588         ;\r
1589 \r
1590 invocation_expression\r
1591         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1592           {\r
1593                 // FIXME:\r
1594                 // if $1 is MethodGroup\r
1595                 //      $$ = new Call ($1, $3);\r
1596                 // else \r
1597                 //      $$ = new DelegateCall ($1, $3);\r
1598                 if ($1 == null) {\r
1599                         Location l = lexer.Location;\r
1600                         rc.Report.Error (1, l, "THIS IS CRAZY");\r
1601                 }\r
1602                 $$ = new Invocation ((Expression) $1, (ArrayList) $3);\r
1603           }\r
1604         ; \r
1605 \r
1606 opt_argument_list\r
1607         : /* empty */           { $$ = null; }\r
1608         | argument_list\r
1609         ;\r
1610 \r
1611 argument_list\r
1612         : argument              \r
1613           { \r
1614                 ArrayList list = new ArrayList ();\r
1615                 list.Add ($1);\r
1616                 $$ = list;\r
1617           }\r
1618         | argument_list COMMA argument\r
1619           {\r
1620                 ArrayList list = (ArrayList) $1;\r
1621                 list.Add ($3);\r
1622                 $$ = list;\r
1623           }\r
1624         ;\r
1625 \r
1626 argument\r
1627         : expression\r
1628           {\r
1629                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);\r
1630           }\r
1631         | REF variable_reference \r
1632           { \r
1633                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);\r
1634           }\r
1635         | OUT variable_reference \r
1636           { \r
1637                 $$ = new Argument ((Expression) $2, Argument.AType.Out);\r
1638           }\r
1639         ;\r
1640 \r
1641 variable_reference\r
1642         : expression { note ("section 5.4"); $$ = $1; }\r
1643         ;\r
1644 \r
1645 element_access\r
1646         : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET \r
1647           {\r
1648                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3);\r
1649           }\r
1650         ;\r
1651 \r
1652 expression_list\r
1653         : expression\r
1654           {\r
1655                 ArrayList list = new ArrayList ();\r
1656                 list.Add ($1);\r
1657                 $$ = list;\r
1658           }\r
1659         | expression_list COMMA expression\r
1660           {\r
1661                 ArrayList list = (ArrayList) $1;\r
1662                 list.Add ($3);\r
1663                 $$ = list;\r
1664           }\r
1665         ;\r
1666 \r
1667 this_access\r
1668         : THIS\r
1669           {\r
1670                 $$ = new This ();\r
1671           }\r
1672         ;\r
1673 \r
1674 base_access\r
1675         : BASE DOT IDENTIFIER\r
1676           {\r
1677                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);\r
1678           }\r
1679         | BASE OPEN_BRACKET expression_list CLOSE_BRACKET\r
1680           {\r
1681                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);\r
1682           }\r
1683         ;\r
1684 \r
1685 post_increment_expression\r
1686         : primary_expression OP_INC\r
1687           {\r
1688                 $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1);\r
1689           }\r
1690         ;\r
1691 \r
1692 post_decrement_expression\r
1693         : primary_expression OP_DEC\r
1694           {\r
1695                 $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1);\r
1696           }\r
1697         ;\r
1698 \r
1699 new_expression\r
1700         : object_or_delegate_creation_expression\r
1701         | array_creation_expression\r
1702         ;\r
1703 \r
1704 object_or_delegate_creation_expression\r
1705         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1706           {\r
1707                 $$ = new New ((string) $2, (ArrayList) $4);\r
1708           }\r
1709         ;\r
1710 \r
1711 array_creation_expression\r
1712         : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET \r
1713           opt_rank_specifier\r
1714           opt_array_initializer\r
1715           {\r
1716                 $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7);\r
1717           }\r
1718         ;\r
1719 \r
1720 opt_rank_specifier\r
1721         : /* empty */\r
1722           {\r
1723                   $$ = "";\r
1724           }\r
1725         | rank_specifiers\r
1726           {\r
1727                         $$ = $1;\r
1728           }\r
1729         ;\r
1730 \r
1731 rank_specifiers\r
1732         : rank_specifier\r
1733           {\r
1734                   $$ = $1;\r
1735           }\r
1736         | rank_specifier rank_specifiers\r
1737           {\r
1738                   $$ = (string) $1 + (string) $2;\r
1739           }             \r
1740         ;\r
1741 \r
1742 rank_specifier\r
1743         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
1744           {\r
1745                 $$ = "[" + (string) $2 + "]";\r
1746           }\r
1747         ;\r
1748 \r
1749 opt_dim_separators\r
1750         : /* empty */\r
1751           {\r
1752                 $$ = "";\r
1753           }\r
1754         | dim_separators\r
1755           {\r
1756                   $$ = $1;\r
1757           }               \r
1758         ;\r
1759 \r
1760 dim_separators\r
1761         : COMMA\r
1762           {\r
1763                 $$ = ",";\r
1764           }\r
1765         | dim_separators COMMA\r
1766           {\r
1767                 $$ =(string) $1 + ",";\r
1768           }\r
1769         ;\r
1770 \r
1771 opt_array_initializer\r
1772         : /* empty */\r
1773           {\r
1774                 $$ = null;\r
1775           }\r
1776         | array_initializer\r
1777           {\r
1778                 $$ = $1;\r
1779           }\r
1780         ;\r
1781 \r
1782 array_initializer\r
1783         : OPEN_BRACE CLOSE_BRACE\r
1784           {\r
1785                 ArrayList list = new ArrayList ();\r
1786                 $$ = list;\r
1787           }\r
1788         | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE\r
1789         {\r
1790                 $$ = (ArrayList) $2;\r
1791         }\r
1792         ;\r
1793 \r
1794 variable_initializer_list\r
1795         : variable_initializer\r
1796         {\r
1797                 ArrayList list = new ArrayList ();\r
1798                 list.Add ($1);\r
1799                 $$ = list;\r
1800         }\r
1801         | variable_initializer_list COMMA variable_initializer\r
1802         {\r
1803                 ArrayList list = (ArrayList) $1;\r
1804                 list.Add ($3);\r
1805                 $$ = list;\r
1806         }\r
1807         ;\r
1808 \r
1809 typeof_expression\r
1810         : TYPEOF OPEN_PARENS type CLOSE_PARENS\r
1811           {\r
1812                 $$ = new TypeOf ((string) $3);\r
1813           }\r
1814         ;\r
1815 \r
1816 sizeof_expression\r
1817         : SIZEOF OPEN_PARENS type CLOSE_PARENS { \r
1818                 $$ = new SizeOf ((string) $3);\r
1819 \r
1820                 note ("Verify type is unmanaged"); \r
1821                 note ("if (5.8) builtin, yield constant expression");\r
1822           }\r
1823         ;\r
1824 \r
1825 checked_expression\r
1826         : CHECKED OPEN_PARENS expression CLOSE_PARENS\r
1827           {\r
1828                 $$ = new CheckedExpr ((Expression) $3);\r
1829           }\r
1830         ;\r
1831 \r
1832 unchecked_expression\r
1833         : UNCHECKED OPEN_PARENS expression CLOSE_PARENS\r
1834           {\r
1835                 $$ = new UnCheckedExpr ((Expression) $3);\r
1836           }\r
1837         ;\r
1838 \r
1839 unary_expression\r
1840         : primary_expression\r
1841         | PLUS unary_expression         { \r
1842                 $$ = new Unary (Unary.Operator.Plus, (Expression) $2);\r
1843           } \r
1844         | MINUS unary_expression \r
1845           { \r
1846                 $$ = new Unary (Unary.Operator.Minus, (Expression) $2);\r
1847           }\r
1848         | BANG unary_expression \r
1849           {\r
1850                 $$ = new Unary (Unary.Operator.Negate, (Expression) $2);\r
1851           }\r
1852         | TILDE unary_expression\r
1853           {\r
1854                 $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2);\r
1855           }\r
1856         | STAR unary_expression\r
1857           {\r
1858                 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2);\r
1859           }\r
1860         | BITWISE_AND unary_expression\r
1861           {\r
1862                 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);\r
1863           }\r
1864         | OP_INC unary_expression \r
1865           {\r
1866                 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);\r
1867           }\r
1868         | OP_DEC unary_expression \r
1869           {\r
1870                 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);\r
1871           }\r
1872         | cast_expression \r
1873         /*\r
1874          we can not do cast expressions at this level,\r
1875          as there is an ambiguity.  Check "Cast Expressions" 7.6.8\r
1876          for the recipe to handle this.\r
1877          */\r
1878         ;\r
1879 \r
1880 pre_increment_expression\r
1881         : OP_INC unary_expression \r
1882           {\r
1883                 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);\r
1884           }\r
1885         ;\r
1886 \r
1887 pre_decrement_expression\r
1888         : OP_DEC unary_expression \r
1889           {\r
1890                 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);\r
1891           }\r
1892         ;\r
1893 \r
1894 cast_expression\r
1895         /* \r
1896          * FIXME: This is actually wrong, it should be `type' but that\r
1897          * introduces a lot of {shift,reduce}/reduces\r
1898          *\r
1899          * This is really really wrong.  We need to track down\r
1900          * the source of problems with QIs because expressions like:\r
1901          * foreach (string s in (string []) object) wont be parsed.\r
1902          */\r
1903         : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression\r
1904           {\r
1905                 $$ = new Cast ((string) $2, (Expression) $4);\r
1906           }\r
1907         | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression\r
1908           {\r
1909                 $$ = new Cast ((string) $2, (Expression) $4);\r
1910           }\r
1911         ;\r
1912 \r
1913 multiplicative_expression\r
1914         : unary_expression\r
1915         | multiplicative_expression STAR unary_expression\r
1916           {\r
1917                 $$ = new Binary (Binary.Operator.Multiply, \r
1918                                  (Expression) $1, (Expression) $3);\r
1919           }\r
1920         | multiplicative_expression DIV unary_expression\r
1921           {\r
1922                 $$ = new Binary (Binary.Operator.Divide, \r
1923                                  (Expression) $1, (Expression) $3);\r
1924           }\r
1925         | multiplicative_expression PERCENT unary_expression \r
1926           {\r
1927                 $$ = new Binary (Binary.Operator.Modulo, \r
1928                                  (Expression) $1, (Expression) $3);\r
1929           }\r
1930         ;\r
1931 \r
1932 additive_expression\r
1933         : multiplicative_expression\r
1934         | additive_expression PLUS multiplicative_expression \r
1935           {\r
1936                 $$ = new Binary (Binary.Operator.Add, \r
1937                                  (Expression) $1, (Expression) $3);\r
1938           }\r
1939         | additive_expression MINUS multiplicative_expression\r
1940           {\r
1941                 $$ = new Binary (Binary.Operator.Substract, \r
1942                                  (Expression) $1, (Expression) $3);\r
1943           }\r
1944         ;\r
1945 \r
1946 shift_expression\r
1947         : additive_expression\r
1948         | shift_expression OP_SHIFT_LEFT additive_expression\r
1949           {\r
1950                 $$ = new Binary (Binary.Operator.ShiftLeft, \r
1951                                  (Expression) $1, (Expression) $3);\r
1952           }\r
1953         | shift_expression OP_SHIFT_RIGHT additive_expression\r
1954           {\r
1955                 $$ = new Binary (Binary.Operator.ShiftRight, \r
1956                                  (Expression) $1, (Expression) $3);\r
1957           }\r
1958         ; \r
1959 \r
1960 relational_expression\r
1961         : shift_expression\r
1962         | relational_expression OP_LT shift_expression\r
1963           {\r
1964                 $$ = new Binary (Binary.Operator.LessThan, \r
1965                                  (Expression) $1, (Expression) $3);\r
1966           }\r
1967         | relational_expression OP_GT shift_expression\r
1968           {\r
1969                 $$ = new Binary (Binary.Operator.GreatherThan, \r
1970                                  (Expression) $1, (Expression) $3);\r
1971           }\r
1972         | relational_expression OP_LE shift_expression\r
1973           {\r
1974                 $$ = new Binary (Binary.Operator.LessOrEqual, \r
1975                                  (Expression) $1, (Expression) $3);\r
1976           }\r
1977         | relational_expression OP_GE shift_expression\r
1978           {\r
1979                 $$ = new Binary (Binary.Operator.GreatherOrEqual, \r
1980                                  (Expression) $1, (Expression) $3);\r
1981           }\r
1982         | relational_expression IS type\r
1983           {\r
1984                 $$ = new Probe (Probe.Operator.Is, \r
1985                                  (Expression) $1, (string) $3);\r
1986           }\r
1987         | relational_expression AS type\r
1988           {\r
1989                 $$ = new Probe (Probe.Operator.As, \r
1990                                  (Expression) $1, (string) $3);\r
1991           }\r
1992         ;\r
1993 \r
1994 equality_expression\r
1995         : relational_expression\r
1996         | equality_expression OP_EQ relational_expression\r
1997           {\r
1998                 $$ = new Binary (Binary.Operator.Equal, \r
1999                                  (Expression) $1, (Expression) $3);\r
2000           }\r
2001         | equality_expression OP_NE relational_expression\r
2002           {\r
2003                 $$ = new Binary (Binary.Operator.NotEqual, \r
2004                                  (Expression) $1, (Expression) $3);\r
2005           }\r
2006         ; \r
2007 \r
2008 and_expression\r
2009         : equality_expression\r
2010         | and_expression BITWISE_AND equality_expression\r
2011           {\r
2012                 $$ = new Binary (Binary.Operator.BitwiseAnd, \r
2013                                  (Expression) $1, (Expression) $3);\r
2014           }\r
2015         ;\r
2016 \r
2017 exclusive_or_expression\r
2018         : and_expression\r
2019         | exclusive_or_expression CARRET and_expression\r
2020           {\r
2021                 $$ = new Binary (Binary.Operator.ExclusiveOr, \r
2022                                  (Expression) $1, (Expression) $3);\r
2023           }\r
2024         ;\r
2025 \r
2026 inclusive_or_expression\r
2027         : exclusive_or_expression\r
2028         | inclusive_or_expression BITWISE_OR exclusive_or_expression\r
2029           {\r
2030                 $$ = new Binary (Binary.Operator.BitwiseOr, \r
2031                                  (Expression) $1, (Expression) $3);\r
2032           }\r
2033         ;\r
2034 \r
2035 conditional_and_expression\r
2036         : inclusive_or_expression\r
2037         | conditional_and_expression OP_AND inclusive_or_expression\r
2038           {\r
2039                 $$ = new Binary (Binary.Operator.LogicalAnd, \r
2040                                  (Expression) $1, (Expression) $3);\r
2041           }\r
2042         ;\r
2043 \r
2044 conditional_or_expression\r
2045         : conditional_and_expression\r
2046         | conditional_or_expression OP_OR conditional_and_expression\r
2047           {\r
2048                 $$ = new Binary (Binary.Operator.LogicalOr, \r
2049                                  (Expression) $1, (Expression) $3);\r
2050           }\r
2051         ;\r
2052 \r
2053 conditional_expression\r
2054         : conditional_or_expression\r
2055         | conditional_or_expression INTERR expression COLON expression \r
2056           {\r
2057                 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);\r
2058           }\r
2059         ;\r
2060 \r
2061 assignment_expression\r
2062         : unary_expression ASSIGN expression\r
2063           {\r
2064                 $$ = new Assign ((Expression) $1, (Expression) $3);\r
2065           }\r
2066         | unary_expression OP_MULT_ASSIGN expression\r
2067           {\r
2068                 $$ = new Assign ((Expression) $1,\r
2069                                  new Binary (Binary.Operator.Multiply, \r
2070                                              (Expression) $1,\r
2071                                              (Expression) $3));\r
2072           }\r
2073         | unary_expression OP_DIV_ASSIGN expression\r
2074           {\r
2075                 $$ = new Assign ((Expression) $1,\r
2076                                  new Binary (Binary.Operator.Divide, \r
2077                                              (Expression) $1,\r
2078                                              (Expression) $3));\r
2079           }\r
2080         | unary_expression OP_MOD_ASSIGN expression\r
2081           {\r
2082                 $$ = new Assign ((Expression) $1,\r
2083                                  new Binary (Binary.Operator.Modulo, \r
2084                                              (Expression) $1,\r
2085                                              (Expression) $3));\r
2086           }\r
2087         | unary_expression OP_ADD_ASSIGN expression\r
2088           {\r
2089                 $$ = new Assign ((Expression) $1,\r
2090                                  new Binary (Binary.Operator.Add, \r
2091                                              (Expression) $1,\r
2092                                              (Expression) $3));\r
2093           }\r
2094         | unary_expression OP_SUB_ASSIGN expression\r
2095           {\r
2096                 $$ = new Assign ((Expression) $1,\r
2097                                  new Binary (Binary.Operator.Substract, \r
2098                                              (Expression) $1,\r
2099                                              (Expression) $3));\r
2100           }\r
2101         | unary_expression OP_SHIFT_LEFT_ASSIGN expression\r
2102           {\r
2103                 $$ = new Assign ((Expression) $1,\r
2104                                  new Binary (Binary.Operator.ShiftLeft, \r
2105                                              (Expression) $1,\r
2106                                              (Expression) $3));\r
2107           }\r
2108         | unary_expression OP_SHIFT_RIGHT_ASSIGN expression\r
2109           {\r
2110                 $$ = new Assign ((Expression) $1,\r
2111                                  new Binary (Binary.Operator.ShiftRight, \r
2112                                              (Expression) $1,\r
2113                                              (Expression) $3));\r
2114           }\r
2115         | unary_expression OP_AND_ASSIGN expression\r
2116           {\r
2117                 $$ = new Assign ((Expression) $1,\r
2118                                  new Binary (Binary.Operator.BitwiseAnd, \r
2119                                              (Expression) $1,\r
2120                                              (Expression) $3));\r
2121           }\r
2122         | unary_expression OP_OR_ASSIGN expression\r
2123           {\r
2124                 $$ = new Assign ((Expression) $1,\r
2125                                  new Binary (Binary.Operator.BitwiseOr, \r
2126                                              (Expression) $1,\r
2127                                              (Expression) $3));\r
2128           }\r
2129         | unary_expression OP_XOR_ASSIGN expression\r
2130           {\r
2131                 $$ = new Assign ((Expression) $1,\r
2132                                  new Binary (Binary.Operator.ExclusiveOr, \r
2133                                              (Expression) $1,\r
2134                                              (Expression) $3));\r
2135           }\r
2136         ;\r
2137 \r
2138 expression\r
2139         : conditional_expression\r
2140         | assignment_expression\r
2141         ;\r
2142 \r
2143 constant_expression\r
2144         : expression\r
2145         ;\r
2146 \r
2147 boolean_expression\r
2148         : expression    { CheckBoolean ((Expression) $1); $$ = $1; } \r
2149         ;\r
2150 \r
2151 //\r
2152 // 10 classes\r
2153 //\r
2154 class_declaration\r
2155         : opt_attributes\r
2156           opt_modifiers\r
2157           CLASS IDENTIFIER\r
2158           {\r
2159                 Class new_class;\r
2160                 string full_class_name = MakeName ((string) $4);\r
2161 \r
2162                 new_class = new Class (rc, current_container, full_class_name, (int) $2, (Attributes) $1);\r
2163                 current_container = new_class;\r
2164                 current_container.Namespace = current_namespace;\r
2165                 tree.RecordClass (full_class_name, new_class);\r
2166           }\r
2167           opt_class_base\r
2168           class_body \r
2169           opt_semicolon \r
2170           {\r
2171                 Class new_class = (Class) current_container;\r
2172 \r
2173                 if ($6 != null)\r
2174                         new_class.Bases = (ArrayList) $6;\r
2175 \r
2176                 current_container = current_container.Parent;\r
2177                 CheckDef (current_container.AddClass (new_class), new_class.Name);\r
2178 \r
2179                 $$ = new_class;\r
2180           }\r
2181         ;       \r
2182 \r
2183 opt_modifiers\r
2184         : /* empty */           { $$ = (int) 0; }\r
2185         | modifiers\r
2186         ;\r
2187 \r
2188 modifiers\r
2189         : modifier\r
2190         | modifiers modifier\r
2191           { \r
2192                 int m1 = (int) $1;\r
2193                 int m2 = (int) $2;\r
2194 \r
2195                 if ((m1 & m2) != 0) {\r
2196                         Location l = lexer.Location;\r
2197                         rc.Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");\r
2198                 }\r
2199                 $$ = (int) (m1 | m2);\r
2200           }\r
2201         ;\r
2202 \r
2203 modifier\r
2204         : NEW                   { $$ = Modifiers.NEW; }\r
2205         | PUBLIC                { $$ = Modifiers.PUBLIC; }\r
2206         | PROTECTED             { $$ = Modifiers.PROTECTED; }\r
2207         | INTERNAL              { $$ = Modifiers.INTERNAL; }\r
2208         | PRIVATE               { $$ = Modifiers.PRIVATE; }\r
2209         | ABSTRACT              { $$ = Modifiers.ABSTRACT; }\r
2210         | SEALED                { $$ = Modifiers.SEALED; }\r
2211         | STATIC                { $$ = Modifiers.STATIC; }\r
2212         | READONLY              { $$ = Modifiers.READONLY; }\r
2213         | VIRTUAL               { $$ = Modifiers.VIRTUAL; }\r
2214         | OVERRIDE              { $$ = Modifiers.OVERRIDE; }\r
2215         | EXTERN                { $$ = Modifiers.EXTERN; }\r
2216         ;\r
2217 \r
2218 opt_class_base\r
2219         : /* empty */           { $$ = null; }\r
2220         | class_base            { $$ = $1;   }\r
2221         ;\r
2222 \r
2223 class_base\r
2224         : COLON type_list { $$ = $2; }\r
2225         ;\r
2226 \r
2227 //\r
2228 // Statements (8.2)\r
2229 //\r
2230 \r
2231 //\r
2232 // A block is "contained" on the following places:\r
2233 //      method_body\r
2234 //      property_declaration as part of the accessor body (get/set)\r
2235 //      operator_declaration\r
2236 //      constructor_declaration\r
2237 //      destructor_declaration\r
2238 //      event_declaration as part of add_accessor_declaration or remove_accessor_declaration\r
2239 //      \r
2240 block\r
2241         : OPEN_BRACE \r
2242           {\r
2243                 current_block = new Block (current_block);\r
2244           } \r
2245           opt_statement_list CLOSE_BRACE \r
2246           { \r
2247                 while (current_block.Implicit)\r
2248                         current_block = current_block.Parent;\r
2249                 $$ = current_block;\r
2250                 current_block = current_block.Parent;\r
2251           }\r
2252         ;\r
2253 \r
2254 opt_statement_list\r
2255         : /* empty */\r
2256         | statement_list \r
2257         ;\r
2258 \r
2259 statement_list\r
2260         : statement\r
2261         | statement_list statement\r
2262         ;\r
2263 \r
2264 statement\r
2265         : declaration_statement\r
2266           {\r
2267                 if ((Block) $1 != current_block){\r
2268                         current_block.AddStatement ((Statement) $1);\r
2269                         current_block = (Block) $1;\r
2270                 }\r
2271           }\r
2272         | embedded_statement\r
2273           {\r
2274                 current_block.AddStatement ((Statement) $1);\r
2275           }\r
2276         | labeled_statement \r
2277           {\r
2278                 current_block.AddStatement ((Statement) $1);\r
2279           }\r
2280         ;\r
2281 \r
2282 embedded_statement\r
2283         : block\r
2284         | empty_statement\r
2285         | expression_statement\r
2286         | selection_statement\r
2287         | iteration_statement\r
2288         | jump_statement                  \r
2289         | try_statement\r
2290         | checked_statement\r
2291         | unchecked_statement\r
2292         | lock_statement\r
2293         | using_statement\r
2294         ;\r
2295 \r
2296 empty_statement\r
2297         : SEMICOLON\r
2298           {\r
2299                   $$ = new EmptyStatement ();\r
2300           }\r
2301         ;\r
2302 \r
2303 labeled_statement\r
2304         : IDENTIFIER COLON statement\r
2305           {\r
2306                 string lab = (String) $1;\r
2307                 Block block;\r
2308 \r
2309                 block = new Block (current_block, lab);\r
2310                 block.AddStatement ((Statement) $3);\r
2311                 $$ = block;\r
2312 \r
2313                 if (!current_block.AddLabel (lab, block)){\r
2314                         Location l = lexer.Location;\r
2315                         rc.Report.Error (140, l, "The label '" + lab + "' is a duplicate");\r
2316                         $$ = $3;\r
2317                 }       \r
2318           }\r
2319         ;\r
2320 \r
2321 declaration_statement\r
2322         : local_variable_declaration SEMICOLON          // done\r
2323         | local_constant_declaration SEMICOLON          // finishme\r
2324         ;\r
2325 \r
2326 /* \r
2327  * The following is from Rhys' grammar:\r
2328  * > Types in local variable declarations must be recognized as \r
2329  * > expressions to prevent reduce/reduce errors in the grammar.\r
2330  * > The expressions are converted into types during semantic analysis.\r
2331  */\r
2332 local_variable_type\r
2333         : primary_expression type_suffixes\r
2334           { \r
2335                 // FIXME: Do something smart here regarding the composition of the type.\r
2336 \r
2337                 // Ok, the above "primary_expression" is there to get rid of\r
2338                 // both reduce/reduce and shift/reduces in the grammar, it should\r
2339                 // really just be "type_name".  If you use type_name, a reduce/reduce\r
2340                 // creeps up.  If you use qualified_identifier (which is all we need\r
2341                 // really) two shift/reduces appear.\r
2342                 // \r
2343                 // So, instead we do a super trick: we just allow ($1) to be a \r
2344                 // SimpleName Expression.\r
2345                 //\r
2346                 if (((Expression) $1) is SimpleName)\r
2347                         $$ = ((SimpleName) $1).Name;\r
2348                 else {\r
2349                         Location l = lexer.Location;\r
2350                         rc.Report.Error (-1, l, "Invalid Type definition");\r
2351                         $$ = "System.Object";\r
2352                 }\r
2353           }\r
2354         | builtin_types type_suffixes\r
2355           {\r
2356                 $$ = (string) $1 + (string) $2;\r
2357           }\r
2358         ;\r
2359 \r
2360 // FIXME : How can the type of a local variable be void ? I don't quite see ;-)\r
2361 //          | VOID \r
2362 //        {\r
2363 //              // FIXME: this is a string that represents the type\r
2364 //              // Figure out something to make this work.\r
2365 //              $$ = "void";\r
2366 //        }\r
2367 //      ;\r
2368 \r
2369 type_suffixes\r
2370         : /* empty */\r
2371           {\r
2372                 $$ = "";\r
2373           }\r
2374         | type_suffix_list\r
2375         ;\r
2376 \r
2377 type_suffix_list \r
2378         : type_suffix\r
2379         | type_suffix_list type_suffix\r
2380           {\r
2381                 $$ = (string) $1 + (string) $2;\r
2382           }\r
2383         ;\r
2384 \r
2385 type_suffix\r
2386         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
2387           {\r
2388                 $$ = "[" + (string) $2 + "]";\r
2389           }\r
2390         ;\r
2391 \r
2392 local_variable_declaration\r
2393         : local_variable_type variable_declarators\r
2394           {\r
2395                 $$ = declare_local_variables ((string) $1, (ArrayList) $2);\r
2396           }\r
2397         ;\r
2398 \r
2399 local_constant_declaration\r
2400         : CONST type constant_declarator\r
2401                 // finishme     \r
2402         ;\r
2403 \r
2404 expression_statement\r
2405         : statement_expression SEMICOLON\r
2406           {\r
2407                 $$ = $1;\r
2408           }\r
2409         ;\r
2410 \r
2411         //\r
2412         // We have to do the wrapping here and not in the case above,\r
2413         // because statement_expression is used for example in for_statement\r
2414         //\r
2415 statement_expression\r
2416         : invocation_expression         { $$ = new StatementExpression ((Expression) $1); }\r
2417         | object_creation_expression    { $$ = new StatementExpression ((Expression) $1); }\r
2418         | assignment_expression         { $$ = new StatementExpression ((Expression) $1); }\r
2419         | post_increment_expression     { $$ = new StatementExpression ((Expression) $1); }\r
2420         | post_decrement_expression     { $$ = new StatementExpression ((Expression) $1); }\r
2421         | pre_increment_expression      { $$ = new StatementExpression ((Expression) $1); }\r
2422         | pre_decrement_expression      { $$ = new StatementExpression ((Expression) $1); }\r
2423         ;\r
2424 \r
2425 object_creation_expression\r
2426         : object_or_delegate_creation_expression\r
2427           { note ("complain if this is a delegate maybe?"); } \r
2428         ;\r
2429 \r
2430 selection_statement\r
2431         : if_statement\r
2432         | switch_statement\r
2433         ; \r
2434 \r
2435 if_statement\r
2436         : IF OPEN_PARENS boolean_expression CLOSE_PARENS \r
2437           embedded_statement\r
2438           { \r
2439                 $$ = new If ((Expression) $3, (Statement) $5);\r
2440           }\r
2441         | IF OPEN_PARENS boolean_expression CLOSE_PARENS\r
2442           embedded_statement ELSE embedded_statement\r
2443           {\r
2444                 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);\r
2445           }\r
2446         ;\r
2447 \r
2448 switch_statement\r
2449         : SWITCH OPEN_PARENS expression CLOSE_PARENS \r
2450           switch_block\r
2451           {\r
2452                 $$ = new Switch ((Expression) $3, (ArrayList) $5);\r
2453           }\r
2454         ;\r
2455 \r
2456 switch_block\r
2457         : OPEN_BRACE\r
2458           opt_switch_sections\r
2459           CLOSE_BRACE\r
2460           {\r
2461                 $$ = $2;\r
2462           }\r
2463         ;\r
2464 \r
2465 opt_switch_sections\r
2466         : /* empty */           { $$ = new ArrayList (); }\r
2467         | switch_sections\r
2468         ;\r
2469 \r
2470 switch_sections\r
2471         : switch_section \r
2472           {\r
2473                 ArrayList sections = new ArrayList ();\r
2474 \r
2475                 sections.Add ($1);\r
2476                 $$ = sections;\r
2477           }\r
2478         | switch_sections switch_section\r
2479           {\r
2480                 ArrayList sections = (ArrayList) $1;\r
2481 \r
2482                 sections.Add ($2);\r
2483                 $$ = sections;\r
2484           }\r
2485         ;\r
2486 \r
2487 switch_section\r
2488         : switch_labels\r
2489           {\r
2490                 current_block = new Block (current_block);\r
2491           }\r
2492           statement_list \r
2493           {\r
2494                 while (current_block.Implicit)\r
2495                         current_block = current_block.Parent;\r
2496                 $$ = new SwitchSection ((ArrayList) $1, current_block);\r
2497                 current_block = current_block.Parent;\r
2498           }\r
2499         ;\r
2500 \r
2501 switch_labels\r
2502         : switch_label \r
2503           {\r
2504                 ArrayList labels = new ArrayList ();\r
2505 \r
2506                 labels.Add ($1);\r
2507                 $$ = labels;\r
2508           }\r
2509         | switch_labels switch_label \r
2510           {\r
2511                 ArrayList labels = (ArrayList) ($1);\r
2512                 labels.Add ($2);\r
2513 \r
2514                 $$ = labels;\r
2515           }\r
2516         ;\r
2517 \r
2518 switch_label\r
2519         : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2); }\r
2520         | DEFAULT COLON                         { $$ = new SwitchLabel (null); }\r
2521         ;\r
2522 \r
2523 iteration_statement\r
2524         : while_statement\r
2525         | do_statement\r
2526         | for_statement\r
2527         | foreach_statement\r
2528         ;\r
2529 \r
2530 while_statement\r
2531         : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement\r
2532         {\r
2533                 $$ = new While ((Expression) $3, (Statement) $5);\r
2534         }\r
2535         ;\r
2536 \r
2537 do_statement\r
2538         : DO embedded_statement \r
2539           WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON\r
2540           {\r
2541                 $$ = new Do ((Statement) $2, (Expression) $5);\r
2542           }\r
2543         ;\r
2544 \r
2545 for_statement\r
2546         : FOR OPEN_PARENS \r
2547           opt_for_initializer SEMICOLON\r
2548           opt_for_condition SEMICOLON\r
2549           opt_for_iterator CLOSE_PARENS \r
2550           embedded_statement\r
2551           {\r
2552                 $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);\r
2553           }\r
2554         ;\r
2555 \r
2556 opt_for_initializer\r
2557         : /* empty */           { $$ = new EmptyStatement (); }\r
2558         | for_initializer       \r
2559         ;\r
2560 \r
2561 for_initializer\r
2562         : local_variable_declaration\r
2563         | statement_expression_list\r
2564         ;\r
2565 \r
2566 opt_for_condition\r
2567         : /* empty */           { $$ = new BoolLiteral (true); }\r
2568         | boolean_expression\r
2569         ;\r
2570 \r
2571 opt_for_iterator\r
2572         : /* empty */           { $$ = new EmptyStatement (); }\r
2573         | for_iterator\r
2574         ;\r
2575 \r
2576 for_iterator\r
2577         : statement_expression_list\r
2578         ;\r
2579 \r
2580 statement_expression_list\r
2581         : statement_expression  \r
2582           {\r
2583                 Block b = new Block (null, true);\r
2584 \r
2585                 b.AddStatement ((Statement) $1);\r
2586                 $$ = b;\r
2587           }\r
2588         | statement_expression_list COMMA statement_expression\r
2589           {\r
2590                 Block b = (Block) $1;\r
2591 \r
2592                 b.AddStatement ((Statement) $3);\r
2593                 $$ = $1;\r
2594           }\r
2595         ;\r
2596 \r
2597 foreach_statement\r
2598         : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS \r
2599           embedded_statement\r
2600           {\r
2601                 string temp_id = current_block.MakeInternalID ();\r
2602                 Expression assign_e, ma;\r
2603                 Statement getcurrent;\r
2604                 Block foreach_block, child_block;\r
2605 \r
2606                 foreach_block = new Block (current_block, true);\r
2607 \r
2608                 foreach_block.AddVariable ("System.IEnumerator", temp_id);\r
2609                 foreach_block.AddVariable ((string) $3, (string) $4);\r
2610                 assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id), \r
2611                                        new Invocation (\r
2612                                                 new MemberAccess ((Expression) $6, "GetEnumerator"), null));\r
2613                 current_block.AddStatement (new StatementExpression (assign_e));\r
2614                 ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");\r
2615                 child_block = new Block (current_block);\r
2616 \r
2617                 getcurrent = new StatementExpression (\r
2618                         new Assign (\r
2619                                 new LocalVariableReference (foreach_block, (string) $4),\r
2620                                 new Cast (\r
2621                                         (string) $3, \r
2622                                         new MemberAccess (\r
2623                                                 new LocalVariableReference (foreach_block, temp_id), "Current"))));\r
2624 \r
2625                 child_block.AddStatement (getcurrent);\r
2626                 child_block.AddStatement ((Statement) $8);\r
2627                 foreach_block.AddStatement (new While (ma, (Statement) child_block));\r
2628 \r
2629                 $$ = foreach_block;\r
2630           }\r
2631         ;\r
2632 \r
2633 jump_statement\r
2634         : break_statement\r
2635         | continue_statement\r
2636         | goto_statement\r
2637         | return_statement\r
2638         | throw_statement\r
2639         ;\r
2640 \r
2641 break_statement\r
2642         : BREAK SEMICOLON\r
2643           {\r
2644                 $$ = new Break ();\r
2645           }\r
2646         ;\r
2647 \r
2648 continue_statement\r
2649         : CONTINUE SEMICOLON\r
2650           {\r
2651                 $$ = new Continue ();\r
2652           }\r
2653         ;\r
2654 \r
2655 goto_statement\r
2656         : GOTO IDENTIFIER SEMICOLON \r
2657           {\r
2658                 $$ = new Goto ((string) $2);\r
2659           }\r
2660         | GOTO CASE constant_expression SEMICOLON\r
2661         | GOTO DEFAULT SEMICOLON \r
2662         ; \r
2663 \r
2664 return_statement\r
2665         : RETURN opt_expression SEMICOLON\r
2666           {\r
2667                 $$ = new Return ((Expression) $2);\r
2668           }\r
2669         ;\r
2670 \r
2671 throw_statement\r
2672         : THROW opt_expression SEMICOLON\r
2673           {\r
2674                 $$ = new Throw ((Expression) $2);\r
2675           }\r
2676         ;\r
2677 \r
2678 opt_expression\r
2679         : /* empty */\r
2680         | expression\r
2681         ;\r
2682 \r
2683 try_statement\r
2684         : TRY block catch_clauses \r
2685         {\r
2686                 Catch g = null;\r
2687                 ArrayList s = new ArrayList ();\r
2688                 \r
2689                 foreach (Catch cc in (ArrayList) $3) {\r
2690                         if (cc.Type == null)\r
2691                                 g = cc;\r
2692                         else\r
2693                                 s.Add (cc);\r
2694                 }\r
2695 \r
2696                 // Now s contains the list of specific catch clauses\r
2697                 // and g contains the general one.\r
2698                 \r
2699                 $$ = new Try ((Block) $2, s, g, null);\r
2700         }\r
2701         | TRY block opt_catch_clauses FINALLY block\r
2702           {\r
2703                 Catch g = null;\r
2704                 ArrayList s = new ArrayList ();\r
2705                 \r
2706                 foreach (Catch cc in (ArrayList) $3) {\r
2707                         if (cc.Type == null)\r
2708                                 g = cc;\r
2709                         else\r
2710                                 s.Add (cc);\r
2711                 }\r
2712 \r
2713                 $$ = new Try ((Block) $2, s, g, (Block) $5);\r
2714           }\r
2715         ;\r
2716 \r
2717 opt_catch_clauses\r
2718         : /* empty */  { $$ = null; }\r
2719         | catch_clauses\r
2720         ;\r
2721 \r
2722 catch_clauses\r
2723         : catch_clause \r
2724           {\r
2725                 ArrayList l = new ArrayList ();\r
2726 \r
2727                 l.Add ($1);\r
2728                 $$ = l;\r
2729           }\r
2730         | catch_clauses catch_clause\r
2731           {\r
2732                 ArrayList l = (ArrayList) $1;\r
2733 \r
2734                 l.Add ($2);\r
2735                 $$ = l;\r
2736           }\r
2737         ;\r
2738 \r
2739 opt_identifier\r
2740         : /* empty */   { $$ = null; }\r
2741         | IDENTIFIER\r
2742         ;\r
2743 \r
2744 catch_clause \r
2745         : CATCH opt_catch_args block\r
2746         {\r
2747                 string type = null;\r
2748                 string id = null;\r
2749                 \r
2750                 if ($2 != null) {\r
2751                         DictionaryEntry cc = (DictionaryEntry) $2;\r
2752                         type = (string) cc.Key;\r
2753                         id   = (string) cc.Value;\r
2754                 }\r
2755 \r
2756                 $$ = new Catch (type, id, (Block) $3);\r
2757         }\r
2758         ;\r
2759 \r
2760 opt_catch_args\r
2761         : /* empty */ { $$ = null; }\r
2762         | catch_args\r
2763         ;         \r
2764 \r
2765 catch_args \r
2766         : OPEN_PARENS type opt_identifier CLOSE_PARENS \r
2767         {\r
2768                 $$ = new DictionaryEntry ($2, $3);\r
2769         }\r
2770         ;\r
2771 \r
2772 checked_statement\r
2773         : CHECKED block\r
2774           {\r
2775                 $$ = new Checked ((Block) $2);\r
2776           }\r
2777         ;\r
2778 \r
2779 unchecked_statement\r
2780         : UNCHECKED block\r
2781           {\r
2782                 $$ = new Unchecked ((Block) $2);\r
2783           }\r
2784         ;\r
2785 \r
2786 lock_statement\r
2787         : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement\r
2788           {\r
2789                 $$ = new Lock ((Expression) $3, (Statement) $5);\r
2790           }\r
2791         ;\r
2792 \r
2793 using_statement\r
2794         : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement\r
2795           // finishme\r
2796         ; \r
2797 \r
2798 resource_acquisition\r
2799         : local_variable_declaration\r
2800           expression\r
2801           // finishme\r
2802         ;\r
2803 \r
2804 %%\r
2805 \r
2806 // <summary>\r
2807 //   A class used to pass around variable declarations and constants\r
2808 // </summary>\r
2809 public class VariableDeclaration {\r
2810         public string identifier;\r
2811         public object expression_or_array_initializer;\r
2812 \r
2813         public VariableDeclaration (string id, object eoai){\r
2814                 this.identifier = id;\r
2815                 this.expression_or_array_initializer = eoai;\r
2816         }\r
2817 }\r
2818 \r
2819 // <summary>\r
2820 //   A class used to hold info about an indexer declarator\r
2821 // </summary>\r
2822 \r
2823 public class IndexerDeclaration {\r
2824         public string type;\r
2825         public string interface_type;\r
2826         public Parameters param_list;\r
2827 \r
2828         public IndexerDeclaration (string type, string interface_type, Parameters param_list)\r
2829         {\r
2830                 this.type = type;\r
2831                 this.interface_type = interface_type;\r
2832                 this.param_list = param_list;\r
2833         }\r
2834 }\r
2835 \r
2836 // <summary>\r
2837 //  A class used to hold info about an operator declarator\r
2838 // </summary>\r
2839 \r
2840 public class OperatorDeclaration {\r
2841         public Operator.OpType optype;\r
2842         public string ret_type;\r
2843         public string arg1type;\r
2844         public string arg1name;\r
2845         public string arg2type;\r
2846         public string arg2name;\r
2847 \r
2848         public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,\r
2849                                     string arg2type, string arg2name)\r
2850         {\r
2851                 optype = op;\r
2852                 this.ret_type = ret_type;\r
2853                 this.arg1type = arg1type;\r
2854                 this.arg1name = arg1name;\r
2855                 this.arg2type = arg2type;\r
2856                 this.arg2name = arg2name;\r
2857         }\r
2858 \r
2859 }\r
2860 \r
2861 // <summary>\r
2862 //   Given the @class_name name, it creates a fully qualified name\r
2863 //   based on the containing declaration space\r
2864 // </summary>\r
2865 string \r
2866 MakeName (string class_name)\r
2867 {\r
2868         string ns = current_namespace.Name;\r
2869         string container_name = current_container.Name;\r
2870 \r
2871         if (container_name == ""){\r
2872                 if (ns != "")\r
2873                         return ns + "." + class_name;\r
2874                 else\r
2875                         return class_name;\r
2876         } else\r
2877                 return container_name + "." + class_name;\r
2878 }\r
2879 \r
2880 // <summary>\r
2881 //   Used to report back to the user the result of a declaration\r
2882 //   in the current declaration space\r
2883 // </summary>\r
2884 void \r
2885 CheckDef (DeclSpace.AdditionResult result, string name)\r
2886 {\r
2887         if (result == DeclSpace.AdditionResult.Success)\r
2888                 return;\r
2889 \r
2890         Location l = lexer.Location;\r
2891         \r
2892         switch (result){\r
2893         case DeclSpace.AdditionResult.NameExists:\r
2894                 rc.Report.Error (102, l, "The namespace `" + current_container.Name + \r
2895                                  "' already contains a definition for `"+\r
2896                                  name + "'");\r
2897                 break;\r
2898 \r
2899 \r
2900 //      NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:\r
2901 //\r
2902 //      case DeclSpace.AdditionResult.MethodDuplicated:\r
2903 //              error (111, "Class `"+current_container.Name+\r
2904 //                          "' already defines a member called '" + \r
2905 //                          name + "' with the same parameter types");\r
2906 //              break;\r
2907 \r
2908         case DeclSpace.AdditionResult.EnclosingClash:\r
2909                 rc.Report.Error (542, l, "Member names cannot be the same as their enclosing type");\r
2910                 break;\r
2911                 \r
2912         case DeclSpace.AdditionResult.NotAConstructor:\r
2913                 rc.Report.Error (1520, l, "Class, struct, or interface method must have a return type");\r
2914                 break;\r
2915         }\r
2916 }\r
2917 \r
2918 void \r
2919 CheckDef (bool result, string name)\r
2920 {\r
2921         if (result)\r
2922                 return;\r
2923         CheckDef (DeclSpace.AdditionResult.NameExists, name);\r
2924 }\r
2925 \r
2926 Block declare_local_variables (string type, ArrayList variable_declarators)\r
2927 {\r
2928         Block implicit_block;\r
2929         ArrayList inits = null;\r
2930 \r
2931         //\r
2932         // We use the `Used' property to check whether statements\r
2933         // have been added to the current block.  If so, we need\r
2934         // to create another block to contain the new declaration\r
2935         // otherwise, as an optimization, we use the same block to\r
2936         // add the declaration.\r
2937         //\r
2938         // FIXME: A further optimization is to check if the statements\r
2939         // that were added were added as part of the initialization\r
2940         // below.  In which case, no other statements have been executed\r
2941         // and we might be able to reduce the number of blocks for\r
2942         // situations like this:\r
2943         //\r
2944         // int j = 1;  int k = j + 1;\r
2945         //\r
2946         if (current_block.Used)\r
2947                 implicit_block = new Block (current_block, true);\r
2948         else\r
2949                 implicit_block = new Block (current_block, true);\r
2950 \r
2951         foreach (VariableDeclaration decl in variable_declarators){\r
2952                 if (implicit_block.AddVariable (type, decl.identifier)){\r
2953                         if (decl.expression_or_array_initializer != null){\r
2954                                 if (inits == null)\r
2955                                         inits = new ArrayList ();\r
2956                                 inits.Add (decl);\r
2957                         }\r
2958                 } else {\r
2959                         Location l = lexer.Location;\r
2960                         rc.Report.Error (128, l, "A local variable `" + decl.identifier +\r
2961                                          "' is already defined in this scope");\r
2962                 }\r
2963         }\r
2964 \r
2965         if (inits == null)\r
2966                 return implicit_block;\r
2967 \r
2968         foreach (VariableDeclaration decl in inits){\r
2969                 if (decl.expression_or_array_initializer is Expression){\r
2970                         Expression expr = (Expression) decl.expression_or_array_initializer;\r
2971                         Assign assign;\r
2972                         \r
2973                         assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr);\r
2974                         implicit_block.AddStatement (new StatementExpression (assign));\r
2975                 } else {\r
2976                         Console.WriteLine ("Not handling Array initializers yet");\r
2977                 }\r
2978         }\r
2979                         \r
2980         return implicit_block;\r
2981 }\r
2982 \r
2983 void CheckConstant (Expression expr)\r
2984 {\r
2985         // finishme\r
2986 }\r
2987 \r
2988 void CheckBoolean (Expression expr)\r
2989 {\r
2990         // finishme\r
2991 }\r
2992 \r
2993 void CheckAttributeTarget (string a)\r
2994 {\r
2995         switch (a) {\r
2996 \r
2997         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :\r
2998                 return;\r
2999                 \r
3000         default :\r
3001                 Location l = lexer.Location;\r
3002                 rc.Report.Error (658, l, "Invalid attribute target");\r
3003                 break;\r
3004         }\r
3005 \r
3006 }\r
3007 \r
3008 void CheckUnaryOperator (Operator.OpType op)\r
3009 {\r
3010         switch (op) {\r
3011                 \r
3012         case Operator.OpType.Bang : case Operator.OpType.Tilde : case Operator.OpType.Increment :\r
3013         case Operator.OpType.Decrement :\r
3014         case Operator.OpType.True : case Operator.OpType.False : case Operator.OpType.Plus : case Operator.OpType.Minus :\r
3015                 \r
3016                 break;\r
3017                 \r
3018         default :\r
3019                 Location l = lexer.Location;\r
3020                 rc.Report.Error (1019, l, "Overloadable unary operator expected"); \r
3021                 break;\r
3022                 \r
3023         }\r
3024 }\r
3025 \r
3026 void CheckBinaryOperator (Operator.OpType op)\r
3027 {\r
3028         switch (op) {\r
3029                 \r
3030         case Operator.OpType.Plus : case Operator.OpType.Minus : case Operator.OpType.Star : case Operator.OpType.Div :\r
3031         case Operator.OpType.Percent : case Operator.OpType.BitAnd : case Operator.OpType.BitOr :\r
3032         case Operator.OpType.Carret : case Operator.OpType.ShiftLeft : case Operator.OpType.ShiftRight :\r
3033         case Operator.OpType.Eq : case Operator.OpType.NotEq :\r
3034         case Operator.OpType.GreaterThan : case Operator.OpType.LesserThan : case Operator.OpType.GreaterOrEq :\r
3035         case Operator.OpType.LesserOrEq :\r
3036                 \r
3037                 break;\r
3038                 \r
3039         default :\r
3040                 Location l = lexer.Location;\r
3041                 rc.Report.Error (1020, l, "Overloadable binary operator expected");\r
3042                 break;\r
3043         }\r
3044         \r
3045 }\r
3046 \r
3047 void output (string s)\r
3048 {\r
3049         Console.WriteLine (s);\r
3050 }\r
3051 \r
3052 void note (string s)\r
3053 {\r
3054         // Used to put annotations\r
3055 }\r
3056 \r
3057 Tokenizer lexer;\r
3058 \r
3059 public Tokenizer Lexer {\r
3060         get {\r
3061                 return lexer;\r
3062         }\r
3063 }                  \r
3064 \r
3065 public CSharpParser(RootContext rc, string name, System.IO.Stream input) \r
3066 {\r
3067         current_namespace = new Namespace (null, "");\r
3068         this.rc   = rc;\r
3069         this.tree = rc.Tree;\r
3070         this.name = name;\r
3071         this.input = input;\r
3072         current_container = tree.Types;\r
3073         current_container.Namespace = current_namespace;\r
3074 \r
3075         lexer = new Tokenizer (input, name);\r
3076 }\r
3077 \r
3078 public override int parse ()\r
3079 {\r
3080         StringBuilder value = new StringBuilder ();\r
3081 \r
3082         global_errors = 0;\r
3083         try {\r
3084                 if (yacc_verbose_flag)\r
3085                         yyparse (lexer, new yydebug.yyDebugSimple ());\r
3086                 else\r
3087                         yyparse (lexer);\r
3088         } catch (Exception e){\r
3089                 // Console.WriteLine ("Fatal error: " + name);\r
3090                 // Console.WriteLine (lexer.location);\r
3091 \r
3092                 Console.WriteLine (lexer.location + "  : Parsing error");\r
3093                 Console.WriteLine (e);\r
3094                 global_errors++;\r
3095         }\r
3096         \r
3097         return global_errors;\r
3098 }\r
3099 \r
3100 /* end end end */\r
3101 }\r