3 // cs-parser.jay: The Parser for the C# compiler
\r
5 // Author: Miguel de Icaza (miguel@gnu.org)
\r
7 // Licensed under the terms of the GNU GPL
\r
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
\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
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
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
32 using System.Collections;
\r
37 public class CSharpParser {
\r
38 static int global_errors;
\r
40 Namespace current_namespace;
\r
41 TypeContainer current_container;
\r
44 // Current block is used to add statements as we find
\r
48 Block current_block;
\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
55 Interface current_interface;
\r
58 // This is used by the unary_expression code to resolve
\r
59 // a name against a parameter.
\r
61 Parameters current_local_parameters;
\r
64 // Using during property parsing to describe the implicit
\r
65 // value parameter that is passed to the "set" accesor
\r
68 Parameter [] implicit_value_parameters;
\r
71 // Used to record all types defined
\r
76 // Name of the file we are parsing
\r
79 // Input stream to parse from.
\r
80 public System.IO.Stream input;
\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
90 *These are the C# keywords
\r
170 /* C# keywords which are not really keywords */
\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
184 %token SEMICOLON ";"
\r
193 %token BITWISE_AND "&"
\r
194 %token BITWISE_OR "|"
\r
201 /* C# multi-character operators. */
\r
204 %token OP_SHIFT_LEFT "<<"
\r
205 %token OP_SHIFT_RIGHT ">>"
\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
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
234 /* Add precedence rules to solve dangling else s/r conflict */
\r
243 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
\r
245 %left STAR DIV PERCENT
\r
246 %right BANG CARRET UMINUS
\r
247 %nonassoc OP_INC OP_DEC
\r
249 %left OPEN_BRACKET OPEN_BRACE
\r
253 %start compilation_unit
\r
254 /*%start namespace_declaration */
\r
258 : opt_using_directives opt_attributes opt_namespace_member_declarations
\r
261 // At some point check that using only comes *before* any namespaces
\r
267 | using_directives using_directive
\r
271 : using_alias_directive
\r
272 | using_namespace_directive
\r
275 using_alias_directive
\r
276 : USING IDENTIFIER ASSIGN
\r
277 namespace_or_type_name SEMICOLON {
\r
281 using_namespace_directive
\r
282 : USING namespace_name SEMICOLON
\r
284 current_namespace.Using ((string) $2);
\r
288 namespace_declarations
\r
289 : namespace_declaration
\r
290 | namespace_declarations namespace_declaration
\r
292 namespace_declaration
\r
293 : NAMESPACE qualified_identifier
\r
295 current_namespace = new Namespace (current_namespace, (string) $2);
\r
297 namespace_body opt_semicolon
\r
299 current_namespace = current_namespace.Parent;
\r
313 qualified_identifier
\r
315 | qualified_identifier DOT IDENTIFIER {
\r
316 $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
\r
321 : namespace_or_type_name
\r
326 opt_using_directives
\r
327 opt_namespace_member_declarations
\r
332 opt_using_directives
\r
337 opt_namespace_member_declarations
\r
339 | namespace_member_declarations
\r
342 namespace_member_declarations
\r
343 : namespace_member_declaration
\r
344 | namespace_member_declarations namespace_member_declaration
\r
347 namespace_member_declaration
\r
354 Class c = (Class) $1;
\r
355 mod_flags = c.ModFlags;
\r
357 } else if ($1 is Struct){
\r
358 Struct s = (Struct) $1;
\r
359 mod_flags = s.ModFlags;
\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
371 | namespace_declaration
\r
375 : class_declaration
\r
376 | struct_declaration
\r
377 | interface_declaration
\r
378 | enum_declaration
\r
379 | delegate_declaration // finishme
\r
387 | attribute_section opt_attributes
\r
392 opt_attribute_target_specifier attribute_list
\r
393 /* FIXME: opt_comma */
\r
397 opt_attribute_target_specifier
\r
399 | attribute_target_specifier
\r
402 attribute_target_specifier
\r
403 : attribute_target COLON
\r
408 // if (Collection.Contains ($$))... FIXME
\r
409 note ("Allows: assembly, field, method, module, param, property, type");
\r
417 | attribute_list COMMA attribute
\r
422 | opt_attribute_arguments
\r
426 : type_name { /* reserved attribute name or identifier: 17.4 */ }
\r
429 opt_attribute_arguments
\r
431 | OPEN_PARENS attribute_arguments CLOSE_PARENS
\r
434 attribute_arguments
\r
436 | attribute_arguments COMMA expression
\r
440 opt_dimension_separators
\r
442 | dimension_separators
\r
445 dimension_separators
\r
447 | dimension_separators COMMA
\r
451 : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
\r
454 opt_class_member_declarations
\r
456 | class_member_declarations
\r
459 class_member_declarations
\r
460 : class_member_declaration
\r
461 | class_member_declarations
\r
462 class_member_declaration
\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
484 string full_struct_name = MakeName ((string) $4);
\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
491 opt_struct_interfaces
\r
495 Struct new_struct = (Struct) current_container;
\r
497 current_container = current_container.Parent;
\r
498 CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
\r
503 opt_struct_interfaces
\r
505 | struct_interfaces
\r
510 | struct_interfaces struct_interface
\r
518 : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
\r
521 opt_struct_member_declarations
\r
523 | struct_member_declarations
\r
526 struct_member_declarations
\r
527 : struct_member_declaration
\r
528 | struct_member_declarations struct_member_declaration
\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
543 constant_declaration
\r
548 constant_declarators
\r
551 Modifiers.Check (Constant.AllowedModifiers, (int) $2, Modifiers.PRIVATE);
\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
558 CheckDef (current_container.AddConstant (c), c.Name);
\r
563 constant_declarators
\r
564 : constant_declarator
\r
566 ArrayList constants = new ArrayList ();
\r
567 constants.Add ($1);
\r
570 | constant_declarators COMMA constant_declarator
\r
572 ArrayList constants = (ArrayList) $1;
\r
574 constants.Add ($3);
\r
578 constant_declarator
\r
579 : IDENTIFIER ASSIGN constant_expression {
\r
580 $$ = new DictionaryEntry ($1, $3);
\r
588 variable_declarators
\r
591 string type = (string) $3;
\r
592 int mod = (int) $2;
\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
598 CheckDef (current_container.AddField (field), field.Name);
\r
604 variable_declarators
\r
605 : variable_declarator
\r
607 ArrayList decl = new ArrayList ();
\r
611 | variable_declarators COMMA variable_declarator
\r
613 ArrayList decls = (ArrayList) $1;
\r
619 variable_declarator
\r
620 : IDENTIFIER ASSIGN variable_initializer
\r
622 $$ = new VariableDeclaration ((string) $1, $3);
\r
626 $$ = new VariableDeclaration ((string) $1, null);
\r
630 variable_initializer
\r
632 | array_initializer
\r
639 Method method = (Method) $1;
\r
641 method.Block = (Block) $2;
\r
642 CheckDef (current_container.AddMethod (method), method.Name);
\r
644 current_local_parameters = null;
\r
653 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
655 Method method = new Method ((string) $3, (int) $2, (string) $4, (Parameters) $6);
\r
657 current_local_parameters = (Parameters) $6;
\r
665 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
667 Method method = new Method ("void", (int) $2, (string) $4, (Parameters) $6);
\r
669 current_local_parameters = (Parameters) $6;
\r
676 | SEMICOLON { $$ = null; }
\r
679 opt_formal_parameter_list
\r
680 : /* empty */ { $$ = new Parameters (null, null); }
\r
681 | formal_parameter_list
\r
684 formal_parameter_list
\r
685 : fixed_parameters
\r
687 ArrayList pars_list = (ArrayList) $1;
\r
689 Parameter [] pars = new Parameter [pars_list.Count];
\r
690 pars_list.CopyTo (pars);
\r
692 $$ = new Parameters (pars, null);
\r
694 | fixed_parameters COMMA parameter_array
\r
696 ArrayList pars_list = (ArrayList) $1;
\r
698 Parameter [] pars = new Parameter [pars_list.Count];
\r
699 pars_list.CopyTo (pars);
\r
701 $$ = new Parameters (pars, (Parameter) $3);
\r
705 $$ = new Parameters (null, (Parameter) $1);
\r
712 ArrayList pars = new ArrayList ();
\r
717 | fixed_parameters COMMA fixed_parameter
\r
719 ArrayList pars = (ArrayList) $1;
\r
728 opt_parameter_modifier
\r
732 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2);
\r
736 opt_parameter_modifier
\r
737 : /* empty */ { $$ = Parameter.Modifier.NONE; }
\r
738 | parameter_modifier
\r
742 : REF { $$ = Parameter.Modifier.REF; }
\r
743 | OUT { $$ = Parameter.Modifier.OUT; }
\r
747 : opt_attributes PARAMS type IDENTIFIER
\r
749 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS);
\r
750 note ("type must be a single-dimension array type");
\r
755 : IDENTIFIER { $$ = $1.ToString (); }
\r
756 | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
\r
759 property_declaration
\r
765 Parameter implicit_value_parameter;
\r
766 implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE);
\r
768 lexer.properties = true;
\r
770 implicit_value_parameters = new Parameter [1];
\r
771 implicit_value_parameters [0] = implicit_value_parameter;
\r
773 accessor_declarations
\r
775 lexer.properties = false;
\r
780 DictionaryEntry pair = (DictionaryEntry) $7;
\r
781 Block get_block = null;
\r
782 Block set_block = null;
\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
789 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block);
\r
791 CheckDef (current_container.AddProperty (prop), prop.Name);
\r
792 implicit_value_parameters = null;
\r
796 accessor_declarations
\r
797 : get_accessor_declaration opt_set_accessor_declaration
\r
799 $$ = new DictionaryEntry ($1, $2);
\r
801 | set_accessor_declaration opt_get_accessor_declaration
\r
803 $$ = new DictionaryEntry ($2, $1);
\r
807 opt_get_accessor_declaration
\r
808 : /* empty */ { $$ = null; }
\r
809 | get_accessor_declaration
\r
812 opt_set_accessor_declaration
\r
813 : /* empty */ { $$ = null; }
\r
814 | set_accessor_declaration
\r
817 get_accessor_declaration
\r
818 : opt_attributes GET accessor_body
\r
824 set_accessor_declaration
\r
825 : opt_attributes SET
\r
827 current_local_parameters = new Parameters (implicit_value_parameters, null);
\r
832 current_local_parameters = null;
\r
838 | SEMICOLON { $$ = new Block (null); }
\r
841 interface_declaration
\r
844 INTERFACE IDENTIFIER
\r
846 Interface new_interface;
\r
847 string full_interface_name = MakeName ((string) $4);
\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
858 Interface new_interface = (Interface) current_interface;
\r
861 new_interface.Bases = (ArrayList) $6;
\r
863 current_interface = null;
\r
864 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
\r
869 : /* empty */ { $$ = null; }
\r
874 : COLON interface_type_list { $$ = $2; }
\r
877 interface_type_list
\r
880 ArrayList interfaces = new ArrayList ();
\r
882 interfaces.Add ($1);
\r
885 | interface_type_list COMMA interface_type
\r
887 ArrayList interfaces = (ArrayList) $1;
\r
888 interfaces.Add ($3);
\r
895 opt_interface_member_declarations
\r
899 opt_interface_member_declarations
\r
901 | interface_member_declarations
\r
904 interface_member_declarations
\r
905 : interface_member_declaration
\r
906 | interface_member_declarations interface_member_declaration
\r
909 interface_member_declaration
\r
910 : interface_method_declaration
\r
912 InterfaceMethod m = (InterfaceMethod) $1;
\r
914 CheckDef (current_interface.AddMethod (m), m.Name);
\r
916 | interface_property_declaration
\r
918 InterfaceProperty p = (InterfaceProperty) $1;
\r
920 CheckDef (current_interface.AddProperty (p), p.Name);
\r
922 | interface_event_declaration
\r
924 InterfaceEvent e = (InterfaceEvent) $1;
\r
926 CheckDef (current_interface.AddEvent (e), e.Name);
\r
928 | interface_indexer_declaration
\r
930 InterfaceIndexer i = (InterfaceIndexer) $1;
\r
932 CheckDef (current_interface.AddIndexer (i), "indexer");
\r
937 : /* empty */ { $$ = false; }
\r
938 | NEW { $$ = true; }
\r
941 interface_method_declaration
\r
942 : opt_attributes opt_new type IDENTIFIER
\r
943 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
946 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6);
\r
948 | opt_attributes opt_new VOID IDENTIFIER
\r
949 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
952 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6);
\r
956 interface_property_declaration
\r
961 { lexer.properties = true; }
\r
962 interface_accesors
\r
963 { lexer.properties = false; }
\r
968 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2,
\r
969 (gs & 1) == 1, (gs & 2) == 2);
\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
978 | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
\r
982 interface_event_declaration
\r
983 : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
\r
985 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2);
\r
989 interface_indexer_declaration
\r
990 : opt_attributes opt_new type THIS
\r
991 OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
993 { lexer.properties = true; }
\r
994 interface_accesors
\r
995 { lexer.properties = false; }
\r
998 int a_flags = (int) $10;
\r
1000 bool do_get = (a_flags & 1) == 1;
\r
1001 bool do_set = (a_flags & 2) == 2;
\r
1003 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2);
\r
1007 operator_declaration
\r
1008 : opt_attributes opt_modifiers operator_declarator block
\r
1010 // FIXME: validate that opt_modifiers is exactly: PUBLIC and STATIC
\r
1014 operator_declarator
\r
1015 : type OPERATOR overloadable_operator
\r
1016 OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1018 // FIXME: since reduce/reduce on this
\r
1019 // rule, validate overloadable_operator is unary
\r
1021 | type OPERATOR overloadable_operator
\r
1023 type IDENTIFIER COMMA
\r
1027 // FIXME: because of the reduce/reduce on PLUS and MINUS
\r
1028 // validate overloadable_operator is binary
\r
1030 | conversion_operator_declarator
\r
1033 overloadable_operator
\r
1034 // Unary operators:
\r
1041 // Unary and binary:
\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
1066 constructor_declaration
\r
1069 constructor_declarator
\r
1072 Constructor c = (Constructor) $3;
\r
1073 c.Block = (Block) $4;
\r
1074 c.ModFlags = (int) $2;
\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
1081 CheckDef (current_container.AddConstructor (c), c.Name);
\r
1083 current_local_parameters = null;
\r
1087 constructor_declarator
\r
1089 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
1090 opt_constructor_initializer
\r
1092 ConstructorInitializer i = null;
\r
1095 i = new ConstructorBaseInitializer (null);
\r
1097 i = (ConstructorInitializer) $5;
\r
1099 $$ = new Constructor ((string) $1, (Parameters) $3, i);
\r
1101 current_local_parameters = (Parameters) $3;
\r
1105 opt_constructor_initializer
\r
1106 : /* empty */ { $$ = null; }
\r
1107 | constructor_initializer
\r
1110 constructor_initializer
\r
1111 : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1113 $$ = new ConstructorBaseInitializer ((ArrayList) $4);
\r
1115 | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1117 $$ = new ConstructorThisInitializer ((ArrayList) $4);
\r
1121 destructor_declaration
\r
1122 : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
\r
1124 Method d = new Method ("System.Void", 0, "Finalize", new Parameters (null, null));
\r
1126 d.Block = (Block) $6;
\r
1127 CheckDef (current_container.AddMethod (d), d.Name);
\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
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
1143 event_accesor_declarations
\r
1144 : add_accessor_declaration remove_accessor_declaration
\r
1145 | remove_accessor_declaration add_accessor_declaration
\r
1148 add_accessor_declaration
\r
1149 : opt_attributes ADD block
\r
1152 remove_accessor_declaration
\r
1153 : opt_attributes REMOVE block
\r
1156 indexer_declaration
\r
1157 : opt_attributes opt_modifiers indexer_declarator
\r
1159 { lexer.properties = true; }
\r
1160 accessor_declarations
\r
1161 { lexer.properties = false; }
\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
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
1183 string name = (string) $4;
\r
1184 Enum e = new Enum ((string) $5, (int) $2, name);
\r
1186 foreach (VariableDeclaration ev in (ArrayList) $6){
\r
1190 (Expression) ev.expression_or_array_initializer),
\r
1194 CheckDef (current_container.AddEnum (e), name);
\r
1199 : /* empty */ { $$ = "System.Int32"; }
\r
1200 | COLON integral_type { $$ = $2; }
\r
1204 : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
\r
1210 opt_enum_member_declarations
\r
1211 : /* empty */ { $$ = new ArrayList (); }
\r
1212 | enum_member_declarations opt_comma { $$ = $1; }
\r
1215 enum_member_declarations
\r
1216 : enum_member_declaration
\r
1218 ArrayList l = new ArrayList ();
\r
1223 | enum_member_declarations COMMA enum_member_declaration
\r
1225 ArrayList l = (ArrayList) $1;
\r
1233 enum_member_declaration
\r
1234 : opt_attributes IDENTIFIER
\r
1236 $$ = new VariableDeclaration ((string) $2, null);
\r
1238 | opt_attributes IDENTIFIER ASSIGN expression
\r
1240 $$ = new VariableDeclaration ((string) $2, $4);
\r
1244 delegate_declaration
\r
1248 IDENTIFIER OPEN_PARENS
\r
1249 formal_parameter_list
\r
1252 { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }
\r
1257 IDENTIFIER OPEN_PARENS
\r
1258 formal_parameter_list
\r
1261 { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }
\r
1265 : namespace_or_type_name
\r
1268 namespace_or_type_name
\r
1269 : qualified_identifier
\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
1279 : type_name { /* class_type */
\r
1281 This does interfaces, delegates, struct_types, class_types,
\r
1282 parent classes, and more! 4.2
\r
1293 ArrayList types = new ArrayList ();
\r
1298 | type_list COMMA type
\r
1300 ArrayList types = (ArrayList) $1;
\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
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
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
1338 : type rank_specifiers
\r
1341 // FIXME: We need to create a type for the nested thing.
\r
1346 // Expressions, section 7.5
\r
1348 primary_expression
\r
1351 // 7.5.1: Literals
\r
1355 | qualified_identifier
\r
1357 string name = (string) $1;
\r
1360 if (name.IndexOf ('.') == -1){
\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
1366 if (current_block != null){
\r
1367 if (current_block.IsVariableDefined (name))
\r
1368 $$ = new LocalVariableReference (current_block, name);
\r
1370 if (($$ == null) && (current_local_parameters != null)){
\r
1371 Parameter par = current_local_parameters.GetParameterByName (name);
\r
1373 $$ = new ParameterReference (current_local_parameters, name);
\r
1377 $$ = new SimpleName (name);
\r
1379 | parenthesized_expression
\r
1381 | invocation_expression
\r
1385 | post_increment_expression
\r
1386 | post_decrement_expression
\r
1388 | typeof_expression
\r
1389 | sizeof_expression
\r
1390 | checked_expression
\r
1391 | unchecked_expression
\r
1398 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
\r
1399 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
\r
1400 | NULL { $$ = new NullLiteral (); }
\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
1410 : LITERAL_INTEGER { $$ = new IntLiteral ((Int32) lexer.Value); }
\r
1414 : TRUE { $$ = new BoolLiteral (true); }
\r
1415 | FALSE { $$ = new BoolLiteral (false); }
\r
1418 parenthesized_expression
\r
1419 : OPEN_PARENS expression CLOSE_PARENS
\r
1424 : primary_expression DOT IDENTIFIER
\r
1426 $$ = new MemberAccess ((Expression) $1, (string) $3);
\r
1428 | predefined_type DOT IDENTIFIER
\r
1430 $$ = new BuiltinTypeAccess ((string) $1, (string) $3);
\r
1438 invocation_expression
\r
1439 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1442 // if $1 is MethodGroup
\r
1443 // $$ = new Call ($1, $3);
\r
1445 // $$ = new DelegateCall ($1, $3);
\r
1447 error (1, "THIS IS CRAZY");
\r
1449 $$ = new Invocation ((Expression) $1, (ArrayList) $3);
\r
1454 : /* empty */ { $$ = null; }
\r
1461 ArrayList list = new ArrayList ();
\r
1465 | argument_list COMMA argument
\r
1467 ArrayList list = (ArrayList) $1;
\r
1476 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
\r
1478 | REF variable_reference
\r
1480 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
\r
1482 | OUT variable_reference
\r
1484 $$ = new Argument ((Expression) $2, Argument.AType.Out);
\r
1488 variable_reference
\r
1489 : expression { note ("section 5.4"); $$ = $1; }
\r
1493 : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1499 | expression_list COMMA expression
\r
1510 : BASE DOT IDENTIFIER
\r
1512 | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1516 post_increment_expression
\r
1517 : primary_expression OP_INC
\r
1519 $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1);
\r
1523 post_decrement_expression
\r
1524 : primary_expression OP_DEC
\r
1526 $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1);
\r
1531 : object_or_delegate_creation_expression
\r
1532 | array_creation_expression
\r
1535 object_or_delegate_creation_expression
\r
1536 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1538 $$ = new New ((string) $2, (ArrayList) $4);
\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
1549 opt_rank_specifier
\r
1556 | rank_specifier rank_specifiers
\r
1561 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
1565 opt_dim_separators
\r
1573 | dim_separators COMMA
\r
1577 opt_array_initializer
\r
1579 | array_initializer
\r
1583 : OPEN_BRACE CLOSE_BRACE
\r
1584 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
\r
1588 variable_initializer_list
\r
1589 : variable_initializer
\r
1590 | variable_initializer_list COMMA variable_initializer
\r
1595 : TYPEOF OPEN_PARENS type CLOSE_PARENS
\r
1597 $$ = new TypeOf ((string) $3);
\r
1602 : SIZEOF OPEN_PARENS type CLOSE_PARENS {
\r
1603 $$ = new SizeOf ((string) $3);
\r
1605 note ("Verify type is unmanaged");
\r
1606 note ("if (5.8) builtin, yield constant expression");
\r
1610 checked_expression
\r
1611 : CHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1614 unchecked_expression
\r
1615 : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1619 : primary_expression
\r
1620 | PLUS unary_expression {
\r
1621 $$ = new Unary (Unary.Operator.Plus, (Expression) $2);
\r
1623 | MINUS unary_expression
\r
1625 $$ = new Unary (Unary.Operator.Minus, (Expression) $2);
\r
1627 | BANG unary_expression
\r
1629 $$ = new Unary (Unary.Operator.Negate, (Expression) $2);
\r
1631 | TILDE unary_expression
\r
1633 $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2);
\r
1635 | STAR unary_expression
\r
1637 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2);
\r
1639 | BITWISE_AND unary_expression
\r
1641 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);
\r
1643 | OP_INC unary_expression
\r
1645 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1647 | OP_DEC unary_expression
\r
1649 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1651 | cast_expression
\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
1659 pre_increment_expression
\r
1660 : OP_INC unary_expression
\r
1662 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1666 pre_decrement_expression
\r
1667 : OP_DEC unary_expression
\r
1669 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1675 * FIXME: This is actually wrong, it should be `type' but that
\r
1676 * introduces a lot of {shift,reduce}/reduces
\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
1682 : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression
\r
1684 $$ = new Cast ((string) $2, (Expression) $4);
\r
1686 | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
\r
1688 $$ = new Cast ((string) $2, (Expression) $4);
\r
1692 multiplicative_expression
\r
1693 : unary_expression
\r
1694 | multiplicative_expression STAR unary_expression
\r
1696 $$ = new Binary (Binary.Operator.Multiply,
\r
1697 (Expression) $1, (Expression) $3);
\r
1699 | multiplicative_expression DIV unary_expression
\r
1701 $$ = new Binary (Binary.Operator.Divide,
\r
1702 (Expression) $1, (Expression) $3);
\r
1704 | multiplicative_expression PERCENT unary_expression
\r
1706 $$ = new Binary (Binary.Operator.Modulo,
\r
1707 (Expression) $1, (Expression) $3);
\r
1711 additive_expression
\r
1712 : multiplicative_expression
\r
1713 | additive_expression PLUS multiplicative_expression
\r
1715 $$ = new Binary (Binary.Operator.Add,
\r
1716 (Expression) $1, (Expression) $3);
\r
1718 | additive_expression MINUS multiplicative_expression
\r
1720 $$ = new Binary (Binary.Operator.Substract,
\r
1721 (Expression) $1, (Expression) $3);
\r
1726 : additive_expression
\r
1727 | shift_expression OP_SHIFT_LEFT additive_expression
\r
1729 $$ = new Binary (Binary.Operator.ShiftLeft,
\r
1730 (Expression) $1, (Expression) $3);
\r
1732 | shift_expression OP_SHIFT_RIGHT additive_expression
\r
1734 $$ = new Binary (Binary.Operator.ShiftRight,
\r
1735 (Expression) $1, (Expression) $3);
\r
1739 relational_expression
\r
1740 : shift_expression
\r
1741 | relational_expression OP_LT shift_expression
\r
1743 $$ = new Binary (Binary.Operator.LessThan,
\r
1744 (Expression) $1, (Expression) $3);
\r
1746 | relational_expression OP_GT shift_expression
\r
1748 $$ = new Binary (Binary.Operator.GreatherThan,
\r
1749 (Expression) $1, (Expression) $3);
\r
1751 | relational_expression OP_LE shift_expression
\r
1753 $$ = new Binary (Binary.Operator.LessOrEqual,
\r
1754 (Expression) $1, (Expression) $3);
\r
1756 | relational_expression OP_GE shift_expression
\r
1758 $$ = new Binary (Binary.Operator.GreatherOrEqual,
\r
1759 (Expression) $1, (Expression) $3);
\r
1761 | relational_expression IS type
\r
1763 $$ = new Probe (Probe.Operator.Is,
\r
1764 (Expression) $1, (string) $3);
\r
1766 | relational_expression AS type
\r
1768 $$ = new Probe (Probe.Operator.As,
\r
1769 (Expression) $1, (string) $3);
\r
1773 equality_expression
\r
1774 : relational_expression
\r
1775 | equality_expression OP_EQ relational_expression
\r
1777 $$ = new Binary (Binary.Operator.Equal,
\r
1778 (Expression) $1, (Expression) $3);
\r
1780 | equality_expression OP_NE relational_expression
\r
1782 $$ = new Binary (Binary.Operator.NotEqual,
\r
1783 (Expression) $1, (Expression) $3);
\r
1788 : equality_expression
\r
1789 | and_expression BITWISE_AND equality_expression
\r
1791 $$ = new Binary (Binary.Operator.BitwiseAnd,
\r
1792 (Expression) $1, (Expression) $3);
\r
1796 exclusive_or_expression
\r
1798 | exclusive_or_expression CARRET and_expression
\r
1800 $$ = new Binary (Binary.Operator.ExclusiveOr,
\r
1801 (Expression) $1, (Expression) $3);
\r
1805 inclusive_or_expression
\r
1806 : exclusive_or_expression
\r
1807 | inclusive_or_expression BITWISE_OR exclusive_or_expression
\r
1809 $$ = new Binary (Binary.Operator.BitwiseOr,
\r
1810 (Expression) $1, (Expression) $3);
\r
1814 conditional_and_expression
\r
1815 : inclusive_or_expression
\r
1816 | conditional_and_expression OP_AND inclusive_or_expression
\r
1818 $$ = new Binary (Binary.Operator.LogicalAnd,
\r
1819 (Expression) $1, (Expression) $3);
\r
1823 conditional_or_expression
\r
1824 : conditional_and_expression
\r
1825 | conditional_or_expression OP_OR conditional_and_expression
\r
1827 $$ = new Binary (Binary.Operator.LogicalOr,
\r
1828 (Expression) $1, (Expression) $3);
\r
1832 conditional_expression
\r
1833 : conditional_or_expression
\r
1834 | conditional_or_expression INTERR expression COLON expression
\r
1836 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);
\r
1840 assignment_expression
\r
1841 : unary_expression ASSIGN expression
\r
1843 $$ = new Assign ((Expression) $1, (Expression) $3);
\r
1845 | unary_expression OP_MULT_ASSIGN expression
\r
1847 $$ = new Assign ((Expression) $1,
\r
1848 new Binary (Binary.Operator.Multiply,
\r
1850 (Expression) $3));
\r
1852 | unary_expression OP_DIV_ASSIGN expression
\r
1854 $$ = new Assign ((Expression) $1,
\r
1855 new Binary (Binary.Operator.Divide,
\r
1857 (Expression) $3));
\r
1859 | unary_expression OP_MOD_ASSIGN expression
\r
1861 $$ = new Assign ((Expression) $1,
\r
1862 new Binary (Binary.Operator.Modulo,
\r
1864 (Expression) $3));
\r
1866 | unary_expression OP_ADD_ASSIGN expression
\r
1868 $$ = new Assign ((Expression) $1,
\r
1869 new Binary (Binary.Operator.Add,
\r
1871 (Expression) $3));
\r
1873 | unary_expression OP_SUB_ASSIGN expression
\r
1875 $$ = new Assign ((Expression) $1,
\r
1876 new Binary (Binary.Operator.Substract,
\r
1878 (Expression) $3));
\r
1880 | unary_expression OP_SHIFT_LEFT_ASSIGN expression
\r
1882 $$ = new Assign ((Expression) $1,
\r
1883 new Binary (Binary.Operator.ShiftLeft,
\r
1885 (Expression) $3));
\r
1887 | unary_expression OP_SHIFT_RIGHT_ASSIGN expression
\r
1889 $$ = new Assign ((Expression) $1,
\r
1890 new Binary (Binary.Operator.ShiftRight,
\r
1892 (Expression) $3));
\r
1894 | unary_expression OP_AND_ASSIGN expression
\r
1896 $$ = new Assign ((Expression) $1,
\r
1897 new Binary (Binary.Operator.BitwiseAnd,
\r
1899 (Expression) $3));
\r
1901 | unary_expression OP_OR_ASSIGN expression
\r
1903 $$ = new Assign ((Expression) $1,
\r
1904 new Binary (Binary.Operator.BitwiseOr,
\r
1906 (Expression) $3));
\r
1908 | unary_expression OP_XOR_ASSIGN expression
\r
1910 $$ = new Assign ((Expression) $1,
\r
1911 new Binary (Binary.Operator.ExclusiveOr,
\r
1913 (Expression) $3));
\r
1918 : conditional_expression
\r
1919 | assignment_expression
\r
1922 constant_expression
\r
1926 boolean_expression
\r
1927 : expression { CheckBoolean ((Expression) $1); $$ = $1; }
\r
1939 string full_class_name = MakeName ((string) $4);
\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
1950 Class new_class = (Class) current_container;
\r
1953 new_class.Bases = (ArrayList) $6;
\r
1955 current_container = current_container.Parent;
\r
1956 CheckDef (current_container.AddClass (new_class), new_class.Name);
\r
1963 : /* empty */ { $$ = (int) 0; }
\r
1969 | modifiers modifier {
\r
1970 int m1 = (int) $1;
\r
1971 int m2 = (int) $2;
\r
1973 if ((m1 & m2) != 0)
\r
1974 error (1002, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
\r
1976 $$ = (int) (m1 | m2);
\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
1996 : /* empty */ { $$ = null; }
\r
1997 | class_base { $$ = $1; }
\r
2001 : COLON type_list { $$ = $2; }
\r
2005 // Statements (8.2)
\r
2009 // A block is "contained" on the following places:
\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
2020 current_block = new Block (current_block);
\r
2022 opt_statement_list CLOSE_BRACE
\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
2031 opt_statement_list
\r
2038 | statement_list statement
\r
2042 : declaration_statement
\r
2044 if ((Block) $1 != current_block){
\r
2045 current_block.AddStatement ((Statement) $1);
\r
2046 current_block = (Block) $1;
\r
2049 | embedded_statement
\r
2051 current_block.AddStatement ((Statement) $1);
\r
2053 | labeled_statement
\r
2055 current_block.AddStatement ((Statement) $1);
\r
2059 embedded_statement
\r
2062 | expression_statement
\r
2063 | selection_statement
\r
2064 | iteration_statement
\r
2067 | checked_statement
\r
2068 | unchecked_statement
\r
2076 $$ = new EmptyStatement ();
\r
2081 : IDENTIFIER COLON statement
\r
2083 string lab = (String) $1;
\r
2086 block = new Block (current_block, lab);
\r
2087 block.AddStatement ((Statement) $3);
\r
2090 if (!current_block.AddLabel (lab, block)){
\r
2091 error (140, "The label '" + lab + "' is a duplicate");
\r
2097 declaration_statement
\r
2098 : local_variable_declaration SEMICOLON // done
\r
2099 | local_constant_declaration SEMICOLON // finishme
\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
2108 local_variable_type
\r
2109 : primary_expression type_suffixes
\r
2111 // FIXME: Do something smart here regarding the composition of the type.
\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
2120 // So, instead we do a super trick: we just allow ($1) to be a
\r
2121 // SimpleName Expression.
\r
2123 if (((Expression) $1) is SimpleName)
\r
2124 $$ = ((SimpleName) $1).Name;
\r
2126 error (-1, "Invalid Type definition");
\r
2127 $$ = "System.Object";
\r
2130 | builtin_types type_suffixes
\r
2132 // FIXME: Do something smart with the type here.
\r
2135 | VOID type_suffixes
\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
2145 | type_suffix_list
\r
2150 | type_suffix_list type_suffix
\r
2154 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
2155 /* FIXME: | MULTIPLY */
\r
2158 local_variable_declaration
\r
2159 : local_variable_type variable_declarators
\r
2161 $$ = declare_local_variables ((string) $1, (ArrayList) $2);
\r
2165 local_constant_declaration
\r
2166 : CONST type constant_declarator
\r
2170 expression_statement
\r
2171 : statement_expression SEMICOLON
\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
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
2191 object_creation_expression
\r
2192 : object_or_delegate_creation_expression
\r
2193 { note ("complain if this is a delegate maybe?"); }
\r
2196 selection_statement
\r
2198 | switch_statement
\r
2202 : IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2203 embedded_statement
\r
2205 $$ = new If ((Expression) $3, (Statement) $5);
\r
2207 | IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2208 embedded_statement ELSE embedded_statement
\r
2210 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
\r
2215 : SWITCH OPEN_PARENS expression CLOSE_PARENS
\r
2218 $$ = new Switch ((Expression) $3, (ArrayList) $5);
\r
2224 opt_switch_sections
\r
2231 opt_switch_sections
\r
2232 : /* empty */ { $$ = new ArrayList (); }
\r
2239 ArrayList sections = new ArrayList ();
\r
2241 sections.Add ($1);
\r
2244 | switch_sections switch_section
\r
2246 ArrayList sections = (ArrayList) $1;
\r
2248 sections.Add ($2);
\r
2256 current_block = new Block (current_block);
\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
2270 ArrayList labels = new ArrayList ();
\r
2275 | switch_labels switch_label
\r
2277 ArrayList labels = (ArrayList) ($1);
\r
2285 : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2); }
\r
2286 | DEFAULT COLON { $$ = new SwitchLabel (null); }
\r
2289 iteration_statement
\r
2293 | foreach_statement
\r
2297 : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
\r
2299 $$ = new While ((Expression) $3, (Statement) $5);
\r
2304 : DO embedded_statement
\r
2305 WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
\r
2307 $$ = new Do ((Statement) $2, (Expression) $5);
\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
2318 $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
\r
2322 opt_for_initializer
\r
2323 : /* empty */ { $$ = new EmptyStatement (); }
\r
2324 | for_initializer
\r
2328 : local_variable_declaration
\r
2329 | statement_expression_list
\r
2333 : /* empty */ { $$ = new BoolLiteral (true); }
\r
2334 | boolean_expression
\r
2338 : /* empty */ { $$ = new EmptyStatement (); }
\r
2343 : statement_expression_list
\r
2346 statement_expression_list
\r
2347 : statement_expression
\r
2349 Block b = new Block (null, true);
\r
2351 b.AddStatement ((Statement) $1);
\r
2354 | statement_expression_list COMMA statement_expression
\r
2356 Block b = (Block) $1;
\r
2358 b.AddStatement ((Statement) $3);
\r
2364 : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS
\r
2365 embedded_statement
\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
2372 foreach_block = new Block (current_block, true);
\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
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
2383 getcurrent = new StatementExpression (
\r
2385 new LocalVariableReference (foreach_block, (string) $4),
\r
2388 new MemberAccess (
\r
2389 new LocalVariableReference (foreach_block, temp_id), "Current"))));
\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
2395 $$ = foreach_block;
\r
2401 | continue_statement
\r
2403 | return_statement
\r
2410 $$ = new Break ();
\r
2414 continue_statement
\r
2415 : CONTINUE SEMICOLON
\r
2417 $$ = new Continue ();
\r
2422 : GOTO IDENTIFIER SEMICOLON
\r
2424 $$ = new Goto ((string) $2);
\r
2426 | GOTO CASE constant_expression SEMICOLON
\r
2427 | GOTO DEFAULT SEMICOLON
\r
2431 : RETURN opt_expression SEMICOLON
\r
2433 $$ = new Return ((Expression) $2);
\r
2438 : THROW opt_expression SEMICOLON
\r
2440 $$ = new Throw ((Expression) $2);
\r
2450 : TRY block catch_clauses
\r
2452 DictionaryEntry cc = (DictionaryEntry) $3;
\r
2453 ArrayList s = null;
\r
2455 if (cc.Key != null)
\r
2456 s = (ArrayList) cc.Key;
\r
2458 $$ = new Try ((Block) $2, s, (Catch) cc.Value, null);
\r
2460 | TRY block FINALLY block
\r
2462 $$ = new Try ((Block) $2, null, null, (Block) $4);
\r
2464 | TRY block catch_clauses FINALLY block
\r
2466 DictionaryEntry cc = (DictionaryEntry) $3;
\r
2467 ArrayList s = null;
\r
2469 if (cc.Key != null)
\r
2470 s = (ArrayList) cc.Key;
\r
2472 $$ = new Try ((Block) $2, s, (Catch) cc.Value, (Block) $5);
\r
2477 : specific_catch_clauses opt_general_catch_clause
\r
2479 DictionaryEntry pair = new DictionaryEntry ();
\r
2486 | opt_specific_catch_clauses general_catch_clause
\r
2488 DictionaryEntry pair = new DictionaryEntry ();
\r
2496 opt_general_catch_clause
\r
2497 : /* empty */ { $$ = null; }
\r
2498 | general_catch_clause
\r
2501 opt_specific_catch_clauses
\r
2502 : /* emtpy */ { $$ = null; }
\r
2503 | specific_catch_clauses
\r
2506 specific_catch_clauses
\r
2507 : specific_catch_clause
\r
2509 ArrayList l = new ArrayList ();
\r
2514 | specific_catch_clauses specific_catch_clause
\r
2516 ArrayList l = (ArrayList) $1;
\r
2523 specific_catch_clause
\r
2524 : CATCH OPEN_PARENS type opt_identifier CLOSE_PARENS block
\r
2531 $$ = new Catch ((string) $3, id, (Block) $6);
\r
2536 : /* empty */ { $$ = null; }
\r
2540 general_catch_clause
\r
2543 $$ = new Catch (null, null, (Block) $2);
\r
2550 $$ = new Checked ((Block) $2);
\r
2554 unchecked_statement
\r
2557 $$ = new Unchecked ((Block) $2);
\r
2562 : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
\r
2564 $$ = new Lock ((Expression) $3, (Statement) $5);
\r
2569 : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
\r
2573 resource_acquisition
\r
2574 : local_variable_declaration
\r
2582 // A class used to pass around variable declarations and constants
\r
2584 public class VariableDeclaration {
\r
2585 public string identifier;
\r
2586 public object expression_or_array_initializer;
\r
2588 public VariableDeclaration (string id, object eoai){
\r
2589 this.identifier = id;
\r
2590 this.expression_or_array_initializer = eoai;
\r
2595 // Given the @class_name name, it creates a fully qualified name
\r
2596 // based on the containing declaration space
\r
2599 MakeName (string class_name)
\r
2601 string ns = current_namespace.Name;
\r
2602 string container_name = current_container.Name;
\r
2604 if (container_name == ""){
\r
2606 return ns + "." + class_name;
\r
2608 return class_name;
\r
2610 return container_name + "." + class_name;
\r
2614 // Used to report back to the user the result of a declaration
\r
2615 // in the current declaration space
\r
2618 CheckDef (DeclSpace.AdditionResult result, string name)
\r
2620 if (result == DeclSpace.AdditionResult.Success)
\r
2624 case DeclSpace.AdditionResult.NameExists:
\r
2625 error (102, "The namespace `" + current_container.Name +
\r
2626 "' already contains a definition for `"+
\r
2631 NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
\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
2639 case DeclSpace.AdditionResult.EnclosingClash:
\r
2640 error (542, "Member names cannot be the same as their enclosing type");
\r
2643 case DeclSpace.AdditionResult.NotAConstructor:
\r
2644 error (1520, "Class, struct, or interface method must have a return type");
\r
2650 CheckDef (bool result, string name)
\r
2654 CheckDef (DeclSpace.AdditionResult.NameExists, name);
\r
2657 Block declare_local_variables (string type, ArrayList variable_declarators)
\r
2659 Block implicit_block;
\r
2660 ArrayList inits = null;
\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
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
2675 // int j = 1; int k = j + 1;
\r
2677 if (current_block.Used)
\r
2678 implicit_block = new Block (current_block, true);
\r
2680 implicit_block = new Block (current_block, true);
\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
2690 error (128, "A local variable `" + decl.identifier +
\r
2691 "' is already defined in this scope");
\r
2695 if (inits == null)
\r
2696 return implicit_block;
\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
2703 assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr);
\r
2704 implicit_block.AddStatement (new StatementExpression (assign));
\r
2709 return implicit_block;
\r
2712 void CheckConstant (Expression expr)
\r
2717 void CheckBoolean (Expression expr)
\r
2722 static public void error (int code, string desc)
\r
2724 Console.WriteLine ("Error CS"+code+": "+desc);
\r
2728 void output (string s)
\r
2730 Console.WriteLine (s);
\r
2733 void note (string s)
\r
2735 // Used to put annotations
\r
2740 public CSharpParser(RootContext rc, string name, System.IO.Stream input)
\r
2742 current_namespace = new Namespace (null, "");
\r
2744 this.tree = rc.Tree;
\r
2746 this.input = input;
\r
2747 current_container = tree.Types;
\r
2748 current_container.Namespace = current_namespace;
\r
2750 lexer = new Tokenizer (input, name);
\r
2753 public int parse ()
\r
2755 StringBuilder value = new StringBuilder ();
\r
2757 global_errors = 0;
\r
2759 if (yacc_verbose_flag)
\r
2760 yyparse (lexer, new yydebug.yyDebugSimple ());
\r
2763 } catch (Exception e){
\r
2764 Console.WriteLine ("Fatal error: "+name);
\r
2765 Console.WriteLine (e);
\r
2766 Console.WriteLine (lexer.location);
\r
2770 return global_errors;
\r
2773 bool yacc_verbose_flag = false;
\r
2775 public bool yacc_verbose {
\r
2777 yacc_verbose_flag = value;
\r
2781 return yacc_verbose_flag;
\r