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