2001-09-27 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
1 %{\r
2 //\r
3 // cs-parser.jay: The Parser for the C# compiler\r
4 //\r
5 // Author: Miguel de Icaza (miguel@gnu.org)\r
6 //\r
7 // Licensed under the terms of the GNU GPL\r
8 //\r
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)\r
10 //\r
11 // TODO:\r
12 //   (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM\r
13 //       And come to think of it, it is not that great, it duplicates a lot of code\r
14 //       for something which is not really needed.  We still have piles of typecasts\r
15 //       anwyays (due to the nature of the stack being a collection of Objects).\r
16 //\r
17 //   (2) Figure out why error productions dont work.  `type-declaration' is a\r
18 //       great spot to put an `error' because you can reproduce it with this input:\r
19 //       "public X { }"\r
20 //\r
21 //   (3) Move Modifier checking from each object into the parser itself, that will\r
22 //       get rid of the global "error" symbol that we use now to report errors. \r
23 //       We still need to pass a pointer to the tree.ErrorHandler, but that is a \r
24 //       separate problem\r
25 //\r
26 using System.Text;\r
27 using CIR;\r
28 using System;\r
29 \r
30 namespace CIR\r
31 {\r
32         using System.Collections;\r
33         using Mono.Languages;\r
34 \r
35         /// <summary>\r
36         ///    The C# Parser\r
37         /// </summary>\r
38         public class CSharpParser : GenericParser {\r
39                 Namespace     current_namespace;\r
40                 TypeContainer current_container;\r
41         \r
42                 // <summary>\r
43                 //   Current block is used to add statements as we find\r
44                 //   them.  \r
45                 // </summary>\r
46 \r
47                 Block      current_block;\r
48 \r
49                 // <summary>\r
50                 //   Current interface is used by the various declaration\r
51                 //   productions in the interface declaration to "add"\r
52                 //   the interfaces as we find them.\r
53                 // </summary>\r
54                 Interface  current_interface;\r
55 \r
56                 // <summary>\r
57                 //   This is used by the unary_expression code to resolve\r
58                 //   a name against a parameter.  \r
59                 // </summary>\r
60                 Parameters current_local_parameters;\r
61 \r
62                 // <summary>\r
63                 //   Using during property parsing to describe the implicit\r
64                 //   value parameter that is passed to the "set" accesor\r
65                 //   method\r
66                 // </summary>\r
67                 Parameter [] implicit_value_parameters;\r
68 \r
69                 // <summary>\r
70                 //   Used to determine if we are parsing the get/set pair\r
71                 //   of an indexer or a property\r
72                 // </summmary>\r
73                 bool  parsing_indexer;\r
74 \r
75                 // <summary>\r
76                 //   Used to record all types defined\r
77                 // </summary>\r
78                 Tree tree;\r
79                 RootContext rc;\r
80 \r
81 %}\r
82 \r
83 %token EOF\r
84 %token NONE   /* This token is never returned by our lexer */\r
85 %token ERROR            // This is used not by the parser, but by the tokenizer.\r
86                         // do not remove.\r
87 \r
88 /*\r
89  *These are the C# keywords\r
90  */\r
91 %token ABSTRACT \r
92 %token AS\r
93 %token ADD\r
94 %token BASE     \r
95 %token BOOL     \r
96 %token BREAK    \r
97 %token BYTE     \r
98 %token CASE     \r
99 %token CATCH    \r
100 %token CHAR     \r
101 %token CHECKED  \r
102 %token CLASS    \r
103 %token CONST    \r
104 %token CONTINUE \r
105 %token DECIMAL  \r
106 %token DEFAULT  \r
107 %token DELEGATE \r
108 %token DO       \r
109 %token DOUBLE   \r
110 %token ELSE     \r
111 %token ENUM     \r
112 %token EVENT    \r
113 %token EXPLICIT \r
114 %token EXTERN   \r
115 %token FALSE    \r
116 %token FINALLY  \r
117 %token FIXED    \r
118 %token FLOAT    \r
119 %token FOR      \r
120 %token FOREACH  \r
121 %token GOTO     \r
122 %token IF       \r
123 %token IMPLICIT \r
124 %token IN       \r
125 %token INT      \r
126 %token INTERFACE\r
127 %token INTERNAL \r
128 %token IS       \r
129 %token LOCK     \r
130 %token LONG     \r
131 %token NAMESPACE\r
132 %token NEW      \r
133 %token NULL     \r
134 %token OBJECT   \r
135 %token OPERATOR \r
136 %token OUT      \r
137 %token OVERRIDE \r
138 %token PARAMS   \r
139 %token PRIVATE  \r
140 %token PROTECTED\r
141 %token PUBLIC   \r
142 %token READONLY \r
143 %token REF      \r
144 %token RETURN   \r
145 %token REMOVE\r
146 %token SBYTE    \r
147 %token SEALED   \r
148 %token SHORT    \r
149 %token SIZEOF   \r
150 %token STATIC   \r
151 %token STRING   \r
152 %token STRUCT   \r
153 %token SWITCH   \r
154 %token THIS     \r
155 %token THROW    \r
156 %token TRUE     \r
157 %token TRY      \r
158 %token TYPEOF   \r
159 %token UINT     \r
160 %token ULONG    \r
161 %token UNCHECKED\r
162 %token UNSAFE   \r
163 %token USHORT   \r
164 %token USING    \r
165 %token VIRTUAL  \r
166 %token VOID     \r
167 %token WHILE    \r
168 \r
169 /* C# keywords which are not really keywords */\r
170 %token GET           "get"\r
171 %token SET           "set"\r
172 \r
173 /* C# single character operators/punctuation. */\r
174 %token OPEN_BRACE    "{"\r
175 %token CLOSE_BRACE   "}"\r
176 %token OPEN_BRACKET  "["\r
177 %token CLOSE_BRACKET "]"\r
178 %token OPEN_PARENS   "("\r
179 %token CLOSE_PARENS  ")"\r
180 %token DOT           "."\r
181 %token COMMA         ","\r
182 %token COLON         ":"\r
183 %token SEMICOLON     ";"\r
184 %token TILDE         "~"\r
185 \r
186 %token PLUS           "+"\r
187 %token MINUS          "-"\r
188 %token BANG           "!"\r
189 %token ASSIGN         "="\r
190 %token OP_LT          "<"\r
191 %token OP_GT          ">"\r
192 %token BITWISE_AND    "&"\r
193 %token BITWISE_OR     "|"\r
194 %token STAR           "*"\r
195 %token PERCENT        "%"\r
196 %token DIV            "/"\r
197 %token CARRET         "^"\r
198 %token INTERR         "?"\r
199 \r
200 /* C# multi-character operators. */\r
201 %token OP_INC                 "++"\r
202 %token OP_DEC                 "--"\r
203 %token OP_SHIFT_LEFT          "<<"\r
204 %token OP_SHIFT_RIGHT         ">>"\r
205 %token OP_LE                  "<="\r
206 %token OP_GE                  ">="\r
207 %token OP_EQ                  "=="\r
208 %token OP_NE                  "!="\r
209 %token OP_AND                 "&&"\r
210 %token OP_OR                  "||"\r
211 %token OP_MULT_ASSIGN         "*="\r
212 %token OP_DIV_ASSIGN          "/="\r
213 %token OP_MOD_ASSIGN          "%="\r
214 %token OP_ADD_ASSIGN          "+="\r
215 %token OP_SUB_ASSIGN          "-="\r
216 %token OP_SHIFT_LEFT_ASSIGN   "<<="\r
217 %token OP_SHIFT_RIGHT_ASSIGN  ">>="\r
218 %token OP_AND_ASSIGN          "&="\r
219 %token OP_XOR_ASSIGN          "^="\r
220 %token OP_OR_ASSIGN           "|="\r
221 %token OP_PTR                 "->"\r
222 \r
223 /* Numbers */\r
224 %token LITERAL_INTEGER           "int literal"\r
225 %token LITERAL_FLOAT             "float literal"\r
226 %token LITERAL_DOUBLE            "double literal"\r
227 %token LITERAL_DECIMAL           "decimal literal"\r
228 %token LITERAL_CHARACTER         "character literal"\r
229 %token LITERAL_STRING            "string literal"\r
230 \r
231 %token IDENTIFIER\r
232 \r
233 /* Add precedence rules to solve dangling else s/r conflict */\r
234 %nonassoc LOWPREC\r
235 %nonassoc IF\r
236 %nonassoc ELSE\r
237 %right ASSIGN\r
238 %left OP_OR\r
239 %left OP_AND\r
240 %left BITWISE_OR\r
241 %left BITWISE_AND\r
242 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT\r
243 %left PLUS MINUS\r
244 %left STAR DIV PERCENT\r
245 %right BANG CARRET UMINUS\r
246 %nonassoc OP_INC OP_DEC\r
247 %left OPEN_PARENS\r
248 %left OPEN_BRACKET OPEN_BRACE\r
249 %left DOT\r
250 %nonassoc HIGHPREC\r
251 \r
252 %start compilation_unit\r
253 /*%start namespace_declaration */\r
254 %%\r
255 \r
256 compilation_unit\r
257         : opt_using_directives opt_attributes opt_namespace_member_declarations EOF\r
258           {\r
259                 // Check that using comes only before namespace elements\r
260           }\r
261         ;\r
262 \r
263 using_directives\r
264         : using_directive \r
265         | using_directives using_directive\r
266         ;\r
267 \r
268 using_directive\r
269         : using_alias_directive\r
270         | using_namespace_directive\r
271         ;\r
272 \r
273 using_alias_directive\r
274         : USING IDENTIFIER ASSIGN \r
275           namespace_or_type_name SEMICOLON\r
276           {\r
277                   // FIXME : Need to implement actual action.\r
278           }\r
279         ;\r
280 \r
281 using_namespace_directive\r
282         : USING namespace_name SEMICOLON \r
283           {\r
284                 current_namespace.Using ((string) $2);\r
285           }\r
286         ;\r
287 \r
288 //  namespace_declarations\r
289 //      : namespace_declaration\r
290 //      | namespace_declarations namespace_declaration\r
291 \r
292 namespace_declaration\r
293         : NAMESPACE qualified_identifier \r
294           {\r
295                 current_namespace = new Namespace (current_namespace, (string) $2);\r
296                 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.Addition; }\r
1111         | MINUS { $$ = Operator.OpType.Subtraction; }\r
1112 // Binary:\r
1113         | STAR { $$ = Operator.OpType.Multiply; }\r
1114         | DIV {  $$ = Operator.OpType.Division; }\r
1115         | PERCENT { $$ = Operator.OpType.Modulus; }\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.LeftShift; }\r
1120         | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }\r
1121         | OP_EQ { $$ = Operator.OpType.Equality; }\r
1122         | OP_NE { $$ = Operator.OpType.Inequality; }\r
1123         | OP_GT { $$ = Operator.OpType.GreaterThan; }\r
1124         | OP_LT { $$ = Operator.OpType.LessThan; }\r
1125         | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }\r
1126         | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }\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                 \r
1172                 CheckDef (current_container.AddConstructor (c), c.Name);\r
1173 \r
1174                 current_local_parameters = null;\r
1175           }\r
1176         ;\r
1177 \r
1178 constructor_declarator\r
1179         : IDENTIFIER \r
1180           OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
1181           opt_constructor_initializer\r
1182           {\r
1183                 $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $5);\r
1184         \r
1185                 current_local_parameters = (Parameters) $3;\r
1186           }\r
1187         ;\r
1188 \r
1189 opt_constructor_initializer\r
1190         : /* empty */                   { $$ = null; }\r
1191         | constructor_initializer\r
1192         ;\r
1193 \r
1194 constructor_initializer\r
1195         : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1196           {\r
1197                 $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);\r
1198           }\r
1199         | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1200           {\r
1201                 $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);\r
1202           }\r
1203         ;\r
1204 \r
1205 destructor_declaration\r
1206         : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block\r
1207           {\r
1208                 Method d = new Method ("System.Void", 0, "Finalize", new Parameters (null, null), (Attributes) $1);\r
1209                   \r
1210                 d.Block = (Block) $6;\r
1211                 CheckDef (current_container.AddMethod (d), d.Name);\r
1212           }\r
1213         ;\r
1214 \r
1215 event_declaration\r
1216         : opt_attributes\r
1217           opt_modifiers\r
1218           EVENT type variable_declarators SEMICOLON\r
1219           {\r
1220                 foreach (VariableDeclaration var in (ArrayList) $5) {\r
1221 \r
1222                         // FIXME : Is this right ?\r
1223                         Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,\r
1224                                              (int) $2, null, null, (Attributes) $1);\r
1225 \r
1226                         CheckDef (current_container.AddEvent (e), e.Name);\r
1227                                        \r
1228                 }\r
1229           }\r
1230         | opt_attributes\r
1231           opt_modifiers\r
1232           EVENT type member_name \r
1233           OPEN_BRACE event_accessor_declarations CLOSE_BRACE\r
1234         {\r
1235                 DictionaryEntry pair = (DictionaryEntry) $7;\r
1236                 Block add_block = null;\r
1237                 Block rem_block = null;\r
1238 \r
1239                 if (pair.Key != null)\r
1240                         add_block = (Block) pair.Key;\r
1241                 if (pair.Value != null)\r
1242                         rem_block = (Block) pair.Value;\r
1243                 \r
1244                 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block, (Attributes) $1);\r
1245                 \r
1246                 CheckDef (current_container.AddEvent (e), e.Name);\r
1247         }\r
1248         ;\r
1249 \r
1250 event_accessor_declarations\r
1251         : add_accessor_declaration remove_accessor_declaration\r
1252         {\r
1253                 $$ = new DictionaryEntry ($1, $2);\r
1254         }\r
1255         | remove_accessor_declaration add_accessor_declaration\r
1256         {\r
1257                 $$ = new DictionaryEntry ($2, $1);\r
1258         }       \r
1259         ;\r
1260 \r
1261 add_accessor_declaration\r
1262         : opt_attributes ADD block\r
1263           {\r
1264                 $$ = $3;\r
1265           }\r
1266         ;\r
1267 \r
1268 remove_accessor_declaration\r
1269         : opt_attributes REMOVE block\r
1270         {\r
1271                 $$ = $3;\r
1272         }\r
1273         ;\r
1274 \r
1275 indexer_declaration\r
1276         : opt_attributes opt_modifiers indexer_declarator \r
1277           OPEN_BRACE \r
1278           {\r
1279                 IndexerDeclaration decl = (IndexerDeclaration) $3;\r
1280                   \r
1281                 lexer.properties = true;\r
1282                 parsing_indexer  = true;\r
1283                 \r
1284                 current_local_parameters = decl.param_list;\r
1285           }\r
1286           accessor_declarations \r
1287           {\r
1288                   lexer.properties = false;\r
1289                   parsing_indexer  = false;\r
1290           }\r
1291           CLOSE_BRACE\r
1292           { \r
1293                 // The signature is computed from the signature of the indexer.  Look\r
1294                 // at section 3.6 on the spec\r
1295 \r
1296                 Indexer indexer;\r
1297                 IndexerDeclaration decl = (IndexerDeclaration) $3;\r
1298                 DictionaryEntry pair = (DictionaryEntry) $6;\r
1299                 Block get_block = null;\r
1300                 Block set_block = null;\r
1301 \r
1302                 if (pair.Key != null)\r
1303                         get_block = (Block) pair.Key;\r
1304                 if (pair.Value != null)\r
1305                         set_block = (Block) pair.Value;\r
1306 \r
1307                 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,\r
1308                                        get_block, set_block, (Attributes) $1);\r
1309 \r
1310                 // Note that there is no equivalent of CheckDef for this case\r
1311                 // We shall handle this in semantic analysis\r
1312                 \r
1313                 current_container.AddIndexer (indexer);\r
1314                 \r
1315                 current_local_parameters = null;\r
1316           }\r
1317         ;\r
1318 \r
1319 indexer_declarator\r
1320         : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
1321           {\r
1322                 $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);\r
1323           }\r
1324         | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
1325           {\r
1326                 $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);\r
1327           }\r
1328         ;\r
1329 \r
1330 enum_declaration\r
1331         : opt_attributes\r
1332           opt_modifiers\r
1333           ENUM IDENTIFIER\r
1334           opt_enum_base\r
1335           enum_body\r
1336           opt_semicolon\r
1337           { \r
1338                 string name = (string) $4;\r
1339                 Enum e = new Enum ((string) $5, (int) $2, name, (Attributes) $1);\r
1340 \r
1341                 foreach (VariableDeclaration ev in (ArrayList) $6){\r
1342                         CheckDef (e.AddEnumMember (ev.identifier, \r
1343                                                    (Expression) ev.expression_or_array_initializer),\r
1344                                   ev.identifier);\r
1345                 }\r
1346 \r
1347                 CheckDef (current_container.AddEnum (e), name);\r
1348           }\r
1349         ;\r
1350 \r
1351 opt_enum_base\r
1352         : /* empty */                   { $$ = "System.Int32"; }\r
1353         | COLON integral_type           { $$ = $2;   }\r
1354         ;\r
1355 \r
1356 enum_body\r
1357         : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE\r
1358           {\r
1359                 $$ = $2;\r
1360           }\r
1361         ;\r
1362 \r
1363 opt_enum_member_declarations\r
1364         : /* empty */                   { $$ = new ArrayList (); }\r
1365         | enum_member_declarations opt_comma { $$ = $1; }\r
1366         ;\r
1367 \r
1368 enum_member_declarations\r
1369         : enum_member_declaration \r
1370           {\r
1371                 ArrayList l = new ArrayList ();\r
1372 \r
1373                 l.Add ($1);\r
1374                 $$ = l;\r
1375           }\r
1376         | enum_member_declarations COMMA enum_member_declaration\r
1377           {\r
1378                 ArrayList l = (ArrayList) $1;\r
1379 \r
1380                 l.Add ($3);\r
1381 \r
1382                 $$ = l;\r
1383           }\r
1384         ;\r
1385 \r
1386 enum_member_declaration\r
1387         : opt_attributes IDENTIFIER \r
1388           {\r
1389                 $$ = new VariableDeclaration ((string) $2, null);\r
1390           }\r
1391         | opt_attributes IDENTIFIER ASSIGN expression\r
1392           { \r
1393                 $$ = new VariableDeclaration ((string) $2, $4);\r
1394           }\r
1395         ;\r
1396 \r
1397 delegate_declaration\r
1398         : opt_attributes\r
1399           opt_modifiers\r
1400           DELEGATE type   \r
1401           IDENTIFIER OPEN_PARENS \r
1402           formal_parameter_list\r
1403           CLOSE_PARENS \r
1404           SEMICOLON\r
1405           {\r
1406                 Delegate del = new Delegate ((string) $4, (int) $2, (string) $5, (Parameters) $7, (Attributes) $1);\r
1407 \r
1408                 CheckDef (current_container.AddDelegate (del), del.Name);\r
1409           }     \r
1410         | opt_attributes\r
1411           opt_modifiers\r
1412           DELEGATE VOID   \r
1413           IDENTIFIER OPEN_PARENS \r
1414           formal_parameter_list\r
1415           CLOSE_PARENS \r
1416           SEMICOLON\r
1417           {\r
1418                 Delegate del = new Delegate (null, (int) $2, (string) $5, (Parameters) $7, (Attributes) $1);\r
1419 \r
1420                 CheckDef (current_container.AddDelegate (del), del.Name);\r
1421           }\r
1422         ;\r
1423 \r
1424 type_name\r
1425         : namespace_or_type_name\r
1426         ;\r
1427 \r
1428 namespace_or_type_name\r
1429         : qualified_identifier\r
1430         ;\r
1431 \r
1432 /* \r
1433  * Before you think of adding a return_type, notice that we have been\r
1434  * using two rules in the places where it matters (one rule using type\r
1435  * and another identical one that uses VOID as the return type).  This\r
1436  * gets rid of a shift/reduce couple\r
1437  */\r
1438 type\r
1439         : type_name {   /* class_type */\r
1440                 /* \r
1441                    This does interfaces, delegates, struct_types, class_types, \r
1442                    parent classes, and more! 4.2 \r
1443                  */\r
1444                 $$ = $1; \r
1445           }\r
1446         | builtin_types\r
1447         | array_type\r
1448         ;\r
1449 \r
1450 type_list\r
1451         : type\r
1452           {\r
1453                 ArrayList types = new ArrayList ();\r
1454 \r
1455                 types.Add ($1);\r
1456                 $$ = types;\r
1457           }\r
1458         | type_list COMMA type\r
1459           {\r
1460                 ArrayList types = (ArrayList) $1;\r
1461 \r
1462                 types.Add ($3);\r
1463                 $$ = types;\r
1464           }\r
1465         ;\r
1466 \r
1467 /*\r
1468  * replaces all the productions for isolating the various\r
1469  * simple types, but we need this to reuse it easily in local_variable_type\r
1470  */\r
1471 builtin_types\r
1472         : OBJECT        { $$ = "System.Object"; }\r
1473         | STRING        { $$ = "System.String"; }\r
1474         | BOOL          { $$ = "System.Boolean"; }\r
1475         | DECIMAL       { $$ = "System.Decimal"; }\r
1476         | FLOAT         { $$ = "System.Single"; }\r
1477         | DOUBLE        { $$ = "System.Double"; }\r
1478         | integral_type\r
1479         ;\r
1480 \r
1481 integral_type\r
1482         : SBYTE         { $$ = "System.SByte"; }\r
1483         | BYTE          { $$ = "System.Byte"; }\r
1484         | SHORT         { $$ = "System.Int16"; }\r
1485         | USHORT        { $$ = "System.UInt16"; }\r
1486         | INT           { $$ = "System.Int32"; }\r
1487         | UINT          { $$ = "System.UInt32"; }\r
1488         | LONG          { $$ = "System.Int64"; }\r
1489         | ULONG         { $$ = "System.UInt64"; }\r
1490         | CHAR          { $$ = "System.Char"; }\r
1491         ;\r
1492 \r
1493 interface_type\r
1494         : type_name\r
1495         ;\r
1496 \r
1497 array_type\r
1498         : type rank_specifiers\r
1499           {\r
1500                   $$ = (string) $1 + (string) $2;\r
1501           }\r
1502         ;\r
1503 \r
1504 //\r
1505 // Expressions, section 7.5\r
1506 //\r
1507 primary_expression\r
1508         : literal\r
1509           {\r
1510                 // 7.5.1: Literals\r
1511           }\r
1512  \r
1513         | qualified_identifier\r
1514           {\r
1515                 string name = (string) $1;\r
1516 \r
1517                 $$ = null;\r
1518                 $$ = QualifiedIdentifier (name, lexer.Location);\r
1519           }\r
1520         | parenthesized_expression\r
1521         | member_access\r
1522         | invocation_expression\r
1523         | element_access\r
1524         | this_access\r
1525         | base_access\r
1526         | post_increment_expression\r
1527         | post_decrement_expression\r
1528         | new_expression\r
1529         | typeof_expression\r
1530         | sizeof_expression\r
1531         | checked_expression\r
1532         | unchecked_expression\r
1533         ;\r
1534 \r
1535 literal\r
1536         : boolean_literal\r
1537         | integer_literal\r
1538         | real_literal\r
1539         | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }\r
1540         | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }\r
1541         | NULL                  { $$ = new NullLiteral (); }\r
1542         ;\r
1543 \r
1544 real_literal\r
1545         : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }\r
1546         | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }\r
1547         | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }\r
1548         ;\r
1549 \r
1550 integer_literal\r
1551         : LITERAL_INTEGER       { $$ = new IntLiteral ((Int32) lexer.Value); }\r
1552         ;\r
1553 \r
1554 boolean_literal\r
1555         : TRUE                  { $$ = new BoolLiteral (true); }\r
1556         | FALSE                 { $$ = new BoolLiteral (false); }\r
1557         ;\r
1558 \r
1559 parenthesized_expression\r
1560         : OPEN_PARENS expression CLOSE_PARENS\r
1561           { $$ = $2; }\r
1562         ;\r
1563 \r
1564 member_access\r
1565         : primary_expression DOT IDENTIFIER\r
1566           {\r
1567                 $$ = new MemberAccess ((Expression) $1, (string) $3);\r
1568           }\r
1569         | predefined_type DOT IDENTIFIER\r
1570           {\r
1571                 $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);\r
1572           }\r
1573         ;\r
1574 \r
1575 predefined_type\r
1576         : builtin_types\r
1577         ;\r
1578 \r
1579 invocation_expression\r
1580         : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1581           {\r
1582                 // FIXME:\r
1583                 // if $1 is MethodGroup\r
1584                 //      $$ = new Call ($1, $3);\r
1585                 // else \r
1586                 //      $$ = new DelegateCall ($1, $3);\r
1587                 if ($1 == null) {\r
1588                         Location l = lexer.Location;\r
1589                         rc.Report.Error (1, l, "THIS IS CRAZY");\r
1590                 }\r
1591                 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);\r
1592                 \r
1593           }\r
1594         ; \r
1595 \r
1596 opt_argument_list\r
1597         : /* empty */           { $$ = null; }\r
1598         | argument_list\r
1599         ;\r
1600 \r
1601 argument_list\r
1602         : argument              \r
1603           { \r
1604                 ArrayList list = new ArrayList ();\r
1605                 list.Add ($1);\r
1606                 $$ = list;\r
1607           }\r
1608         | argument_list COMMA argument\r
1609           {\r
1610                 ArrayList list = (ArrayList) $1;\r
1611                 list.Add ($3);\r
1612                 $$ = list;\r
1613           }\r
1614         ;\r
1615 \r
1616 argument\r
1617         : expression\r
1618           {\r
1619                 $$ = new Argument ((Expression) $1, Argument.AType.Expression);\r
1620           }\r
1621         | REF variable_reference \r
1622           { \r
1623                 $$ = new Argument ((Expression) $2, Argument.AType.Ref);\r
1624           }\r
1625         | OUT variable_reference \r
1626           { \r
1627                 $$ = new Argument ((Expression) $2, Argument.AType.Out);\r
1628           }\r
1629         ;\r
1630 \r
1631 variable_reference\r
1632         : expression { note ("section 5.4"); $$ = $1; }\r
1633         ;\r
1634 \r
1635 element_access\r
1636         : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET \r
1637           {\r
1638                 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3);\r
1639           }\r
1640         ;\r
1641 \r
1642 expression_list\r
1643         : expression\r
1644           {\r
1645                 ArrayList list = new ArrayList ();\r
1646                 list.Add ($1);\r
1647                 $$ = list;\r
1648           }\r
1649         | expression_list COMMA expression\r
1650           {\r
1651                 ArrayList list = (ArrayList) $1;\r
1652                 list.Add ($3);\r
1653                 $$ = list;\r
1654           }\r
1655         ;\r
1656 \r
1657 this_access\r
1658         : THIS\r
1659           {\r
1660                 $$ = new This ();\r
1661           }\r
1662         ;\r
1663 \r
1664 base_access\r
1665         : BASE DOT IDENTIFIER\r
1666           {\r
1667                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);\r
1668           }\r
1669         | BASE OPEN_BRACKET expression_list CLOSE_BRACKET\r
1670           {\r
1671                 $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);\r
1672           }\r
1673         ;\r
1674 \r
1675 post_increment_expression\r
1676         : primary_expression OP_INC\r
1677           {\r
1678                 $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1, lexer.Location);\r
1679           }\r
1680         ;\r
1681 \r
1682 post_decrement_expression\r
1683         : primary_expression OP_DEC\r
1684           {\r
1685                 $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1, lexer.Location);\r
1686           }\r
1687         ;\r
1688 \r
1689 new_expression\r
1690         : object_or_delegate_creation_expression\r
1691         | array_creation_expression\r
1692         ;\r
1693 \r
1694 object_or_delegate_creation_expression\r
1695         : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS\r
1696           {\r
1697                 $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);\r
1698           }\r
1699         ;\r
1700 \r
1701 array_creation_expression\r
1702         : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET \r
1703           opt_rank_specifier\r
1704           opt_array_initializer\r
1705           {\r
1706                 $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);\r
1707           }\r
1708         ;\r
1709 \r
1710 opt_rank_specifier\r
1711         : /* empty */\r
1712           {\r
1713                   $$ = "";\r
1714           }\r
1715         | rank_specifiers\r
1716           {\r
1717                         $$ = $1;\r
1718           }\r
1719         ;\r
1720 \r
1721 rank_specifiers\r
1722         : rank_specifier\r
1723           {\r
1724                   $$ = $1;\r
1725           }\r
1726         | rank_specifier rank_specifiers\r
1727           {\r
1728                   $$ = (string) $1 + (string) $2;\r
1729           }             \r
1730         ;\r
1731 \r
1732 rank_specifier\r
1733         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
1734           {\r
1735                 $$ = "[" + (string) $2 + "]";\r
1736           }\r
1737         ;\r
1738 \r
1739 opt_dim_separators\r
1740         : /* empty */\r
1741           {\r
1742                 $$ = "";\r
1743           }\r
1744         | dim_separators\r
1745           {\r
1746                   $$ = $1;\r
1747           }               \r
1748         ;\r
1749 \r
1750 dim_separators\r
1751         : COMMA\r
1752           {\r
1753                 $$ = ",";\r
1754           }\r
1755         | dim_separators COMMA\r
1756           {\r
1757                 $$ =(string) $1 + ",";\r
1758           }\r
1759         ;\r
1760 \r
1761 opt_array_initializer\r
1762         : /* empty */\r
1763           {\r
1764                 $$ = null;\r
1765           }\r
1766         | array_initializer\r
1767           {\r
1768                 $$ = $1;\r
1769           }\r
1770         ;\r
1771 \r
1772 array_initializer\r
1773         : OPEN_BRACE CLOSE_BRACE\r
1774           {\r
1775                 ArrayList list = new ArrayList ();\r
1776                 $$ = list;\r
1777           }\r
1778         | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE\r
1779         {\r
1780                 $$ = (ArrayList) $2;\r
1781         }\r
1782         ;\r
1783 \r
1784 variable_initializer_list\r
1785         : variable_initializer\r
1786         {\r
1787                 ArrayList list = new ArrayList ();\r
1788                 list.Add ($1);\r
1789                 $$ = list;\r
1790         }\r
1791         | variable_initializer_list COMMA variable_initializer\r
1792         {\r
1793                 ArrayList list = (ArrayList) $1;\r
1794                 list.Add ($3);\r
1795                 $$ = list;\r
1796         }\r
1797         ;\r
1798 \r
1799 typeof_expression\r
1800         : TYPEOF OPEN_PARENS type CLOSE_PARENS\r
1801           {\r
1802                 $$ = new TypeOf ((string) $3);\r
1803           }\r
1804         ;\r
1805 \r
1806 sizeof_expression\r
1807         : SIZEOF OPEN_PARENS type CLOSE_PARENS { \r
1808                 $$ = new SizeOf ((string) $3);\r
1809 \r
1810                 note ("Verify type is unmanaged"); \r
1811                 note ("if (5.8) builtin, yield constant expression");\r
1812           }\r
1813         ;\r
1814 \r
1815 checked_expression\r
1816         : CHECKED OPEN_PARENS expression CLOSE_PARENS\r
1817           {\r
1818                 $$ = new CheckedExpr ((Expression) $3);\r
1819           }\r
1820         ;\r
1821 \r
1822 unchecked_expression\r
1823         : UNCHECKED OPEN_PARENS expression CLOSE_PARENS\r
1824           {\r
1825                 $$ = new UnCheckedExpr ((Expression) $3);\r
1826           }\r
1827         ;\r
1828 \r
1829 unary_expression\r
1830         : primary_expression\r
1831         | PLUS unary_expression         { \r
1832                 $$ = new Unary (Unary.Operator.Addition, (Expression) $2, lexer.Location);\r
1833           } \r
1834         | MINUS unary_expression \r
1835           { \r
1836                 $$ = new Unary (Unary.Operator.Subtraction, (Expression) $2, lexer.Location);\r
1837           }\r
1838         | BANG unary_expression \r
1839           {\r
1840                 $$ = new Unary (Unary.Operator.Negate, (Expression) $2, lexer.Location);\r
1841           }\r
1842         | TILDE unary_expression\r
1843           {\r
1844                 $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2, lexer.Location);\r
1845           }\r
1846         | STAR unary_expression\r
1847           {\r
1848                 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);\r
1849           }\r
1850         | BITWISE_AND unary_expression\r
1851           {\r
1852                 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);\r
1853           }\r
1854         | OP_INC unary_expression \r
1855           {\r
1856                 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);\r
1857           }\r
1858         | OP_DEC unary_expression \r
1859           {\r
1860                 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);\r
1861           }\r
1862         | cast_expression \r
1863         /*\r
1864          we can not do cast expressions at this level,\r
1865          as there is an ambiguity.  Check "Cast Expressions" 7.6.8\r
1866          for the recipe to handle this.\r
1867          */\r
1868         ;\r
1869 \r
1870 pre_increment_expression\r
1871         : OP_INC unary_expression \r
1872           {\r
1873                 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);\r
1874           }\r
1875         ;\r
1876 \r
1877 pre_decrement_expression\r
1878         : OP_DEC unary_expression \r
1879           {\r
1880                 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);\r
1881           }\r
1882         ;\r
1883 \r
1884 cast_expression\r
1885         /* \r
1886          * FIXME: This is actually wrong, it should be `type' but that\r
1887          * introduces a lot of {shift,reduce}/reduces\r
1888          *\r
1889          * This is really really wrong.  We need to track down\r
1890          * the source of problems with QIs because expressions like:\r
1891          * foreach (string s in (string []) object) wont be parsed.\r
1892          */\r
1893         : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression\r
1894           {\r
1895                 $$ = new Cast ((string) $2, (Expression) $4);\r
1896           }\r
1897         | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression\r
1898           {\r
1899                 $$ = new Cast ((string) $2, (Expression) $4);\r
1900           }\r
1901         ;\r
1902 \r
1903 multiplicative_expression\r
1904         : unary_expression\r
1905         | multiplicative_expression STAR unary_expression\r
1906           {\r
1907                 $$ = new Binary (Binary.Operator.Multiply, \r
1908                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1909           }\r
1910         | multiplicative_expression DIV unary_expression\r
1911           {\r
1912                 $$ = new Binary (Binary.Operator.Division, \r
1913                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1914           }\r
1915         | multiplicative_expression PERCENT unary_expression \r
1916           {\r
1917                 $$ = new Binary (Binary.Operator.Modulus, \r
1918                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1919           }\r
1920         ;\r
1921 \r
1922 additive_expression\r
1923         : multiplicative_expression\r
1924         | additive_expression PLUS multiplicative_expression \r
1925           {\r
1926                 $$ = new Binary (Binary.Operator.Addition, \r
1927                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1928           }\r
1929         | additive_expression MINUS multiplicative_expression\r
1930           {\r
1931                 $$ = new Binary (Binary.Operator.Subtraction, \r
1932                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1933           }\r
1934         ;\r
1935 \r
1936 shift_expression\r
1937         : additive_expression\r
1938         | shift_expression OP_SHIFT_LEFT additive_expression\r
1939           {\r
1940                 $$ = new Binary (Binary.Operator.LeftShift, \r
1941                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1942           }\r
1943         | shift_expression OP_SHIFT_RIGHT additive_expression\r
1944           {\r
1945                 $$ = new Binary (Binary.Operator.RightShift, \r
1946                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1947           }\r
1948         ; \r
1949 \r
1950 relational_expression\r
1951         : shift_expression\r
1952         | relational_expression OP_LT shift_expression\r
1953           {\r
1954                 $$ = new Binary (Binary.Operator.LessThan, \r
1955                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1956           }\r
1957         | relational_expression OP_GT shift_expression\r
1958           {\r
1959                 $$ = new Binary (Binary.Operator.GreaterThan, \r
1960                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1961           }\r
1962         | relational_expression OP_LE shift_expression\r
1963           {\r
1964                 $$ = new Binary (Binary.Operator.LessThanOrEqual, \r
1965                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1966           }\r
1967         | relational_expression OP_GE shift_expression\r
1968           {\r
1969                 $$ = new Binary (Binary.Operator.GreaterThanOrEqual, \r
1970                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1971           }\r
1972         | relational_expression IS type\r
1973           {\r
1974                 $$ = new Probe (Probe.Operator.Is, \r
1975                                  (Expression) $1, (string) $3);\r
1976           }\r
1977         | relational_expression AS type\r
1978           {\r
1979                 $$ = new Probe (Probe.Operator.As, \r
1980                                  (Expression) $1, (string) $3);\r
1981           }\r
1982         ;\r
1983 \r
1984 equality_expression\r
1985         : relational_expression\r
1986         | equality_expression OP_EQ relational_expression\r
1987           {\r
1988                 $$ = new Binary (Binary.Operator.Equality, \r
1989                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1990           }\r
1991         | equality_expression OP_NE relational_expression\r
1992           {\r
1993                 $$ = new Binary (Binary.Operator.Inequality, \r
1994                                  (Expression) $1, (Expression) $3, lexer.Location);\r
1995           }\r
1996         ; \r
1997 \r
1998 and_expression\r
1999         : equality_expression\r
2000         | and_expression BITWISE_AND equality_expression\r
2001           {\r
2002                 $$ = new Binary (Binary.Operator.BitwiseAnd, \r
2003                                  (Expression) $1, (Expression) $3, lexer.Location);\r
2004           }\r
2005         ;\r
2006 \r
2007 exclusive_or_expression\r
2008         : and_expression\r
2009         | exclusive_or_expression CARRET and_expression\r
2010           {\r
2011                 $$ = new Binary (Binary.Operator.ExclusiveOr, \r
2012                                  (Expression) $1, (Expression) $3, lexer.Location);\r
2013           }\r
2014         ;\r
2015 \r
2016 inclusive_or_expression\r
2017         : exclusive_or_expression\r
2018         | inclusive_or_expression BITWISE_OR exclusive_or_expression\r
2019           {\r
2020                 $$ = new Binary (Binary.Operator.BitwiseOr, \r
2021                                  (Expression) $1, (Expression) $3, lexer.Location);\r
2022           }\r
2023         ;\r
2024 \r
2025 conditional_and_expression\r
2026         : inclusive_or_expression\r
2027         | conditional_and_expression OP_AND inclusive_or_expression\r
2028           {\r
2029                 $$ = new Binary (Binary.Operator.LogicalAnd, \r
2030                                  (Expression) $1, (Expression) $3, lexer.Location);\r
2031           }\r
2032         ;\r
2033 \r
2034 conditional_or_expression\r
2035         : conditional_and_expression\r
2036         | conditional_or_expression OP_OR conditional_and_expression\r
2037           {\r
2038                 $$ = new Binary (Binary.Operator.LogicalOr, \r
2039                                  (Expression) $1, (Expression) $3, lexer.Location);\r
2040           }\r
2041         ;\r
2042 \r
2043 conditional_expression\r
2044         : conditional_or_expression\r
2045         | conditional_or_expression INTERR expression COLON expression \r
2046           {\r
2047                 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);\r
2048           }\r
2049         ;\r
2050 \r
2051 assignment_expression\r
2052         : unary_expression ASSIGN expression\r
2053           {\r
2054                 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);\r
2055           }\r
2056         | unary_expression OP_MULT_ASSIGN expression\r
2057           {\r
2058                 Location l = lexer.Location;\r
2059 \r
2060                 $$ = new Assign ((Expression) $1,\r
2061                                  new Binary (Binary.Operator.Multiply, \r
2062                                              (Expression) $1,\r
2063                                              (Expression) $3, l), l);\r
2064           }\r
2065         | unary_expression OP_DIV_ASSIGN expression\r
2066           {\r
2067                 Location l = lexer.Location;\r
2068 \r
2069                 $$ = new Assign ((Expression) $1,\r
2070                                  new Binary (Binary.Operator.Division, \r
2071                                              (Expression) $1,\r
2072                                              (Expression) $3, l), l);\r
2073           }\r
2074         | unary_expression OP_MOD_ASSIGN expression\r
2075           {\r
2076                 Location l = lexer.Location;\r
2077 \r
2078                 $$ = new Assign ((Expression) $1,\r
2079                                  new Binary (Binary.Operator.Modulus, \r
2080                                              (Expression) $1,\r
2081                                              (Expression) $3, l), l);\r
2082           }\r
2083         | unary_expression OP_ADD_ASSIGN expression\r
2084           {\r
2085                 Location l = lexer.Location;\r
2086 \r
2087                 $$ = new Assign ((Expression) $1,\r
2088                                  new Binary (Binary.Operator.Addition, \r
2089                                              (Expression) $1,\r
2090                                              (Expression) $3, l), l);\r
2091           }\r
2092         | unary_expression OP_SUB_ASSIGN expression\r
2093           {\r
2094                 Location l = lexer.Location;\r
2095 \r
2096                 $$ = new Assign ((Expression) $1,\r
2097                                  new Binary (Binary.Operator.Subtraction, \r
2098                                              (Expression) $1,\r
2099                                              (Expression) $3, l), l);\r
2100           }\r
2101         | unary_expression OP_SHIFT_LEFT_ASSIGN expression\r
2102           {\r
2103                 Location l = lexer.Location;\r
2104 \r
2105                 $$ = new Assign ((Expression) $1,\r
2106                                  new Binary (Binary.Operator.LeftShift, \r
2107                                              (Expression) $1,\r
2108                                              (Expression) $3, l), l);\r
2109           }\r
2110         | unary_expression OP_SHIFT_RIGHT_ASSIGN expression\r
2111           {\r
2112                 Location l = lexer.Location;\r
2113 \r
2114                 $$ = new Assign ((Expression) $1,\r
2115                                  new Binary (Binary.Operator.RightShift, \r
2116                                              (Expression) $1,\r
2117                                              (Expression) $3, l), l);\r
2118           }\r
2119         | unary_expression OP_AND_ASSIGN expression\r
2120           {\r
2121                 Location l = lexer.Location;\r
2122 \r
2123                 $$ = new Assign ((Expression) $1,\r
2124                                  new Binary (Binary.Operator.BitwiseAnd, \r
2125                                              (Expression) $1,\r
2126                                              (Expression) $3, l), l);\r
2127           }\r
2128         | unary_expression OP_OR_ASSIGN expression\r
2129           {\r
2130                 Location l = lexer.Location;\r
2131 \r
2132                 $$ = new Assign ((Expression) $1,\r
2133                                  new Binary (Binary.Operator.BitwiseOr, \r
2134                                              (Expression) $1,\r
2135                                              (Expression) $3, l), l);\r
2136           }\r
2137         | unary_expression OP_XOR_ASSIGN expression\r
2138           {\r
2139                 Location l = lexer.Location;\r
2140 \r
2141                 $$ = new Assign ((Expression) $1,\r
2142                                  new Binary (Binary.Operator.ExclusiveOr, \r
2143                                              (Expression) $1,\r
2144                                              (Expression) $3, l), l);\r
2145           }\r
2146         ;\r
2147 \r
2148 expression\r
2149         : conditional_expression\r
2150         | assignment_expression\r
2151         ;\r
2152 \r
2153 constant_expression\r
2154         : expression\r
2155         ;\r
2156 \r
2157 boolean_expression\r
2158         : expression    { CheckBoolean ((Expression) $1); $$ = $1; } \r
2159         ;\r
2160 \r
2161 //\r
2162 // 10 classes\r
2163 //\r
2164 class_declaration\r
2165         : opt_attributes\r
2166           opt_modifiers\r
2167           CLASS IDENTIFIER\r
2168           {\r
2169                 Class new_class;\r
2170                 string full_class_name = MakeName ((string) $4);\r
2171 \r
2172                 new_class = new Class (rc, current_container, full_class_name, (int) $2, (Attributes) $1);\r
2173                 current_container = new_class;\r
2174                 current_container.Namespace = current_namespace;\r
2175                 tree.RecordClass (full_class_name, new_class);\r
2176           }\r
2177           opt_class_base\r
2178           class_body \r
2179           opt_semicolon \r
2180           {\r
2181                 Class new_class = (Class) current_container;\r
2182 \r
2183                 if ($6 != null)\r
2184                         new_class.Bases = (ArrayList) $6;\r
2185 \r
2186                 current_container = current_container.Parent;\r
2187                 CheckDef (current_container.AddClass (new_class), new_class.Name);\r
2188 \r
2189                 $$ = new_class;\r
2190           }\r
2191         ;       \r
2192 \r
2193 opt_modifiers\r
2194         : /* empty */           { $$ = (int) 0; }\r
2195         | modifiers\r
2196         ;\r
2197 \r
2198 modifiers\r
2199         : modifier\r
2200         | modifiers modifier\r
2201           { \r
2202                 int m1 = (int) $1;\r
2203                 int m2 = (int) $2;\r
2204 \r
2205                 if ((m1 & m2) != 0) {\r
2206                         Location l = lexer.Location;\r
2207                         rc.Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");\r
2208                 }\r
2209                 $$ = (int) (m1 | m2);\r
2210           }\r
2211         ;\r
2212 \r
2213 modifier\r
2214         : NEW                   { $$ = Modifiers.NEW; }\r
2215         | PUBLIC                { $$ = Modifiers.PUBLIC; }\r
2216         | PROTECTED             { $$ = Modifiers.PROTECTED; }\r
2217         | INTERNAL              { $$ = Modifiers.INTERNAL; }\r
2218         | PRIVATE               { $$ = Modifiers.PRIVATE; }\r
2219         | ABSTRACT              { $$ = Modifiers.ABSTRACT; }\r
2220         | SEALED                { $$ = Modifiers.SEALED; }\r
2221         | STATIC                { $$ = Modifiers.STATIC; }\r
2222         | READONLY              { $$ = Modifiers.READONLY; }\r
2223         | VIRTUAL               { $$ = Modifiers.VIRTUAL; }\r
2224         | OVERRIDE              { $$ = Modifiers.OVERRIDE; }\r
2225         | EXTERN                { $$ = Modifiers.EXTERN; }\r
2226         ;\r
2227 \r
2228 opt_class_base\r
2229         : /* empty */           { $$ = null; }\r
2230         | class_base            { $$ = $1;   }\r
2231         ;\r
2232 \r
2233 class_base\r
2234         : COLON type_list { $$ = $2; }\r
2235         ;\r
2236 \r
2237 //\r
2238 // Statements (8.2)\r
2239 //\r
2240 \r
2241 //\r
2242 // A block is "contained" on the following places:\r
2243 //      method_body\r
2244 //      property_declaration as part of the accessor body (get/set)\r
2245 //      operator_declaration\r
2246 //      constructor_declaration\r
2247 //      destructor_declaration\r
2248 //      event_declaration as part of add_accessor_declaration or remove_accessor_declaration\r
2249 //      \r
2250 block\r
2251         : OPEN_BRACE \r
2252           {\r
2253                 current_block = new Block (current_block);\r
2254           } \r
2255           opt_statement_list CLOSE_BRACE \r
2256           { \r
2257                 while (current_block.Implicit)\r
2258                         current_block = current_block.Parent;\r
2259                 $$ = current_block;\r
2260                 current_block = current_block.Parent;\r
2261           }\r
2262         ;\r
2263 \r
2264 opt_statement_list\r
2265         : /* empty */\r
2266         | statement_list \r
2267         ;\r
2268 \r
2269 statement_list\r
2270         : statement\r
2271         | statement_list statement\r
2272         ;\r
2273 \r
2274 statement\r
2275         : declaration_statement\r
2276           {\r
2277                 if ((Block) $1 != current_block){\r
2278                         current_block.AddStatement ((Statement) $1);\r
2279                         current_block = (Block) $1;\r
2280                 }\r
2281           }\r
2282         | embedded_statement\r
2283           {\r
2284                 current_block.AddStatement ((Statement) $1);\r
2285           }\r
2286         | labeled_statement \r
2287           {\r
2288                 current_block.AddStatement ((Statement) $1);\r
2289           }\r
2290         ;\r
2291 \r
2292 embedded_statement\r
2293         : block\r
2294         | empty_statement\r
2295         | expression_statement\r
2296         | selection_statement\r
2297         | iteration_statement\r
2298         | jump_statement                  \r
2299         | try_statement\r
2300         | checked_statement\r
2301         | unchecked_statement\r
2302         | lock_statement\r
2303         | using_statement\r
2304         ;\r
2305 \r
2306 empty_statement\r
2307         : SEMICOLON\r
2308           {\r
2309                   $$ = new EmptyStatement ();\r
2310           }\r
2311         ;\r
2312 \r
2313 labeled_statement\r
2314         : IDENTIFIER COLON statement\r
2315           {\r
2316                 string lab = (String) $1;\r
2317                 Block block;\r
2318 \r
2319                 block = new Block (current_block, lab);\r
2320                 block.AddStatement ((Statement) $3);\r
2321                 $$ = block;\r
2322 \r
2323                 if (!current_block.AddLabel (lab, block)){\r
2324                         Location l = lexer.Location;\r
2325                         rc.Report.Error (140, l, "The label '" + lab + "' is a duplicate");\r
2326                         $$ = $3;\r
2327                 }       \r
2328           }\r
2329         ;\r
2330 \r
2331 declaration_statement\r
2332         : local_variable_declaration SEMICOLON          // done\r
2333         | local_constant_declaration SEMICOLON          // finishme\r
2334         ;\r
2335 \r
2336 /* \r
2337  * The following is from Rhys' grammar:\r
2338  * > Types in local variable declarations must be recognized as \r
2339  * > expressions to prevent reduce/reduce errors in the grammar.\r
2340  * > The expressions are converted into types during semantic analysis.\r
2341  */\r
2342 local_variable_type\r
2343         : primary_expression type_suffixes\r
2344           { \r
2345                 // FIXME: Do something smart here regarding the composition of the type.\r
2346 \r
2347                 // Ok, the above "primary_expression" is there to get rid of\r
2348                 // both reduce/reduce and shift/reduces in the grammar, it should\r
2349                 // really just be "type_name".  If you use type_name, a reduce/reduce\r
2350                 // creeps up.  If you use qualified_identifier (which is all we need\r
2351                 // really) two shift/reduces appear.\r
2352                 // \r
2353                 // So, instead we do a super trick: we just allow ($1) to be a \r
2354                 // SimpleName Expression.\r
2355                 //\r
2356                 if (((Expression) $1) is SimpleName)\r
2357                         $$ = ((SimpleName) $1).Name;\r
2358                 else {\r
2359                         Location l = lexer.Location;\r
2360                         rc.Report.Error (-1, l, "Invalid Type definition");\r
2361                         $$ = "System.Object";\r
2362                 }\r
2363           }\r
2364         | builtin_types type_suffixes\r
2365           {\r
2366                 $$ = (string) $1 + (string) $2;\r
2367           }\r
2368         ;\r
2369 \r
2370 // FIXME : How can the type of a local variable be void ? I don't quite see ;-)\r
2371 //          | VOID \r
2372 //        {\r
2373 //              // FIXME: this is a string that represents the type\r
2374 //              // Figure out something to make this work.\r
2375 //              $$ = "void";\r
2376 //        }\r
2377 //      ;\r
2378 \r
2379 type_suffixes\r
2380         : /* empty */\r
2381           {\r
2382                 $$ = "";\r
2383           }\r
2384         | type_suffix_list\r
2385         ;\r
2386 \r
2387 type_suffix_list \r
2388         : type_suffix\r
2389         | type_suffix_list type_suffix\r
2390           {\r
2391                 $$ = (string) $1 + (string) $2;\r
2392           }\r
2393         ;\r
2394 \r
2395 type_suffix\r
2396         : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
2397           {\r
2398                 $$ = "[" + (string) $2 + "]";\r
2399           }\r
2400         ;\r
2401 \r
2402 local_variable_declaration\r
2403         : local_variable_type variable_declarators\r
2404           {\r
2405                 $$ = declare_local_variables ((string) $1, (ArrayList) $2);\r
2406           }\r
2407         ;\r
2408 \r
2409 local_constant_declaration\r
2410         : CONST type constant_declarator\r
2411                 // finishme     \r
2412         ;\r
2413 \r
2414 expression_statement\r
2415         : statement_expression SEMICOLON\r
2416           {\r
2417                 $$ = $1;\r
2418           }\r
2419         ;\r
2420 \r
2421         //\r
2422         // We have to do the wrapping here and not in the case above,\r
2423         // because statement_expression is used for example in for_statement\r
2424         //\r
2425 statement_expression\r
2426         : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }\r
2427         | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1); }\r
2428         | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1); }\r
2429         | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }\r
2430         | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1); }\r
2431         | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }\r
2432         | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1); }\r
2433         ;\r
2434 \r
2435 object_creation_expression\r
2436         : object_or_delegate_creation_expression\r
2437           { note ("complain if this is a delegate maybe?"); } \r
2438         ;\r
2439 \r
2440 selection_statement\r
2441         : if_statement\r
2442         | switch_statement\r
2443         ; \r
2444 \r
2445 if_statement\r
2446         : IF OPEN_PARENS boolean_expression CLOSE_PARENS \r
2447           embedded_statement\r
2448           { \r
2449                 $$ = new If ((Expression) $3, (Statement) $5);\r
2450           }\r
2451         | IF OPEN_PARENS boolean_expression CLOSE_PARENS\r
2452           embedded_statement ELSE embedded_statement\r
2453           {\r
2454                 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);\r
2455           }\r
2456         ;\r
2457 \r
2458 switch_statement\r
2459         : SWITCH OPEN_PARENS expression CLOSE_PARENS \r
2460           switch_block\r
2461           {\r
2462                 $$ = new Switch ((Expression) $3, (ArrayList) $5);\r
2463           }\r
2464         ;\r
2465 \r
2466 switch_block\r
2467         : OPEN_BRACE\r
2468           opt_switch_sections\r
2469           CLOSE_BRACE\r
2470           {\r
2471                 $$ = $2;\r
2472           }\r
2473         ;\r
2474 \r
2475 opt_switch_sections\r
2476         : /* empty */           { $$ = new ArrayList (); }\r
2477         | switch_sections\r
2478         ;\r
2479 \r
2480 switch_sections\r
2481         : switch_section \r
2482           {\r
2483                 ArrayList sections = new ArrayList ();\r
2484 \r
2485                 sections.Add ($1);\r
2486                 $$ = sections;\r
2487           }\r
2488         | switch_sections switch_section\r
2489           {\r
2490                 ArrayList sections = (ArrayList) $1;\r
2491 \r
2492                 sections.Add ($2);\r
2493                 $$ = sections;\r
2494           }\r
2495         ;\r
2496 \r
2497 switch_section\r
2498         : switch_labels\r
2499           {\r
2500                 current_block = new Block (current_block);\r
2501           }\r
2502           statement_list \r
2503           {\r
2504                 while (current_block.Implicit)\r
2505                         current_block = current_block.Parent;\r
2506                 $$ = new SwitchSection ((ArrayList) $1, current_block);\r
2507                 current_block = current_block.Parent;\r
2508           }\r
2509         ;\r
2510 \r
2511 switch_labels\r
2512         : switch_label \r
2513           {\r
2514                 ArrayList labels = new ArrayList ();\r
2515 \r
2516                 labels.Add ($1);\r
2517                 $$ = labels;\r
2518           }\r
2519         | switch_labels switch_label \r
2520           {\r
2521                 ArrayList labels = (ArrayList) ($1);\r
2522                 labels.Add ($2);\r
2523 \r
2524                 $$ = labels;\r
2525           }\r
2526         ;\r
2527 \r
2528 switch_label\r
2529         : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2); }\r
2530         | DEFAULT COLON                         { $$ = new SwitchLabel (null); }\r
2531         ;\r
2532 \r
2533 iteration_statement\r
2534         : while_statement\r
2535         | do_statement\r
2536         | for_statement\r
2537         | foreach_statement\r
2538         ;\r
2539 \r
2540 while_statement\r
2541         : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement\r
2542         {\r
2543                 $$ = new While ((Expression) $3, (Statement) $5);\r
2544         }\r
2545         ;\r
2546 \r
2547 do_statement\r
2548         : DO embedded_statement \r
2549           WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON\r
2550           {\r
2551                 $$ = new Do ((Statement) $2, (Expression) $5);\r
2552           }\r
2553         ;\r
2554 \r
2555 for_statement\r
2556         : FOR OPEN_PARENS \r
2557           opt_for_initializer SEMICOLON\r
2558           opt_for_condition SEMICOLON\r
2559           opt_for_iterator CLOSE_PARENS \r
2560           embedded_statement\r
2561           {\r
2562                 $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);\r
2563           }\r
2564         ;\r
2565 \r
2566 opt_for_initializer\r
2567         : /* empty */           { $$ = new EmptyStatement (); }\r
2568         | for_initializer       \r
2569         ;\r
2570 \r
2571 for_initializer\r
2572         : local_variable_declaration\r
2573         | statement_expression_list\r
2574         ;\r
2575 \r
2576 opt_for_condition\r
2577         : /* empty */           { $$ = new BoolLiteral (true); }\r
2578         | boolean_expression\r
2579         ;\r
2580 \r
2581 opt_for_iterator\r
2582         : /* empty */           { $$ = new EmptyStatement (); }\r
2583         | for_iterator\r
2584         ;\r
2585 \r
2586 for_iterator\r
2587         : statement_expression_list\r
2588         ;\r
2589 \r
2590 statement_expression_list\r
2591         : statement_expression  \r
2592           {\r
2593                 Block b = new Block (null, true);\r
2594 \r
2595                 b.AddStatement ((Statement) $1);\r
2596                 $$ = b;\r
2597           }\r
2598         | statement_expression_list COMMA statement_expression\r
2599           {\r
2600                 Block b = (Block) $1;\r
2601 \r
2602                 b.AddStatement ((Statement) $3);\r
2603                 $$ = $1;\r
2604           }\r
2605         ;\r
2606 \r
2607 foreach_statement\r
2608         : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS \r
2609           embedded_statement\r
2610           {\r
2611                 string temp_id = current_block.MakeInternalID ();\r
2612                 ExpressionStatement assign_e;\r
2613                 Expression ma;\r
2614                 Statement getcurrent;\r
2615                 Block foreach_block, child_block;\r
2616 \r
2617                 foreach_block = new Block (current_block, true);\r
2618 \r
2619                 foreach_block.AddVariable ("System.IEnumerator", temp_id);\r
2620                 foreach_block.AddVariable ((string) $3, (string) $4);\r
2621                 assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id), \r
2622                                        new Invocation (\r
2623                                                 new MemberAccess ((Expression) $6, "GetEnumerator"), \r
2624                                                 null, lexer.Location), lexer.Location);\r
2625                 current_block.AddStatement (new StatementExpression (assign_e));\r
2626                 ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");\r
2627                 child_block = new Block (current_block);\r
2628 \r
2629                 getcurrent = new StatementExpression (\r
2630                         new Assign (\r
2631                                 new LocalVariableReference (foreach_block, (string) $4),\r
2632                                 new Cast (\r
2633                                         (string) $3, \r
2634                                         new MemberAccess (\r
2635                                 new LocalVariableReference (foreach_block, temp_id), "Current")), \r
2636                                 lexer.Location));\r
2637 \r
2638                 child_block.AddStatement (getcurrent);\r
2639                 child_block.AddStatement ((Statement) $8);\r
2640                 foreach_block.AddStatement (new While (ma, (Statement) child_block));\r
2641 \r
2642                 $$ = foreach_block;\r
2643           }\r
2644         ;\r
2645 \r
2646 jump_statement\r
2647         : break_statement\r
2648         | continue_statement\r
2649         | goto_statement\r
2650         | return_statement\r
2651         | throw_statement\r
2652         ;\r
2653 \r
2654 break_statement\r
2655         : BREAK SEMICOLON\r
2656           {\r
2657                 $$ = new Break ();\r
2658           }\r
2659         ;\r
2660 \r
2661 continue_statement\r
2662         : CONTINUE SEMICOLON\r
2663           {\r
2664                 $$ = new Continue ();\r
2665           }\r
2666         ;\r
2667 \r
2668 goto_statement\r
2669         : GOTO IDENTIFIER SEMICOLON \r
2670           {\r
2671                 $$ = new Goto ((string) $2);\r
2672           }\r
2673         | GOTO CASE constant_expression SEMICOLON\r
2674         | GOTO DEFAULT SEMICOLON \r
2675         ; \r
2676 \r
2677 return_statement\r
2678         : RETURN opt_expression SEMICOLON\r
2679           {\r
2680                 $$ = new Return ((Expression) $2);\r
2681           }\r
2682         ;\r
2683 \r
2684 throw_statement\r
2685         : THROW opt_expression SEMICOLON\r
2686           {\r
2687                 $$ = new Throw ((Expression) $2);\r
2688           }\r
2689         ;\r
2690 \r
2691 opt_expression\r
2692         : /* empty */\r
2693         | expression\r
2694         ;\r
2695 \r
2696 try_statement\r
2697         : TRY block catch_clauses \r
2698         {\r
2699                 Catch g = null;\r
2700                 ArrayList s = new ArrayList ();\r
2701                 \r
2702                 foreach (Catch cc in (ArrayList) $3) {\r
2703                         if (cc.Type == null)\r
2704                                 g = cc;\r
2705                         else\r
2706                                 s.Add (cc);\r
2707                 }\r
2708 \r
2709                 // Now s contains the list of specific catch clauses\r
2710                 // and g contains the general one.\r
2711                 \r
2712                 $$ = new Try ((Block) $2, s, g, null);\r
2713         }\r
2714         | TRY block opt_catch_clauses FINALLY block\r
2715           {\r
2716                 Catch g = null;\r
2717                 ArrayList s = new ArrayList ();\r
2718                 \r
2719                 foreach (Catch cc in (ArrayList) $3) {\r
2720                         if (cc.Type == null)\r
2721                                 g = cc;\r
2722                         else\r
2723                                 s.Add (cc);\r
2724                 }\r
2725 \r
2726                 $$ = new Try ((Block) $2, s, g, (Block) $5);\r
2727           }\r
2728         ;\r
2729 \r
2730 opt_catch_clauses\r
2731         : /* empty */  { $$ = null; }\r
2732         | catch_clauses\r
2733         ;\r
2734 \r
2735 catch_clauses\r
2736         : catch_clause \r
2737           {\r
2738                 ArrayList l = new ArrayList ();\r
2739 \r
2740                 l.Add ($1);\r
2741                 $$ = l;\r
2742           }\r
2743         | catch_clauses catch_clause\r
2744           {\r
2745                 ArrayList l = (ArrayList) $1;\r
2746 \r
2747                 l.Add ($2);\r
2748                 $$ = l;\r
2749           }\r
2750         ;\r
2751 \r
2752 opt_identifier\r
2753         : /* empty */   { $$ = null; }\r
2754         | IDENTIFIER\r
2755         ;\r
2756 \r
2757 catch_clause \r
2758         : CATCH opt_catch_args block\r
2759         {\r
2760                 string type = null;\r
2761                 string id = null;\r
2762                 \r
2763                 if ($2 != null) {\r
2764                         DictionaryEntry cc = (DictionaryEntry) $2;\r
2765                         type = (string) cc.Key;\r
2766                         id   = (string) cc.Value;\r
2767                 }\r
2768 \r
2769                 $$ = new Catch (type, id, (Block) $3);\r
2770         }\r
2771         ;\r
2772 \r
2773 opt_catch_args\r
2774         : /* empty */ { $$ = null; }\r
2775         | catch_args\r
2776         ;         \r
2777 \r
2778 catch_args \r
2779         : OPEN_PARENS type opt_identifier CLOSE_PARENS \r
2780         {\r
2781                 $$ = new DictionaryEntry ($2, $3);\r
2782         }\r
2783         ;\r
2784 \r
2785 checked_statement\r
2786         : CHECKED block\r
2787           {\r
2788                 $$ = new Checked ((Block) $2);\r
2789           }\r
2790         ;\r
2791 \r
2792 unchecked_statement\r
2793         : UNCHECKED block\r
2794           {\r
2795                 $$ = new Unchecked ((Block) $2);\r
2796           }\r
2797         ;\r
2798 \r
2799 lock_statement\r
2800         : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement\r
2801           {\r
2802                 $$ = new Lock ((Expression) $3, (Statement) $5);\r
2803           }\r
2804         ;\r
2805 \r
2806 using_statement\r
2807         : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement\r
2808           // finishme\r
2809         ; \r
2810 \r
2811 resource_acquisition\r
2812         : local_variable_declaration\r
2813           expression\r
2814           // finishme\r
2815         ;\r
2816 \r
2817 %%\r
2818 \r
2819 // <summary>\r
2820 //   A class used to pass around variable declarations and constants\r
2821 // </summary>\r
2822 public class VariableDeclaration {\r
2823         public string identifier;\r
2824         public object expression_or_array_initializer;\r
2825 \r
2826         public VariableDeclaration (string id, object eoai){\r
2827                 this.identifier = id;\r
2828                 this.expression_or_array_initializer = eoai;\r
2829         }\r
2830 }\r
2831 \r
2832 // <summary>\r
2833 //   A class used to hold info about an indexer declarator\r
2834 // </summary>\r
2835 \r
2836 public class IndexerDeclaration {\r
2837         public string type;\r
2838         public string interface_type;\r
2839         public Parameters param_list;\r
2840 \r
2841         public IndexerDeclaration (string type, string interface_type, Parameters param_list)\r
2842         {\r
2843                 this.type = type;\r
2844                 this.interface_type = interface_type;\r
2845                 this.param_list = param_list;\r
2846         }\r
2847 }\r
2848 \r
2849 // <summary>\r
2850 //  A class used to hold info about an operator declarator\r
2851 // </summary>\r
2852 \r
2853 public class OperatorDeclaration {\r
2854         public Operator.OpType optype;\r
2855         public string ret_type;\r
2856         public string arg1type;\r
2857         public string arg1name;\r
2858         public string arg2type;\r
2859         public string arg2name;\r
2860 \r
2861         public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,\r
2862                                     string arg2type, string arg2name)\r
2863         {\r
2864                 optype = op;\r
2865                 this.ret_type = ret_type;\r
2866                 this.arg1type = arg1type;\r
2867                 this.arg1name = arg1name;\r
2868                 this.arg2type = arg2type;\r
2869                 this.arg2name = arg2name;\r
2870         }\r
2871 \r
2872 }\r
2873 \r
2874 // <summary>\r
2875 //   Given the @class_name name, it creates a fully qualified name\r
2876 //   based on the containing declaration space\r
2877 // </summary>\r
2878 string \r
2879 MakeName (string class_name)\r
2880 {\r
2881         string ns = current_namespace.Name;\r
2882         string container_name = current_container.Name;\r
2883 \r
2884         if (container_name == ""){\r
2885                 if (ns != "")\r
2886                         return ns + "." + class_name;\r
2887                 else\r
2888                         return class_name;\r
2889         } else\r
2890                 return container_name + "." + class_name;\r
2891 }\r
2892 \r
2893 // <summary>\r
2894 //   Used to report back to the user the result of a declaration\r
2895 //   in the current declaration space\r
2896 // </summary>\r
2897 void \r
2898 CheckDef (DeclSpace.AdditionResult result, string name)\r
2899 {\r
2900         if (result == DeclSpace.AdditionResult.Success)\r
2901                 return;\r
2902 \r
2903         Location l = lexer.Location;\r
2904         \r
2905         switch (result){\r
2906         case DeclSpace.AdditionResult.NameExists:\r
2907                 rc.Report.Error (102, l, "The namespace `" + current_container.Name + \r
2908                                  "' already contains a definition for `"+\r
2909                                  name + "'");\r
2910                 break;\r
2911 \r
2912 \r
2913 //      NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:\r
2914 //\r
2915 //      case DeclSpace.AdditionResult.MethodDuplicated:\r
2916 //              error (111, "Class `"+current_container.Name+\r
2917 //                          "' already defines a member called '" + \r
2918 //                          name + "' with the same parameter types");\r
2919 //              break;\r
2920 \r
2921         case DeclSpace.AdditionResult.EnclosingClash:\r
2922                 rc.Report.Error (542, l, "Member names cannot be the same as their enclosing type");\r
2923                 break;\r
2924                 \r
2925         case DeclSpace.AdditionResult.NotAConstructor:\r
2926                 rc.Report.Error (1520, l, "Class, struct, or interface method must have a return type");\r
2927                 break;\r
2928         }\r
2929 }\r
2930 \r
2931 void \r
2932 CheckDef (bool result, string name)\r
2933 {\r
2934         if (result)\r
2935                 return;\r
2936         CheckDef (DeclSpace.AdditionResult.NameExists, name);\r
2937 }\r
2938 \r
2939 object \r
2940 SimpleLookup (string name)\r
2941 {\r
2942         //\r
2943         // we need to check against current_block not being null\r
2944         // as `expression' is allowed in argument_lists, which \r
2945         // do not exist inside a block.  \r
2946         //\r
2947         if (current_block != null){\r
2948                 if (current_block.IsVariableDefined (name))\r
2949                         return new LocalVariableReference (current_block, name);\r
2950         }\r
2951 \r
2952         if (current_local_parameters != null){\r
2953                 int idx;\r
2954                 Parameter par = current_local_parameters.GetParameterByName (name, out idx);\r
2955                 if (par != null)\r
2956                         return new ParameterReference (current_local_parameters, idx, name);\r
2957         }\r
2958 \r
2959         return null;\r
2960 }\r
2961 \r
2962 // \r
2963 // Assumes that the name contains a `.' and tries to perform a simple lookup\r
2964 // and shape the result to be a MemberAccess on a Local/Parameter\r
2965 //\r
2966 object CompositeLookup (string name)\r
2967 {\r
2968         int pos = name.IndexOf (".");\r
2969         string left = name.Substring (0, pos);\r
2970         object o;\r
2971 \r
2972         o = SimpleLookup (left);\r
2973         if (o != null){\r
2974                 string right = name.Substring (pos + 1);\r
2975                 return new MemberAccess ((Expression) o, right);\r
2976         }\r
2977 \r
2978         return null;\r
2979 }\r
2980 \r
2981 object QualifiedIdentifier (string name, Location l)\r
2982 {\r
2983         object o;\r
2984 \r
2985         if (name.IndexOf ('.') == -1)\r
2986                 o = SimpleLookup (name);\r
2987         else \r
2988                 o = CompositeLookup (name);\r
2989 \r
2990         if (o == null)\r
2991                 o = new SimpleName (name, l);\r
2992 \r
2993         return o;\r
2994 }\r
2995 \r
2996 Block declare_local_variables (string type, ArrayList variable_declarators)\r
2997 {\r
2998         Block implicit_block;\r
2999         ArrayList inits = null;\r
3000 \r
3001         //\r
3002         // We use the `Used' property to check whether statements\r
3003         // have been added to the current block.  If so, we need\r
3004         // to create another block to contain the new declaration\r
3005         // otherwise, as an optimization, we use the same block to\r
3006         // add the declaration.\r
3007         //\r
3008         // FIXME: A further optimization is to check if the statements\r
3009         // that were added were added as part of the initialization\r
3010         // below.  In which case, no other statements have been executed\r
3011         // and we might be able to reduce the number of blocks for\r
3012         // situations like this:\r
3013         //\r
3014         // int j = 1;  int k = j + 1;\r
3015         //\r
3016         if (current_block.Used)\r
3017                 implicit_block = new Block (current_block, true);\r
3018         else\r
3019                 implicit_block = new Block (current_block, true);\r
3020 \r
3021         foreach (VariableDeclaration decl in variable_declarators){\r
3022                 if (implicit_block.AddVariable (type, decl.identifier)){\r
3023                         if (decl.expression_or_array_initializer != null){\r
3024                                 if (inits == null)\r
3025                                         inits = new ArrayList ();\r
3026                                 inits.Add (decl);\r
3027                         }\r
3028                 } else {\r
3029                         Location l = lexer.Location;\r
3030                         rc.Report.Error (128, l, "A local variable `" + decl.identifier +\r
3031                                          "' is already defined in this scope");\r
3032                 }\r
3033         }\r
3034 \r
3035         if (inits == null)\r
3036                 return implicit_block;\r
3037 \r
3038         foreach (VariableDeclaration decl in inits){\r
3039                 if (decl.expression_or_array_initializer is Expression){\r
3040                         Expression expr = (Expression) decl.expression_or_array_initializer;\r
3041                         Assign assign;\r
3042                         \r
3043                         assign = new Assign (new LocalVariableReference (\r
3044                                                 implicit_block, decl.identifier), \r
3045                                              expr, lexer.Location);\r
3046                         implicit_block.AddStatement (new StatementExpression (assign));\r
3047                 } else {\r
3048                         Console.WriteLine ("Not handling Array initializers yet");\r
3049                 }\r
3050         }\r
3051                         \r
3052         return implicit_block;\r
3053 }\r
3054 \r
3055 void CheckConstant (Expression expr)\r
3056 {\r
3057         // finishme\r
3058 }\r
3059 \r
3060 void CheckBoolean (Expression expr)\r
3061 {\r
3062         // finishme\r
3063 }\r
3064 \r
3065 void CheckAttributeTarget (string a)\r
3066 {\r
3067         switch (a) {\r
3068 \r
3069         case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :\r
3070                 return;\r
3071                 \r
3072         default :\r
3073                 Location l = lexer.Location;\r
3074                 rc.Report.Error (658, l, "Invalid attribute target");\r
3075                 break;\r
3076         }\r
3077 \r
3078 }\r
3079 \r
3080 void CheckUnaryOperator (Operator.OpType op)\r
3081 {\r
3082         switch (op) {\r
3083                 \r
3084         case Operator.OpType.Negate: \r
3085         case Operator.OpType.BitComplement: \r
3086         case Operator.OpType.Increment:\r
3087         case Operator.OpType.Decrement:\r
3088         case Operator.OpType.True: \r
3089         case Operator.OpType.False: \r
3090         case Operator.OpType.Addition: \r
3091         case Operator.OpType.Subtraction:\r
3092                 \r
3093                 break;\r
3094                 \r
3095         default :\r
3096                 Location l = lexer.Location;\r
3097                 rc.Report.Error (1019, l, "Overloadable unary operator expected"); \r
3098                 break;\r
3099                 \r
3100         }\r
3101 }\r
3102 \r
3103 void CheckBinaryOperator (Operator.OpType op)\r
3104 {\r
3105         switch (op) {\r
3106                 \r
3107         case Operator.OpType.Addition: \r
3108         case Operator.OpType.Subtraction: \r
3109         case Operator.OpType.Multiply:\r
3110         case Operator.OpType.Division:\r
3111         case Operator.OpType.Modulus: \r
3112         case Operator.OpType.BitwiseAnd: \r
3113         case Operator.OpType.BitwiseOr:\r
3114         case Operator.OpType.ExclusiveOr: \r
3115         case Operator.OpType.LeftShift: \r
3116         case Operator.OpType.RightShift:\r
3117         case Operator.OpType.Equality: \r
3118         case Operator.OpType.Inequality:\r
3119         case Operator.OpType.GreaterThan: \r
3120         case Operator.OpType.LessThan: \r
3121         case Operator.OpType.GreaterThanOrEqual:\r
3122         case Operator.OpType.LessThanOrEqual:\r
3123                 break;\r
3124                 \r
3125         default :\r
3126                 Location l = lexer.Location;\r
3127                 rc.Report.Error (1020, l, "Overloadable binary operator expected");\r
3128                 break;\r
3129         }\r
3130         \r
3131 }\r
3132 \r
3133 void output (string s)\r
3134 {\r
3135         Console.WriteLine (s);\r
3136 }\r
3137 \r
3138 void note (string s)\r
3139 {\r
3140         // Used to put annotations\r
3141 }\r
3142 \r
3143 Tokenizer lexer;\r
3144 \r
3145 public Tokenizer Lexer {\r
3146         get {\r
3147                 return lexer;\r
3148         }\r
3149 }                  \r
3150 \r
3151 public CSharpParser(RootContext rc, string name, System.IO.Stream input) \r
3152 {\r
3153         current_namespace = new Namespace (null, "");\r
3154         this.rc   = rc;\r
3155         this.tree = rc.Tree;\r
3156         this.name = name;\r
3157         this.input = input;\r
3158         current_container = tree.Types;\r
3159         current_container.Namespace = current_namespace;\r
3160 \r
3161         lexer = new Tokenizer (input, name);\r
3162 }\r
3163 \r
3164 public override int parse ()\r
3165 {\r
3166         StringBuilder value = new StringBuilder ();\r
3167 \r
3168         global_errors = 0;\r
3169         try {\r
3170                 if (yacc_verbose_flag)\r
3171                         yyparse (lexer, new yydebug.yyDebugSimple ());\r
3172                 else\r
3173                         yyparse (lexer);\r
3174         } catch (Exception e){\r
3175                 // Console.WriteLine ("Fatal error: " + name);\r
3176                 // Console.WriteLine (lexer.location);\r
3177 \r
3178                 Console.WriteLine (lexer.location + "  : Parsing error");\r
3179                 Console.WriteLine (e);\r
3180                 global_errors++;\r
3181         }\r
3182         \r
3183         return global_errors;\r
3184 }\r
3185 \r
3186 \r
3187 /* end end end */\r
3188 }\r