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