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