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