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 ParameterCollection implicit_value_parameters;
\r
71 // Used to record all types defined
\r
75 // Name of the file we are parsing
\r
78 // Input stream to parse from.
\r
79 public System.IO.Stream input;
\r
84 %token NONE /* This token is never returned by our lexer */
\r
85 %token ERROR // This is used not by the parser, but by the tokenizer.
\r
89 *These are the C# keywords
\r
169 /* C# keywords which are not really keywords */
\r
173 /* C# single character operators/punctuation. */
\r
174 %token OPEN_BRACE "{"
\r
175 %token CLOSE_BRACE "}"
\r
176 %token OPEN_BRACKET "["
\r
177 %token CLOSE_BRACKET "]"
\r
178 %token OPEN_PARENS "("
\r
179 %token CLOSE_PARENS ")"
\r
183 %token SEMICOLON ";"
\r
192 %token BITWISE_AND "&"
\r
193 %token BITWISE_OR "|"
\r
200 /* C# multi-character operators. */
\r
203 %token OP_SHIFT_LEFT "<<"
\r
204 %token OP_SHIFT_RIGHT ">>"
\r
211 %token OP_MULT_ASSIGN "*="
\r
212 %token OP_DIV_ASSIGN "/="
\r
213 %token OP_MOD_ASSIGN "%="
\r
214 %token OP_ADD_ASSIGN "+="
\r
215 %token OP_SUB_ASSIGN "-="
\r
216 %token OP_SHIFT_LEFT_ASSIGN "<<="
\r
217 %token OP_SHIFT_RIGHT_ASSIGN ">>="
\r
218 %token OP_AND_ASSIGN "&="
\r
219 %token OP_XOR_ASSIGN "^="
\r
220 %token OP_OR_ASSIGN "|="
\r
224 %token LITERAL_INTEGER "int literal"
\r
225 %token LITERAL_FLOAT "float literal"
\r
226 %token LITERAL_DOUBLE "double literal"
\r
227 %token LITERAL_DECIMAL "decimal literal"
\r
228 %token LITERAL_CHARACTER "character literal"
\r
229 %token LITERAL_STRING "string literal"
\r
233 /* Add precedence rules to solve dangling else s/r conflict */
\r
242 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
\r
244 %left STAR DIV PERCENT
\r
245 %right BANG CARRET UMINUS
\r
246 %nonassoc OP_INC OP_DEC
\r
248 %left OPEN_BRACKET OPEN_BRACE
\r
252 %start compilation_unit
\r
253 /*%start namespace_declaration */
\r
257 : opt_using_directives opt_attributes opt_namespace_member_declarations
\r
260 // At some point check that using only comes *before* any namespaces
\r
266 | using_directives using_directive
\r
270 : using_alias_directive
\r
271 | using_namespace_directive
\r
274 using_alias_directive
\r
275 : USING IDENTIFIER ASSIGN
\r
276 namespace_or_type_name SEMICOLON {
\r
280 using_namespace_directive
\r
281 : USING namespace_name SEMICOLON
\r
283 current_namespace.Using ((string) $2);
\r
287 namespace_declarations
\r
288 : namespace_declaration
\r
289 | namespace_declarations namespace_declaration
\r
291 namespace_declaration
\r
292 : NAMESPACE qualified_identifier
\r
294 current_namespace = new Namespace (current_namespace, (string) $2);
\r
296 namespace_body opt_semicolon
\r
298 current_namespace = current_namespace.Parent;
\r
312 qualified_identifier
\r
314 | qualified_identifier DOT IDENTIFIER {
\r
315 $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
\r
320 : namespace_or_type_name
\r
325 opt_using_directives
\r
326 opt_namespace_member_declarations
\r
331 opt_using_directives
\r
336 opt_namespace_member_declarations
\r
338 | namespace_member_declarations
\r
341 namespace_member_declarations
\r
342 : namespace_member_declaration
\r
343 | namespace_member_declarations namespace_member_declaration
\r
346 namespace_member_declaration
\r
353 Class c = (Class) $1;
\r
354 mod_flags = c.ModFlags;
\r
356 } else if ($1 is Struct){
\r
357 Struct s = (Struct) $1;
\r
358 mod_flags = s.ModFlags;
\r
364 // We remove this error until we can
\r
365 //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
\r
366 // error (1527, "Namespace elements cant be explicitly " +
\r
367 // "declared private or protected in `" + name + "'");
\r
370 | namespace_declaration
\r
374 : class_declaration
\r
375 | struct_declaration
\r
376 | interface_declaration
\r
377 | enum_declaration
\r
378 | delegate_declaration // finishme
\r
386 | attribute_section opt_attributes
\r
391 opt_attribute_target_specifier attribute_list
\r
392 /* FIXME: opt_comma */
\r
396 opt_attribute_target_specifier
\r
398 | attribute_target_specifier
\r
401 attribute_target_specifier
\r
402 : attribute_target COLON
\r
407 // if (Collection.Contains ($$))... FIXME
\r
408 note ("Allows: assembly, field, method, module, param, property, type");
\r
416 | attribute_list COMMA attribute
\r
421 | opt_attribute_arguments
\r
425 : type_name { /* reserved attribute name or identifier: 17.4 */ }
\r
428 opt_attribute_arguments
\r
430 | OPEN_PARENS attribute_arguments CLOSE_PARENS
\r
433 attribute_arguments
\r
435 | attribute_arguments COMMA expression
\r
439 opt_dimension_separators
\r
441 | dimension_separators
\r
444 dimension_separators
\r
446 | dimension_separators COMMA
\r
450 : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
\r
453 opt_class_member_declarations
\r
455 | class_member_declarations
\r
458 class_member_declarations
\r
459 : class_member_declaration
\r
460 | class_member_declarations
\r
461 class_member_declaration
\r
464 class_member_declaration
\r
465 : constant_declaration // done
\r
466 | field_declaration // done
\r
467 | method_declaration // done
\r
468 | property_declaration // done
\r
469 | event_declaration // finishme
\r
470 | indexer_declaration // finishme
\r
471 | operator_declaration // finishme
\r
472 | constructor_declaration // done
\r
473 | destructor_declaration // done
\r
483 string full_struct_name = MakeName ((string) $4);
\r
485 new_struct = new Struct (current_container, full_struct_name, (int) $2);
\r
486 current_container = new_struct;
\r
487 current_container.Namespace = current_namespace;
\r
488 tree.RecordStruct (full_struct_name, new_struct);
\r
490 opt_struct_interfaces
\r
494 Struct new_struct = (Struct) current_container;
\r
496 current_container = current_container.Parent;
\r
497 CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
\r
502 opt_struct_interfaces
\r
504 | struct_interfaces
\r
509 | struct_interfaces struct_interface
\r
517 : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
\r
520 opt_struct_member_declarations
\r
522 | struct_member_declarations
\r
525 struct_member_declarations
\r
526 : struct_member_declaration
\r
527 | struct_member_declarations struct_member_declaration
\r
530 struct_member_declaration
\r
531 : constant_declaration
\r
532 | field_declaration
\r
533 | method_declaration
\r
534 | property_declaration
\r
535 | event_declaration
\r
536 | indexer_declaration
\r
537 | operator_declaration
\r
538 | constructor_declaration
\r
542 constant_declaration
\r
547 constant_declarators
\r
550 Modifiers.Check (Constant.AllowedModifiers, (int) $2, Modifiers.PRIVATE);
\r
552 foreach (DictionaryEntry constant in (ArrayList) $5){
\r
553 Constant c = new Constant (
\r
554 (string) $4, (string) constant.Key,
\r
555 (Expression) constant.Value, (int) $2);
\r
557 CheckDef (current_container.AddConstant (c), c.Name);
\r
562 constant_declarators
\r
563 : constant_declarator
\r
565 ArrayList constants = new ArrayList ();
\r
566 constants.Add ($1);
\r
569 | constant_declarators COMMA constant_declarator
\r
571 ArrayList constants = (ArrayList) $1;
\r
573 constants.Add ($3);
\r
577 constant_declarator
\r
578 : IDENTIFIER ASSIGN constant_expression {
\r
579 $$ = new DictionaryEntry ($1, $3);
\r
587 variable_declarators
\r
590 string type = (string) $3;
\r
591 int mod = (int) $2;
\r
593 foreach (VariableDeclaration var in (ArrayList) $4){
\r
594 Field field = new Field (type, mod, var.identifier,
\r
595 var.expression_or_array_initializer);
\r
597 CheckDef (current_container.AddField (field), field.Name);
\r
603 variable_declarators
\r
604 : variable_declarator
\r
606 ArrayList decl = new ArrayList ();
\r
610 | variable_declarators COMMA variable_declarator
\r
612 ArrayList decls = (ArrayList) $1;
\r
618 variable_declarator
\r
619 : IDENTIFIER ASSIGN variable_initializer
\r
621 $$ = new VariableDeclaration ((string) $1, $3);
\r
625 $$ = new VariableDeclaration ((string) $1, null);
\r
629 variable_initializer
\r
631 | array_initializer
\r
638 Method method = (Method) $1;
\r
640 method.Block = (Block) $2;
\r
641 CheckDef (current_container.AddMethod (method), method.Name);
\r
643 current_local_parameters = null;
\r
652 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
654 Method method = new Method ((string) $3, (int) $2, (string) $4, (Parameters) $6);
\r
656 current_local_parameters = (Parameters) $6;
\r
664 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
666 Method method = new Method ("void", (int) $2, (string) $4, (Parameters) $6);
\r
668 current_local_parameters = (Parameters) $6;
\r
675 | SEMICOLON { $$ = null; }
\r
678 opt_formal_parameter_list
\r
679 : /* empty */ { $$ = new Parameters (null, null); }
\r
680 | formal_parameter_list
\r
683 formal_parameter_list
\r
684 : fixed_parameters
\r
686 $$ = new Parameters ((ParameterCollection) $1, null);
\r
688 | fixed_parameters COMMA parameter_array
\r
690 $$ = new Parameters ((ParameterCollection) $1, (Parameter) $3);
\r
694 $$ = new Parameters (null, (Parameter) $1);
\r
701 ParameterCollection pars = new ParameterCollection ();
\r
702 pars.Add ((Parameter) $1);
\r
705 | fixed_parameters COMMA fixed_parameter
\r
707 ParameterCollection pars = (ParameterCollection) $1;
\r
708 pars.Add ((Parameter) $3);
\r
715 opt_parameter_modifier
\r
719 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2);
\r
723 opt_parameter_modifier
\r
724 : /* empty */ { $$ = Parameter.Modifier.NONE; }
\r
725 | parameter_modifier
\r
729 : REF { $$ = Parameter.Modifier.REF; }
\r
730 | OUT { $$ = Parameter.Modifier.OUT; }
\r
734 : opt_attributes PARAMS type IDENTIFIER
\r
736 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS);
\r
737 note ("type must be a single-dimension array type");
\r
742 : IDENTIFIER { $$ = $1.ToString (); }
\r
743 | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
\r
746 property_declaration
\r
752 Parameter implicit_value_parameter;
\r
753 implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE);
\r
755 lexer.properties = true;
\r
757 implicit_value_parameters = new ParameterCollection ();
\r
758 implicit_value_parameters.Add (implicit_value_parameter);
\r
760 accessor_declarations
\r
762 lexer.properties = false;
\r
767 DictionaryEntry pair = (DictionaryEntry) $7;
\r
768 Block get_block = null;
\r
769 Block set_block = null;
\r
771 if (pair.Key != null)
\r
772 get_block = (Block) pair.Key;
\r
773 if (pair.Value != null)
\r
774 set_block = (Block) pair.Value;
\r
776 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block);
\r
778 CheckDef (current_container.AddProperty (prop), prop.Name);
\r
779 implicit_value_parameters = null;
\r
783 accessor_declarations
\r
784 : get_accessor_declaration opt_set_accessor_declaration
\r
786 $$ = new DictionaryEntry ($1, $2);
\r
788 | set_accessor_declaration opt_get_accessor_declaration
\r
790 $$ = new DictionaryEntry ($2, $1);
\r
794 opt_get_accessor_declaration
\r
795 : /* empty */ { $$ = null; }
\r
796 | get_accessor_declaration
\r
799 opt_set_accessor_declaration
\r
800 : /* empty */ { $$ = null; }
\r
801 | set_accessor_declaration
\r
804 get_accessor_declaration
\r
805 : opt_attributes GET accessor_body
\r
811 set_accessor_declaration
\r
812 : opt_attributes SET
\r
814 current_local_parameters = new Parameters (implicit_value_parameters, null);
\r
819 current_local_parameters = null;
\r
825 | SEMICOLON { $$ = new Block (null); }
\r
828 interface_declaration
\r
831 INTERFACE IDENTIFIER
\r
833 Interface new_interface;
\r
834 string full_interface_name = MakeName ((string) $4);
\r
836 new_interface = new Interface (current_container, full_interface_name, (int) $2);
\r
837 if (current_interface != null)
\r
838 error (-2, "Internal compiler error: interface inside interface");
\r
839 current_interface = new_interface;
\r
840 tree.RecordInterface (full_interface_name, new_interface);
\r
845 Interface new_interface = (Interface) current_interface;
\r
848 new_interface.Bases = (ArrayList) $6;
\r
850 current_interface = null;
\r
851 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
\r
856 : /* empty */ { $$ = null; }
\r
861 : COLON interface_type_list { $$ = $2; }
\r
864 interface_type_list
\r
867 ArrayList interfaces = new ArrayList ();
\r
869 interfaces.Add ($1);
\r
872 | interface_type_list COMMA interface_type
\r
874 ArrayList interfaces = (ArrayList) $1;
\r
875 interfaces.Add ($3);
\r
882 opt_interface_member_declarations
\r
886 opt_interface_member_declarations
\r
888 | interface_member_declarations
\r
891 interface_member_declarations
\r
892 : interface_member_declaration
\r
893 | interface_member_declarations interface_member_declaration
\r
896 interface_member_declaration
\r
897 : interface_method_declaration
\r
899 InterfaceMethod m = (InterfaceMethod) $1;
\r
901 CheckDef (current_interface.AddMethod (m), m.Name);
\r
903 | interface_property_declaration
\r
905 InterfaceProperty p = (InterfaceProperty) $1;
\r
907 CheckDef (current_interface.AddProperty (p), p.Name);
\r
909 | interface_event_declaration
\r
911 InterfaceEvent e = (InterfaceEvent) $1;
\r
913 CheckDef (current_interface.AddEvent (e), e.Name);
\r
915 | interface_indexer_declaration
\r
917 InterfaceIndexer i = (InterfaceIndexer) $1;
\r
919 CheckDef (current_interface.AddIndexer (i), "indexer");
\r
924 : /* empty */ { $$ = false; }
\r
925 | NEW { $$ = true; }
\r
928 interface_method_declaration
\r
929 : opt_attributes opt_new type IDENTIFIER
\r
930 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
933 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6);
\r
935 | opt_attributes opt_new VOID IDENTIFIER
\r
936 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
939 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6);
\r
943 interface_property_declaration
\r
948 { lexer.properties = true; }
\r
949 interface_accesors
\r
950 { lexer.properties = false; }
\r
955 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2,
\r
956 (gs & 1) == 1, (gs & 2) == 2);
\r
961 : opt_attributes GET SEMICOLON { $$ = 1; }
\r
962 | opt_attributes SET SEMICOLON { $$ = 2; }
\r
963 | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
\r
965 | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
\r
969 interface_event_declaration
\r
970 : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
\r
972 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2);
\r
976 interface_indexer_declaration
\r
977 : opt_attributes opt_new type THIS
\r
978 OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
980 { lexer.properties = true; }
\r
981 interface_accesors
\r
982 { lexer.properties = false; }
\r
985 int a_flags = (int) $10;
\r
987 bool do_get = (a_flags & 1) == 1;
\r
988 bool do_set = (a_flags & 2) == 2;
\r
990 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2);
\r
994 operator_declaration
\r
995 : opt_attributes opt_modifiers operator_declarator block
\r
997 // FIXME: validate that opt_modifiers is exactly: PUBLIC and STATIC
\r
1001 operator_declarator
\r
1002 : type OPERATOR overloadable_operator
\r
1003 OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1005 // FIXME: since reduce/reduce on this
\r
1006 // rule, validate overloadable_operator is unary
\r
1008 | type OPERATOR overloadable_operator
\r
1010 type IDENTIFIER COMMA
\r
1014 // FIXME: because of the reduce/reduce on PLUS and MINUS
\r
1015 // validate overloadable_operator is binary
\r
1017 | conversion_operator_declarator
\r
1020 overloadable_operator
\r
1021 // Unary operators:
\r
1028 // Unary and binary:
\r
1048 conversion_operator_declarator
\r
1049 : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1050 | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1053 constructor_declaration
\r
1056 constructor_declarator
\r
1059 Constructor c = (Constructor) $3;
\r
1060 c.Block = (Block) $4;
\r
1061 c.ModFlags = (int) $2;
\r
1063 if ((c.ModFlags & Modifiers.STATIC) != 0){
\r
1064 if ((c.ModFlags & Modifiers.Accessibility) != 0){
\r
1065 error (515, "Access modifiers are not allowed on static constructors");
\r
1068 CheckDef (current_container.AddConstructor (c), c.Name);
\r
1070 current_local_parameters = null;
\r
1074 constructor_declarator
\r
1076 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
1077 opt_constructor_initializer
\r
1079 ConstructorInitializer i = null;
\r
1082 i = (ConstructorInitializer) $5;
\r
1084 $$ = new Constructor ((string) $1, (Parameters) $3, i);
\r
1086 current_local_parameters = (Parameters) $3;
\r
1090 opt_constructor_initializer
\r
1091 : /* empty */ { $$ = null; }
\r
1092 | constructor_initializer
\r
1095 constructor_initializer
\r
1096 : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1098 $$ = new ConstructorBaseInitializer ((ArrayList) $4);
\r
1100 | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1102 $$ = new ConstructorThisInitializer ((ArrayList) $4);
\r
1106 destructor_declaration
\r
1107 : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
\r
1109 Method d = new Method ("System.Void", 0, "Finalize", new Parameters (null, null));
\r
1111 d.Block = (Block) $6;
\r
1112 CheckDef (current_container.AddMethod (d), d.Name);
\r
1119 EVENT type variable_declarators SEMICOLON
\r
1120 { note ("validate that the flags only contain new public protected internal private static virtual sealed override abstract"); }
\r
1123 EVENT type member_name
\r
1124 OPEN_BRACE event_accesor_declarations CLOSE_BRACE SEMICOLON
\r
1125 { note ("validate that the flags only contain new public protected internal private static virtual sealed override abstract"); }
\r
1128 event_accesor_declarations
\r
1129 : add_accessor_declaration remove_accessor_declaration
\r
1130 | remove_accessor_declaration add_accessor_declaration
\r
1133 add_accessor_declaration
\r
1134 : opt_attributes ADD block
\r
1137 remove_accessor_declaration
\r
1138 : opt_attributes REMOVE block
\r
1141 indexer_declaration
\r
1142 : opt_attributes opt_modifiers indexer_declarator
\r
1144 { lexer.properties = true; }
\r
1145 accessor_declarations
\r
1146 { lexer.properties = false; }
\r
1149 // The signature is computed from the signature of the indexer. Look
\r
1150 // at section 3.6 on the spec
\r
1151 note ("verify modifiers are NEW PUBLIC PROTECTED INTERNAL PRIVATE VIRTUAL SEALED OVERRIDE ABSTRACT");
\r
1155 indexer_declarator
\r
1156 : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1157 | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1168 string name = (string) $4;
\r
1169 Enum e = new Enum ((string) $5, (int) $2, name);
\r
1171 foreach (VariableDeclaration ev in (ArrayList) $6){
\r
1175 (Expression) ev.expression_or_array_initializer),
\r
1179 CheckDef (current_container.AddEnum (e), name);
\r
1184 : /* empty */ { $$ = "System.Int32"; }
\r
1185 | COLON integral_type { $$ = $2; }
\r
1189 : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
\r
1195 opt_enum_member_declarations
\r
1196 : /* empty */ { $$ = new ArrayList (); }
\r
1197 | enum_member_declarations opt_comma { $$ = $1; }
\r
1200 enum_member_declarations
\r
1201 : enum_member_declaration
\r
1203 ArrayList l = new ArrayList ();
\r
1208 | enum_member_declarations COMMA enum_member_declaration
\r
1210 ArrayList l = (ArrayList) $1;
\r
1218 enum_member_declaration
\r
1219 : opt_attributes IDENTIFIER
\r
1221 $$ = new VariableDeclaration ((string) $2, null);
\r
1223 | opt_attributes IDENTIFIER ASSIGN expression
\r
1225 $$ = new VariableDeclaration ((string) $2, $4);
\r
1229 delegate_declaration
\r
1233 IDENTIFIER OPEN_PARENS
\r
1234 formal_parameter_list
\r
1237 { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }
\r
1242 IDENTIFIER OPEN_PARENS
\r
1243 formal_parameter_list
\r
1246 { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }
\r
1250 : namespace_or_type_name
\r
1253 namespace_or_type_name
\r
1254 : qualified_identifier
\r
1258 * Before you think of adding a return_type, notice that we have been
\r
1259 * using two rules in the places where it matters (one rule using type
\r
1260 * and another identical one that uses VOID as the return type). This
\r
1261 * gets rid of a shift/reduce couple
\r
1264 : type_name { /* class_type */
\r
1266 This does interfaces, delegates, struct_types, class_types,
\r
1267 parent classes, and more! 4.2
\r
1278 ArrayList types = new ArrayList ();
\r
1283 | type_list COMMA type
\r
1285 ArrayList types = (ArrayList) $1;
\r
1293 * replaces all the productions for isolating the various
\r
1294 * simple types, but we need this to reuse it easily in local_variable_type
\r
1297 : OBJECT { $$ = "System.Object"; }
\r
1298 | STRING { $$ = "System.String"; }
\r
1299 | BOOL { $$ = "System.Boolean"; }
\r
1300 | DECIMAL { $$ = "System.Decimal"; }
\r
1301 | FLOAT { $$ = "System.Single"; }
\r
1302 | DOUBLE { $$ = "System.Double"; }
\r
1307 : SBYTE { $$ = "System.SByte"; }
\r
1308 | BYTE { $$ = "System.Byte"; }
\r
1309 | SHORT { $$ = "System.Int16"; }
\r
1310 | USHORT { $$ = "System.UInt16"; }
\r
1311 | INT { $$ = "System.Int32"; }
\r
1312 | UINT { $$ = "System.UInt32"; }
\r
1313 | LONG { $$ = "System.Int64"; }
\r
1314 | ULONG { $$ = "System.UInt64"; }
\r
1315 | CHAR { $$ = "System.Char"; }
\r
1323 : type rank_specifiers
\r
1326 // FIXME: We need to create a type for the nested thing.
\r
1331 // Expressions, section 7.5
\r
1333 primary_expression
\r
1336 // 7.5.1: Literals
\r
1340 | qualified_identifier
\r
1342 string name = (string) $1;
\r
1345 if (name.IndexOf ('.') == -1){
\r
1347 // we need to check against current_block not being null
\r
1348 // as `expression' is allowed in argument_lists, which
\r
1349 // do not exist inside a block.
\r
1351 if (current_block != null){
\r
1352 if (current_block.IsVariableDefined (name))
\r
1353 $$ = new LocalVariableReference (current_block, name);
\r
1355 if (($$ == null) && (current_local_parameters != null)){
\r
1356 Parameter par = current_local_parameters.GetParameterByName (name);
\r
1358 $$ = new ParameterReference (current_local_parameters, name);
\r
1362 $$ = new SimpleName (name);
\r
1364 | parenthesized_expression
\r
1366 | invocation_expression
\r
1370 | post_increment_expression
\r
1371 | post_decrement_expression
\r
1373 | typeof_expression
\r
1374 | sizeof_expression
\r
1375 | checked_expression
\r
1376 | unchecked_expression
\r
1383 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
\r
1384 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
\r
1385 | NULL { $$ = new NullLiteral (); }
\r
1389 : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }
\r
1390 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
\r
1391 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
\r
1395 : LITERAL_INTEGER { $$ = new IntLiteral ((Int32) lexer.Value); }
\r
1399 : TRUE { $$ = new BoolLiteral (true); }
\r
1400 | FALSE { $$ = new BoolLiteral (false); }
\r
1403 parenthesized_expression
\r
1404 : OPEN_PARENS expression CLOSE_PARENS
\r
1409 : primary_expression DOT IDENTIFIER
\r
1411 $$ = new MemberAccess ((Expression) $1, (string) $3);
\r
1413 | predefined_type DOT IDENTIFIER
\r
1415 $$ = new BuiltinTypeAccess ((string) $1, (string) $3);
\r
1423 invocation_expression
\r
1424 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1427 // if $1 is MethodGroup
\r
1428 // $$ = new Call ($1, $3);
\r
1430 // $$ = new DelegateCall ($1, $3);
\r
1432 error (1, "THIS IS CRAZY");
\r
1434 $$ = new Invocation ((Expression) $1, (ArrayList) $3);
\r
1439 : /* empty */ { $$ = new ArrayList (); }
\r
1446 ArrayList list = new ArrayList ();
\r
1450 | argument_list COMMA argument
\r
1452 ArrayList list = (ArrayList) $1;
\r
1461 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
\r
1463 | REF variable_reference
\r
1465 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
\r
1467 | OUT variable_reference
\r
1469 $$ = new Argument ((Expression) $2, Argument.AType.Out);
\r
1473 variable_reference
\r
1474 : expression { note ("section 5.4"); $$ = $1; }
\r
1478 : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1484 | expression_list COMMA expression
\r
1495 : BASE DOT IDENTIFIER
\r
1497 | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1501 post_increment_expression
\r
1502 : primary_expression OP_INC
\r
1504 $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1);
\r
1508 post_decrement_expression
\r
1509 : primary_expression OP_DEC
\r
1511 $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1);
\r
1516 : object_or_delegate_creation_expression
\r
1517 | array_creation_expression
\r
1520 object_or_delegate_creation_expression
\r
1521 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1523 $$ = new New ((string) $2, (ArrayList) $4);
\r
1527 array_creation_expression
\r
1528 : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1529 opt_rank_specifier
\r
1530 opt_array_initializer
\r
1534 opt_rank_specifier
\r
1541 | rank_specifier rank_specifiers
\r
1546 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
1550 opt_dim_separators
\r
1558 | dim_separators COMMA
\r
1562 opt_array_initializer
\r
1564 | array_initializer
\r
1568 : OPEN_BRACE CLOSE_BRACE
\r
1569 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
\r
1573 variable_initializer_list
\r
1574 : variable_initializer
\r
1575 | variable_initializer_list COMMA variable_initializer
\r
1580 : TYPEOF OPEN_PARENS type CLOSE_PARENS
\r
1582 $$ = new TypeOf ((string) $3);
\r
1587 : SIZEOF OPEN_PARENS type CLOSE_PARENS {
\r
1588 $$ = new SizeOf ((string) $3);
\r
1590 note ("Verify type is unmanaged");
\r
1591 note ("if (5.8) builtin, yield constant expression");
\r
1595 checked_expression
\r
1596 : CHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1599 unchecked_expression
\r
1600 : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1604 : primary_expression
\r
1605 | PLUS unary_expression {
\r
1606 $$ = new Unary (Unary.Operator.Plus, (Expression) $2);
\r
1608 | MINUS unary_expression
\r
1610 $$ = new Unary (Unary.Operator.Minus, (Expression) $2);
\r
1612 | BANG unary_expression
\r
1614 $$ = new Unary (Unary.Operator.Negate, (Expression) $2);
\r
1616 | TILDE unary_expression
\r
1618 $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2);
\r
1620 | STAR unary_expression
\r
1622 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2);
\r
1624 | BITWISE_AND unary_expression
\r
1626 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);
\r
1628 | OP_INC unary_expression
\r
1630 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1632 | OP_DEC unary_expression
\r
1634 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1636 | cast_expression
\r
1638 we can not do cast expressions at this level,
\r
1639 as there is an ambiguity. Check "Cast Expressions" 7.6.8
\r
1640 for the recipe to handle this.
\r
1644 pre_increment_expression
\r
1645 : OP_INC unary_expression
\r
1647 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1651 pre_decrement_expression
\r
1652 : OP_DEC unary_expression
\r
1654 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1660 * FIXME: This is actually wrong, it should be `type' but that
\r
1661 * introduces a lot of {shift,reduce}/reduces
\r
1663 * This is really really wrong. We need to track down
\r
1664 * the source of problems with QIs because expressions like:
\r
1665 * foreach (string s in (string []) object) wont be parsed.
\r
1667 : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression
\r
1669 $$ = new Cast ((string) $2, (Expression) $4);
\r
1671 | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
\r
1673 $$ = new Cast ((string) $2, (Expression) $4);
\r
1677 multiplicative_expression
\r
1678 : unary_expression
\r
1679 | multiplicative_expression STAR unary_expression
\r
1681 $$ = new Binary (Binary.Operator.Multiply,
\r
1682 (Expression) $1, (Expression) $3);
\r
1684 | multiplicative_expression DIV unary_expression
\r
1686 $$ = new Binary (Binary.Operator.Divide,
\r
1687 (Expression) $1, (Expression) $3);
\r
1689 | multiplicative_expression PERCENT unary_expression
\r
1691 $$ = new Binary (Binary.Operator.Modulo,
\r
1692 (Expression) $1, (Expression) $3);
\r
1696 additive_expression
\r
1697 : multiplicative_expression
\r
1698 | additive_expression PLUS multiplicative_expression
\r
1700 $$ = new Binary (Binary.Operator.Add,
\r
1701 (Expression) $1, (Expression) $3);
\r
1703 | additive_expression MINUS multiplicative_expression
\r
1705 $$ = new Binary (Binary.Operator.Substract,
\r
1706 (Expression) $1, (Expression) $3);
\r
1711 : additive_expression
\r
1712 | shift_expression OP_SHIFT_LEFT additive_expression
\r
1714 $$ = new Binary (Binary.Operator.ShiftLeft,
\r
1715 (Expression) $1, (Expression) $3);
\r
1717 | shift_expression OP_SHIFT_RIGHT additive_expression
\r
1719 $$ = new Binary (Binary.Operator.ShiftRight,
\r
1720 (Expression) $1, (Expression) $3);
\r
1724 relational_expression
\r
1725 : shift_expression
\r
1726 | relational_expression OP_LT shift_expression
\r
1728 $$ = new Binary (Binary.Operator.LessThan,
\r
1729 (Expression) $1, (Expression) $3);
\r
1731 | relational_expression OP_GT shift_expression
\r
1733 $$ = new Binary (Binary.Operator.GreatherThan,
\r
1734 (Expression) $1, (Expression) $3);
\r
1736 | relational_expression OP_LE shift_expression
\r
1738 $$ = new Binary (Binary.Operator.LessOrEqual,
\r
1739 (Expression) $1, (Expression) $3);
\r
1741 | relational_expression OP_GE shift_expression
\r
1743 $$ = new Binary (Binary.Operator.GreatherOrEqual,
\r
1744 (Expression) $1, (Expression) $3);
\r
1746 | relational_expression IS type
\r
1748 $$ = new Probe (Probe.Operator.Is,
\r
1749 (Expression) $1, (string) $3);
\r
1751 | relational_expression AS type
\r
1753 $$ = new Probe (Probe.Operator.As,
\r
1754 (Expression) $1, (string) $3);
\r
1758 equality_expression
\r
1759 : relational_expression
\r
1760 | equality_expression OP_EQ relational_expression
\r
1762 $$ = new Binary (Binary.Operator.Equal,
\r
1763 (Expression) $1, (Expression) $3);
\r
1765 | equality_expression OP_NE relational_expression
\r
1767 $$ = new Binary (Binary.Operator.NotEqual,
\r
1768 (Expression) $1, (Expression) $3);
\r
1773 : equality_expression
\r
1774 | and_expression BITWISE_AND equality_expression
\r
1776 $$ = new Binary (Binary.Operator.BitwiseAnd,
\r
1777 (Expression) $1, (Expression) $3);
\r
1781 exclusive_or_expression
\r
1783 | exclusive_or_expression CARRET and_expression
\r
1785 $$ = new Binary (Binary.Operator.ExclusiveOr,
\r
1786 (Expression) $1, (Expression) $3);
\r
1790 inclusive_or_expression
\r
1791 : exclusive_or_expression
\r
1792 | inclusive_or_expression BITWISE_OR exclusive_or_expression
\r
1794 $$ = new Binary (Binary.Operator.BitwiseOr,
\r
1795 (Expression) $1, (Expression) $3);
\r
1799 conditional_and_expression
\r
1800 : inclusive_or_expression
\r
1801 | conditional_and_expression OP_AND inclusive_or_expression
\r
1803 $$ = new Binary (Binary.Operator.LogicalAnd,
\r
1804 (Expression) $1, (Expression) $3);
\r
1808 conditional_or_expression
\r
1809 : conditional_and_expression
\r
1810 | conditional_or_expression OP_OR conditional_and_expression
\r
1812 $$ = new Binary (Binary.Operator.LogicalOr,
\r
1813 (Expression) $1, (Expression) $3);
\r
1817 conditional_expression
\r
1818 : conditional_or_expression
\r
1819 | conditional_or_expression INTERR expression COLON expression
\r
1821 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);
\r
1825 assignment_expression
\r
1826 : unary_expression ASSIGN expression
\r
1828 $$ = new Assign ((Expression) $1, (Expression) $3);
\r
1830 | unary_expression OP_MULT_ASSIGN expression
\r
1832 $$ = new Assign ((Expression) $1,
\r
1833 new Binary (Binary.Operator.Multiply,
\r
1835 (Expression) $3));
\r
1837 | unary_expression OP_DIV_ASSIGN expression
\r
1839 $$ = new Assign ((Expression) $1,
\r
1840 new Binary (Binary.Operator.Divide,
\r
1842 (Expression) $3));
\r
1844 | unary_expression OP_MOD_ASSIGN expression
\r
1846 $$ = new Assign ((Expression) $1,
\r
1847 new Binary (Binary.Operator.Modulo,
\r
1849 (Expression) $3));
\r
1851 | unary_expression OP_ADD_ASSIGN expression
\r
1853 $$ = new Assign ((Expression) $1,
\r
1854 new Binary (Binary.Operator.Add,
\r
1856 (Expression) $3));
\r
1858 | unary_expression OP_SUB_ASSIGN expression
\r
1860 $$ = new Assign ((Expression) $1,
\r
1861 new Binary (Binary.Operator.Substract,
\r
1863 (Expression) $3));
\r
1865 | unary_expression OP_SHIFT_LEFT_ASSIGN expression
\r
1867 $$ = new Assign ((Expression) $1,
\r
1868 new Binary (Binary.Operator.ShiftLeft,
\r
1870 (Expression) $3));
\r
1872 | unary_expression OP_SHIFT_RIGHT_ASSIGN expression
\r
1874 $$ = new Assign ((Expression) $1,
\r
1875 new Binary (Binary.Operator.ShiftRight,
\r
1877 (Expression) $3));
\r
1879 | unary_expression OP_AND_ASSIGN expression
\r
1881 $$ = new Assign ((Expression) $1,
\r
1882 new Binary (Binary.Operator.BitwiseAnd,
\r
1884 (Expression) $3));
\r
1886 | unary_expression OP_OR_ASSIGN expression
\r
1888 $$ = new Assign ((Expression) $1,
\r
1889 new Binary (Binary.Operator.BitwiseOr,
\r
1891 (Expression) $3));
\r
1893 | unary_expression OP_XOR_ASSIGN expression
\r
1895 $$ = new Assign ((Expression) $1,
\r
1896 new Binary (Binary.Operator.ExclusiveOr,
\r
1898 (Expression) $3));
\r
1903 : conditional_expression
\r
1904 | assignment_expression
\r
1907 constant_expression
\r
1911 boolean_expression
\r
1912 : expression { CheckBoolean ((Expression) $1); $$ = $1; }
\r
1924 string full_class_name = MakeName ((string) $4);
\r
1926 new_class = new Class (current_container, full_class_name, (int) $2);
\r
1927 current_container = new_class;
\r
1928 current_container.Namespace = current_namespace;
\r
1929 tree.RecordClass (full_class_name, new_class);
\r
1935 Class new_class = (Class) current_container;
\r
1938 new_class.Bases = (ArrayList) $6;
\r
1940 current_container = current_container.Parent;
\r
1941 CheckDef (current_container.AddClass (new_class), new_class.Name);
\r
1948 : /* empty */ { $$ = (int) 0; }
\r
1954 | modifiers modifier {
\r
1955 int m1 = (int) $1;
\r
1956 int m2 = (int) $2;
\r
1958 if ((m1 & m2) != 0)
\r
1959 error (1002, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
\r
1961 $$ = (int) (m1 | m2);
\r
1966 : NEW { $$ = Modifiers.NEW; }
\r
1967 | PUBLIC { $$ = Modifiers.PUBLIC; }
\r
1968 | PROTECTED { $$ = Modifiers.PROTECTED; }
\r
1969 | INTERNAL { $$ = Modifiers.INTERNAL; }
\r
1970 | PRIVATE { $$ = Modifiers.PRIVATE; }
\r
1971 | ABSTRACT { $$ = Modifiers.ABSTRACT; }
\r
1972 | SEALED { $$ = Modifiers.SEALED; }
\r
1973 | STATIC { $$ = Modifiers.STATIC; }
\r
1974 | READONLY { $$ = Modifiers.READONLY; }
\r
1975 | VIRTUAL { $$ = Modifiers.VIRTUAL; }
\r
1976 | OVERRIDE { $$ = Modifiers.OVERRIDE; }
\r
1977 | EXTERN { $$ = Modifiers.EXTERN; }
\r
1981 : /* empty */ { $$ = null; }
\r
1982 | class_base { $$ = $1; }
\r
1986 : COLON type_list { $$ = $2; }
\r
1990 // Statements (8.2)
\r
1994 // A block is "contained" on the following places:
\r
1996 // property_declaration as part of the accessor body (get/set)
\r
1997 // operator_declaration
\r
1998 // constructor_declaration
\r
1999 // destructor_declaration
\r
2000 // event_declaration as part of add_accessor_declaration or remove_accessor_declaration
\r
2005 current_block = new Block (current_block);
\r
2007 opt_statement_list CLOSE_BRACE
\r
2009 while (current_block.Implicit)
\r
2010 current_block = current_block.Parent;
\r
2011 $$ = current_block;
\r
2012 current_block = current_block.Parent;
\r
2016 opt_statement_list
\r
2023 | statement_list statement
\r
2027 : declaration_statement
\r
2029 if ((Block) $1 != current_block){
\r
2030 current_block.AddStatement ((Statement) $1);
\r
2031 current_block = (Block) $1;
\r
2034 | embedded_statement
\r
2036 current_block.AddStatement ((Statement) $1);
\r
2038 | labeled_statement
\r
2040 current_block.AddStatement ((Statement) $1);
\r
2044 embedded_statement
\r
2047 | expression_statement
\r
2048 | selection_statement
\r
2049 | iteration_statement
\r
2052 | checked_statement
\r
2053 | unchecked_statement
\r
2061 $$ = new EmptyStatement ();
\r
2066 : IDENTIFIER COLON statement
\r
2068 string lab = (String) $1;
\r
2071 block = new Block (current_block, lab);
\r
2072 block.AddStatement ((Statement) $3);
\r
2075 if (!current_block.AddLabel (lab, block)){
\r
2076 error (140, "The label '" + lab + "' is a duplicate");
\r
2082 declaration_statement
\r
2083 : local_variable_declaration SEMICOLON // done
\r
2084 | local_constant_declaration SEMICOLON // finishme
\r
2088 * The following is from Rhys' grammar:
\r
2089 * > Types in local variable declarations must be recognized as
\r
2090 * > expressions to prevent reduce/reduce errors in the grammar.
\r
2091 * > The expressions are converted into types during semantic analysis.
\r
2093 local_variable_type
\r
2094 : primary_expression type_suffixes
\r
2096 // FIXME: Do something smart here regarding the composition of the type.
\r
2099 // Ok, the above "primary_expression" is there to get rid of
\r
2100 // both reduce/reduce and shift/reduces in the grammar, it should
\r
2101 // really just be "type_name". If you use type_name, a reduce/reduce
\r
2102 // creeps up. If you use qualified_identifier (which is all we need
\r
2103 // really) two shift/reduces appear.
\r
2105 // So, instead we do a super trick: we just allow ($1) to be a
\r
2106 // SimpleName Expression.
\r
2108 if (((Expression) $1) is SimpleName)
\r
2109 $$ = ((SimpleName) $1).Name;
\r
2111 error (-1, "Invalid Type definition");
\r
2112 $$ = "System.Object";
\r
2115 | builtin_types type_suffixes
\r
2117 // FIXME: Do something smart with the type here.
\r
2120 | VOID type_suffixes
\r
2122 // FIXME: this is a string that represents the type
\r
2123 // Figure out something to make this work.
\r
2124 $$ = "VOID SOMETHING TYPE FIXME";
\r
2130 | type_suffix_list
\r
2135 | type_suffix_list type_suffix
\r
2139 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
2140 /* FIXME: | MULTIPLY */
\r
2143 local_variable_declaration
\r
2144 : local_variable_type variable_declarators
\r
2146 $$ = declare_local_variables ((string) $1, (ArrayList) $2);
\r
2150 local_constant_declaration
\r
2151 : CONST type constant_declarator
\r
2155 expression_statement
\r
2156 : statement_expression SEMICOLON
\r
2163 // We have to do the wrapping here and not in the case above,
\r
2164 // because statement_expression is used for example in for_statement
\r
2166 statement_expression
\r
2167 : invocation_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2168 | object_creation_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2169 | assignment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2170 | post_increment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2171 | post_decrement_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2172 | pre_increment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2173 | pre_decrement_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2176 object_creation_expression
\r
2177 : object_or_delegate_creation_expression
\r
2178 { note ("complain if this is a delegate maybe?"); }
\r
2181 selection_statement
\r
2183 | switch_statement
\r
2187 : IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2188 embedded_statement
\r
2190 $$ = new If ((Expression) $3, (Statement) $5);
\r
2192 | IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2193 embedded_statement ELSE embedded_statement
\r
2195 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
\r
2200 : SWITCH OPEN_PARENS expression CLOSE_PARENS
\r
2203 $$ = new Switch ((Expression) $3, (ArrayList) $5);
\r
2209 opt_switch_sections
\r
2216 opt_switch_sections
\r
2217 : /* empty */ { $$ = new ArrayList (); }
\r
2224 ArrayList sections = new ArrayList ();
\r
2226 sections.Add ($1);
\r
2229 | switch_sections switch_section
\r
2231 ArrayList sections = (ArrayList) $1;
\r
2233 sections.Add ($2);
\r
2241 current_block = new Block (current_block);
\r
2245 while (current_block.Implicit)
\r
2246 current_block = current_block.Parent;
\r
2247 $$ = new SwitchSection ((ArrayList) $1, current_block);
\r
2248 current_block = current_block.Parent;
\r
2255 ArrayList labels = new ArrayList ();
\r
2260 | switch_labels switch_label
\r
2262 ArrayList labels = (ArrayList) ($1);
\r
2270 : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2); }
\r
2271 | DEFAULT COLON { $$ = new SwitchLabel (null); }
\r
2274 iteration_statement
\r
2278 | foreach_statement
\r
2282 : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
\r
2284 $$ = new While ((Expression) $3, (Statement) $5);
\r
2289 : DO embedded_statement
\r
2290 WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
\r
2292 $$ = new Do ((Statement) $2, (Expression) $5);
\r
2297 : FOR OPEN_PARENS
\r
2298 opt_for_initializer SEMICOLON
\r
2299 opt_for_condition SEMICOLON
\r
2300 opt_for_iterator CLOSE_PARENS
\r
2301 embedded_statement
\r
2303 $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
\r
2307 opt_for_initializer
\r
2308 : /* empty */ { $$ = new EmptyStatement (); }
\r
2309 | for_initializer
\r
2313 : local_variable_declaration
\r
2314 | statement_expression_list
\r
2318 : /* empty */ { $$ = new BoolLiteral (true); }
\r
2319 | boolean_expression
\r
2323 : /* empty */ { $$ = new EmptyStatement (); }
\r
2328 : statement_expression_list
\r
2331 statement_expression_list
\r
2332 : statement_expression
\r
2334 Block b = new Block (null, true);
\r
2336 b.AddStatement ((Statement) $1);
\r
2339 | statement_expression_list COMMA statement_expression
\r
2341 Block b = (Block) $1;
\r
2343 b.AddStatement ((Statement) $3);
\r
2349 : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS
\r
2350 embedded_statement
\r
2352 string temp_id = current_block.MakeInternalID ();
\r
2353 Expression assign_e, ma;
\r
2354 Statement getcurrent;
\r
2355 Block foreach_block, child_block;
\r
2357 foreach_block = new Block (current_block, true);
\r
2359 foreach_block.AddVariable ("System.IEnumerator", temp_id);
\r
2360 foreach_block.AddVariable ((string) $3, (string) $4);
\r
2361 assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id),
\r
2363 new MemberAccess ((Expression) $6, "GetEnumerator"), null));
\r
2364 current_block.AddStatement (new StatementExpression (assign_e));
\r
2365 ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");
\r
2366 child_block = new Block (current_block);
\r
2368 getcurrent = new StatementExpression (
\r
2370 new LocalVariableReference (foreach_block, (string) $4),
\r
2373 new MemberAccess (
\r
2374 new LocalVariableReference (foreach_block, temp_id), "Current"))));
\r
2376 child_block.AddStatement (getcurrent);
\r
2377 child_block.AddStatement ((Statement) $8);
\r
2378 foreach_block.AddStatement (new While (ma, (Statement) child_block));
\r
2380 $$ = foreach_block;
\r
2386 | continue_statement
\r
2388 | return_statement
\r
2395 $$ = new Break ();
\r
2399 continue_statement
\r
2400 : CONTINUE SEMICOLON
\r
2402 $$ = new Continue ();
\r
2407 : GOTO IDENTIFIER SEMICOLON
\r
2409 $$ = new Goto ((string) $2);
\r
2411 | GOTO CASE constant_expression SEMICOLON
\r
2412 | GOTO DEFAULT SEMICOLON
\r
2416 : RETURN opt_expression SEMICOLON
\r
2418 $$ = new Return ((Expression) $2);
\r
2423 : THROW opt_expression SEMICOLON
\r
2425 $$ = new Throw ((Expression) $2);
\r
2435 : TRY block catch_clauses
\r
2437 DictionaryEntry cc = (DictionaryEntry) $3;
\r
2438 ArrayList s = null;
\r
2440 if (cc.Key != null)
\r
2441 s = (ArrayList) cc.Key;
\r
2443 $$ = new Try ((Block) $2, s, (Catch) cc.Value, null);
\r
2445 | TRY block FINALLY block
\r
2447 $$ = new Try ((Block) $2, null, null, (Block) $4);
\r
2449 | TRY block catch_clauses FINALLY block
\r
2451 DictionaryEntry cc = (DictionaryEntry) $3;
\r
2452 ArrayList s = null;
\r
2454 if (cc.Key != null)
\r
2455 s = (ArrayList) cc.Key;
\r
2457 $$ = new Try ((Block) $2, s, (Catch) cc.Value, (Block) $5);
\r
2462 : specific_catch_clauses opt_general_catch_clause
\r
2464 DictionaryEntry pair = new DictionaryEntry ();
\r
2471 | opt_specific_catch_clauses general_catch_clause
\r
2473 DictionaryEntry pair = new DictionaryEntry ();
\r
2481 opt_general_catch_clause
\r
2482 : /* empty */ { $$ = null; }
\r
2483 | general_catch_clause
\r
2486 opt_specific_catch_clauses
\r
2487 : /* emtpy */ { $$ = null; }
\r
2488 | specific_catch_clauses
\r
2491 specific_catch_clauses
\r
2492 : specific_catch_clause
\r
2494 ArrayList l = new ArrayList ();
\r
2499 | specific_catch_clauses specific_catch_clause
\r
2501 ArrayList l = (ArrayList) $1;
\r
2508 specific_catch_clause
\r
2509 : CATCH OPEN_PARENS type opt_identifier CLOSE_PARENS block
\r
2516 $$ = new Catch ((string) $3, id, (Block) $6);
\r
2521 : /* empty */ { $$ = null; }
\r
2525 general_catch_clause
\r
2528 $$ = new Catch (null, null, (Block) $2);
\r
2535 $$ = new Checked ((Block) $2);
\r
2539 unchecked_statement
\r
2542 $$ = new Unchecked ((Block) $2);
\r
2547 : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
\r
2549 $$ = new Lock ((Expression) $3, (Statement) $5);
\r
2554 : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
\r
2558 resource_acquisition
\r
2559 : local_variable_declaration
\r
2567 // A class used to pass around variable declarations and constants
\r
2569 public class VariableDeclaration {
\r
2570 public string identifier;
\r
2571 public object expression_or_array_initializer;
\r
2573 public VariableDeclaration (string id, object eoai){
\r
2574 this.identifier = id;
\r
2575 this.expression_or_array_initializer = eoai;
\r
2580 // Given the @class_name name, it creates a fully qualified name
\r
2581 // based on the containing declaration space
\r
2584 MakeName (string class_name)
\r
2586 string ns = current_namespace.Name;
\r
2587 string container_name = current_container.Name;
\r
2589 if (container_name == ""){
\r
2591 return ns + "." + class_name;
\r
2593 return class_name;
\r
2595 return container_name + "." + class_name;
\r
2599 // Used to report back to the user the result of a declaration
\r
2600 // in the current declaration space
\r
2603 CheckDef (DeclSpace.AdditionResult result, string name)
\r
2605 if (result == DeclSpace.AdditionResult.Success)
\r
2609 case DeclSpace.AdditionResult.NameExists:
\r
2610 error (102, "The namespace `" + current_container.Name +
\r
2611 "' already contains a definition for `"+
\r
2616 NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
\r
2618 case DeclSpace.AdditionResult.MethodDuplicated:
\r
2619 error (111, "Class `"+current_container.Name+
\r
2620 "' already defines a member called '" +
\r
2621 name + "' with the same parameter types");
\r
2624 case DeclSpace.AdditionResult.EnclosingClash:
\r
2625 error (542, "Member names cannot be the same as their enclosing type");
\r
2628 case DeclSpace.AdditionResult.NotAConstructor:
\r
2629 error (1520, "Class, struct, or interface method must have a return type");
\r
2635 CheckDef (bool result, string name)
\r
2639 CheckDef (DeclSpace.AdditionResult.NameExists, name);
\r
2642 Block declare_local_variables (string type, ArrayList variable_declarators)
\r
2644 Block implicit_block;
\r
2645 ArrayList inits = null;
\r
2648 // We use the `Used' property to check whether statements
\r
2649 // have been added to the current block. If so, we need
\r
2650 // to create another block to contain the new declaration
\r
2651 // otherwise, as an optimization, we use the same block to
\r
2652 // add the declaration.
\r
2654 // FIXME: A further optimization is to check if the statements
\r
2655 // that were added were added as part of the initialization
\r
2656 // below. In which case, no other statements have been executed
\r
2657 // and we might be able to reduce the number of blocks for
\r
2658 // situations like this:
\r
2660 // int j = 1; int k = j + 1;
\r
2662 if (current_block.Used)
\r
2663 implicit_block = new Block (current_block, true);
\r
2665 implicit_block = new Block (current_block, true);
\r
2667 foreach (VariableDeclaration decl in variable_declarators){
\r
2668 if (implicit_block.AddVariable (type, decl.identifier)){
\r
2669 if (decl.expression_or_array_initializer != null){
\r
2670 if (inits == null)
\r
2671 inits = new ArrayList ();
\r
2675 error (128, "A local variable `" + decl.identifier +
\r
2676 "' is already defined in this scope");
\r
2680 if (inits == null)
\r
2681 return implicit_block;
\r
2683 foreach (VariableDeclaration decl in inits){
\r
2684 if (decl.expression_or_array_initializer is Expression){
\r
2685 Expression expr = (Expression) decl.expression_or_array_initializer;
\r
2688 assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr);
\r
2689 implicit_block.AddStatement (new StatementExpression (assign));
\r
2694 return implicit_block;
\r
2697 void CheckConstant (Expression expr)
\r
2702 void CheckBoolean (Expression expr)
\r
2707 static public void error (int code, string desc)
\r
2709 Console.WriteLine ("Error CS"+code+": "+desc);
\r
2713 void output (string s)
\r
2715 Console.WriteLine (s);
\r
2718 void note (string s)
\r
2720 // Used to put annotations
\r
2725 public CSharpParser(CIR.Tree tree, string name, System.IO.Stream input)
\r
2727 current_namespace = new Namespace (null, "");
\r
2730 this.input = input;
\r
2731 current_container = tree.Types;
\r
2732 current_container.Namespace = current_namespace;
\r
2734 lexer = new Tokenizer (input, name);
\r
2737 public int parse ()
\r
2739 StringBuilder value = new StringBuilder ();
\r
2741 global_errors = 0;
\r
2743 if (yacc_verbose_flag)
\r
2744 yyparse (lexer, new yydebug.yyDebugSimple ());
\r
2747 } catch (Exception e){
\r
2748 Console.WriteLine ("Fatal error: "+name);
\r
2749 Console.WriteLine (e);
\r
2750 Console.WriteLine (lexer.location);
\r
2754 return global_errors;
\r
2757 bool yacc_verbose_flag = false;
\r
2759 public bool yacc_verbose {
\r
2761 yacc_verbose_flag = value;
\r
2765 return yacc_verbose_flag;
\r