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
33 using Mono.Languages;
\r
38 public class CSharpParser : GenericParser {
\r
39 Namespace current_namespace;
\r
40 TypeContainer current_container;
\r
43 // Current block is used to add statements as we find
\r
47 Block current_block;
\r
50 // Current interface is used by the various declaration
\r
51 // productions in the interface declaration to "add"
\r
52 // the interfaces as we find them.
\r
54 Interface current_interface;
\r
57 // This is used by the unary_expression code to resolve
\r
58 // a name against a parameter.
\r
60 Parameters current_local_parameters;
\r
63 // Using during property parsing to describe the implicit
\r
64 // value parameter that is passed to the "set" accesor
\r
67 Parameter [] implicit_value_parameters;
\r
70 // Used to determine if we are parsing the get/set pair
\r
71 // of an indexer or a property
\r
73 bool parsing_indexer;
\r
76 // Used to record all types defined
\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 EOF
\r
259 // Check that using comes only before namespace elements
\r
265 | using_directives using_directive
\r
269 : using_alias_directive
\r
270 | using_namespace_directive
\r
273 using_alias_directive
\r
274 : USING IDENTIFIER ASSIGN
\r
275 namespace_or_type_name SEMICOLON
\r
277 // FIXME : Need to implement actual action.
\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
333 opt_using_directives
\r
338 opt_namespace_member_declarations
\r
340 | namespace_member_declarations
\r
343 namespace_member_declarations
\r
344 : namespace_member_declaration
\r
345 | namespace_member_declarations namespace_member_declaration
\r
348 namespace_member_declaration
\r
355 Class c = (Class) $1;
\r
356 mod_flags = c.ModFlags;
\r
358 } else if ($1 is Struct){
\r
359 Struct s = (Struct) $1;
\r
360 mod_flags = s.ModFlags;
\r
366 // We remove this error until we can
\r
367 //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
\r
368 // error (1527, "Namespace elements cant be explicitly " +
\r
369 // "declared private or protected in `" + name + "'");
\r
372 | namespace_declaration
\r
376 : class_declaration
\r
377 | struct_declaration
\r
378 | interface_declaration
\r
379 | enum_declaration
\r
380 | delegate_declaration
\r
387 : /* empty */ { $$ = null; }
\r
388 | attribute_section opt_attributes
\r
393 attrs = (Attributes) $2;
\r
394 attrs.AddAttribute ((Attribute) $1);
\r
396 attrs = new Attributes ((Attribute) $1);
\r
403 : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET
\r
405 string target = null;
\r
408 target = (string) $2;
\r
410 $$ = new Attribute (target, (ArrayList) $3);
\r
412 | OPEN_BRACKET attribute_list CLOSE_BRACKET
\r
414 $$ = new Attribute (null, (ArrayList) $2);
\r
418 attribute_target_specifier
\r
419 : attribute_target COLON
\r
428 CheckAttributeTarget ((string) $1);
\r
431 | EVENT { $$ = "event"; }
\r
432 | RETURN { $$ = "return"; }
\r
438 ArrayList attrs = new ArrayList ();
\r
444 | attribute_list COMMA attribute
\r
446 ArrayList attrs = (ArrayList) $1;
\r
454 : attribute_name opt_attribute_arguments
\r
456 $$ = new DictionaryEntry ($1, $2);
\r
461 : type_name { /* reserved attribute name or identifier: 17.4 */ }
\r
464 opt_attribute_arguments
\r
465 : /* empty */ { $$ = null; }
\r
466 | OPEN_PARENS attribute_arguments CLOSE_PARENS
\r
472 attribute_arguments
\r
475 ArrayList args = new ArrayList ();
\r
480 | attribute_arguments COMMA expression
\r
482 ArrayList args = (ArrayList) $1;
\r
491 : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
\r
494 opt_class_member_declarations
\r
496 | class_member_declarations
\r
499 class_member_declarations
\r
500 : class_member_declaration
\r
501 | class_member_declarations
\r
502 class_member_declaration
\r
505 class_member_declaration
\r
506 : constant_declaration // done
\r
507 | field_declaration // done
\r
508 | method_declaration // done
\r
509 | property_declaration // done
\r
510 | event_declaration // done
\r
511 | indexer_declaration // done
\r
512 | operator_declaration // done
\r
513 | constructor_declaration // done
\r
514 | destructor_declaration // done
\r
524 string full_struct_name = MakeName ((string) $4);
\r
526 new_struct = new Struct (rc, current_container, full_struct_name, (int) $2, (Attributes) $1);
\r
527 current_container = new_struct;
\r
528 current_container.Namespace = current_namespace;
\r
529 tree.RecordStruct (full_struct_name, new_struct);
\r
531 opt_struct_interfaces
\r
535 Struct new_struct = (Struct) current_container;
\r
537 current_container = current_container.Parent;
\r
538 CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
\r
543 opt_struct_interfaces
\r
545 | struct_interfaces
\r
550 | struct_interfaces struct_interface
\r
558 : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
\r
561 opt_struct_member_declarations
\r
563 | struct_member_declarations
\r
566 struct_member_declarations
\r
567 : struct_member_declaration
\r
568 | struct_member_declarations struct_member_declaration
\r
571 struct_member_declaration
\r
572 : constant_declaration
\r
573 | field_declaration
\r
574 | method_declaration
\r
575 | property_declaration
\r
576 | event_declaration
\r
577 | indexer_declaration
\r
578 | operator_declaration
\r
579 | constructor_declaration
\r
583 constant_declaration
\r
588 constant_declarators
\r
591 foreach (DictionaryEntry constant in (ArrayList) $5){
\r
592 Constant c = new Constant (
\r
593 (string) $4, (string) constant.Key,
\r
594 (Expression) constant.Value, (int) $2, (Attributes) $1);
\r
596 CheckDef (current_container.AddConstant (c), c.Name);
\r
601 constant_declarators
\r
602 : constant_declarator
\r
604 ArrayList constants = new ArrayList ();
\r
605 constants.Add ($1);
\r
608 | constant_declarators COMMA constant_declarator
\r
610 ArrayList constants = (ArrayList) $1;
\r
612 constants.Add ($3);
\r
616 constant_declarator
\r
617 : IDENTIFIER ASSIGN constant_expression
\r
619 $$ = new DictionaryEntry ($1, $3);
\r
627 variable_declarators
\r
630 string type = (string) $3;
\r
631 int mod = (int) $2;
\r
633 foreach (VariableDeclaration var in (ArrayList) $4){
\r
634 Field field = new Field (type, mod, var.identifier,
\r
635 var.expression_or_array_initializer, (Attributes) $1);
\r
637 CheckDef (current_container.AddField (field), field.Name);
\r
643 variable_declarators
\r
644 : variable_declarator
\r
646 ArrayList decl = new ArrayList ();
\r
650 | variable_declarators COMMA variable_declarator
\r
652 ArrayList decls = (ArrayList) $1;
\r
658 variable_declarator
\r
659 : IDENTIFIER ASSIGN variable_initializer
\r
661 $$ = new VariableDeclaration ((string) $1, $3);
\r
665 $$ = new VariableDeclaration ((string) $1, null);
\r
669 variable_initializer
\r
674 | array_initializer
\r
684 Method method = (Method) $1;
\r
686 method.Block = (Block) $2;
\r
687 CheckDef (current_container.AddMethod (method), method.Name);
\r
689 current_local_parameters = null;
\r
698 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
700 Method method = new Method ((string) $3, (int) $2, (string) $4, (Parameters) $6, (Attributes) $1);
\r
702 current_local_parameters = (Parameters) $6;
\r
710 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
712 Method method = new Method ("System.Void", (int) $2, (string) $4, (Parameters) $6, (Attributes) $1);
\r
714 current_local_parameters = (Parameters) $6;
\r
721 | SEMICOLON { $$ = null; }
\r
724 opt_formal_parameter_list
\r
725 : /* empty */ { $$ = new Parameters (null, null); }
\r
726 | formal_parameter_list
\r
729 formal_parameter_list
\r
730 : fixed_parameters
\r
732 ArrayList pars_list = (ArrayList) $1;
\r
734 Parameter [] pars = new Parameter [pars_list.Count];
\r
735 pars_list.CopyTo (pars);
\r
737 $$ = new Parameters (pars, null);
\r
739 | fixed_parameters COMMA parameter_array
\r
741 ArrayList pars_list = (ArrayList) $1;
\r
743 Parameter [] pars = new Parameter [pars_list.Count];
\r
744 pars_list.CopyTo (pars);
\r
746 $$ = new Parameters (pars, (Parameter) $3);
\r
750 $$ = new Parameters (null, (Parameter) $1);
\r
757 ArrayList pars = new ArrayList ();
\r
762 | fixed_parameters COMMA fixed_parameter
\r
764 ArrayList pars = (ArrayList) $1;
\r
773 opt_parameter_modifier
\r
777 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
\r
781 opt_parameter_modifier
\r
782 : /* empty */ { $$ = Parameter.Modifier.NONE; }
\r
783 | parameter_modifier
\r
787 : REF { $$ = Parameter.Modifier.REF; }
\r
788 | OUT { $$ = Parameter.Modifier.OUT; }
\r
792 : opt_attributes PARAMS type IDENTIFIER
\r
794 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
\r
795 note ("type must be a single-dimension array type");
\r
800 : IDENTIFIER { $$ = $1.ToString (); }
\r
801 | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
\r
804 property_declaration
\r
810 Parameter implicit_value_parameter;
\r
811 implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE, null);
\r
813 lexer.properties = true;
\r
815 implicit_value_parameters = new Parameter [1];
\r
816 implicit_value_parameters [0] = implicit_value_parameter;
\r
818 accessor_declarations
\r
820 lexer.properties = false;
\r
825 DictionaryEntry pair = (DictionaryEntry) $7;
\r
826 Block get_block = null;
\r
827 Block set_block = null;
\r
829 if (pair.Key != null)
\r
830 get_block = (Block) pair.Key;
\r
831 if (pair.Value != null)
\r
832 set_block = (Block) pair.Value;
\r
834 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block, (Attributes) $1);
\r
836 CheckDef (current_container.AddProperty (prop), prop.Name);
\r
837 implicit_value_parameters = null;
\r
841 accessor_declarations
\r
842 : get_accessor_declaration opt_set_accessor_declaration
\r
844 $$ = new DictionaryEntry ($1, $2);
\r
846 | set_accessor_declaration opt_get_accessor_declaration
\r
848 $$ = new DictionaryEntry ($2, $1);
\r
852 opt_get_accessor_declaration
\r
853 : /* empty */ { $$ = null; }
\r
854 | get_accessor_declaration
\r
857 opt_set_accessor_declaration
\r
858 : /* empty */ { $$ = null; }
\r
859 | set_accessor_declaration
\r
862 get_accessor_declaration
\r
863 : opt_attributes GET
\r
865 // If this is not the case, then current_local_parameters has already
\r
866 // been set in indexer_declaration
\r
867 if (parsing_indexer == false)
\r
868 current_local_parameters = new Parameters (implicit_value_parameters, null);
\r
875 current_local_parameters = null;
\r
879 set_accessor_declaration
\r
880 : opt_attributes SET
\r
882 if (parsing_indexer == false)
\r
883 current_local_parameters = new Parameters (implicit_value_parameters, null);
\r
888 current_local_parameters = null;
\r
894 | SEMICOLON { $$ = new Block (null); }
\r
897 interface_declaration
\r
900 INTERFACE IDENTIFIER
\r
902 Interface new_interface;
\r
903 string full_interface_name = MakeName ((string) $4);
\r
905 new_interface = new Interface (current_container, full_interface_name, (int) $2, (Attributes) $1);
\r
906 if (current_interface != null) {
\r
907 Location l = lexer.Location;
\r
908 rc.Report.Error (-2, l, "Internal compiler error: interface inside interface");
\r
910 current_interface = new_interface;
\r
911 tree.RecordInterface (full_interface_name, new_interface);
\r
916 Interface new_interface = (Interface) current_interface;
\r
919 new_interface.Bases = (ArrayList) $6;
\r
921 current_interface = null;
\r
922 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
\r
927 : /* empty */ { $$ = null; }
\r
932 : COLON interface_type_list { $$ = $2; }
\r
935 interface_type_list
\r
938 ArrayList interfaces = new ArrayList ();
\r
940 interfaces.Add ($1);
\r
943 | interface_type_list COMMA interface_type
\r
945 ArrayList interfaces = (ArrayList) $1;
\r
946 interfaces.Add ($3);
\r
953 opt_interface_member_declarations
\r
957 opt_interface_member_declarations
\r
959 | interface_member_declarations
\r
962 interface_member_declarations
\r
963 : interface_member_declaration
\r
964 | interface_member_declarations interface_member_declaration
\r
967 interface_member_declaration
\r
968 : interface_method_declaration
\r
970 InterfaceMethod m = (InterfaceMethod) $1;
\r
972 CheckDef (current_interface.AddMethod (m), m.Name);
\r
974 | interface_property_declaration
\r
976 InterfaceProperty p = (InterfaceProperty) $1;
\r
978 CheckDef (current_interface.AddProperty (p), p.Name);
\r
980 | interface_event_declaration
\r
982 InterfaceEvent e = (InterfaceEvent) $1;
\r
984 CheckDef (current_interface.AddEvent (e), e.Name);
\r
986 | interface_indexer_declaration
\r
988 InterfaceIndexer i = (InterfaceIndexer) $1;
\r
990 CheckDef (current_interface.AddIndexer (i), "indexer");
\r
995 : /* empty */ { $$ = false; }
\r
996 | NEW { $$ = true; }
\r
999 interface_method_declaration
\r
1000 : opt_attributes opt_new type IDENTIFIER
\r
1001 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
1004 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
\r
1006 | opt_attributes opt_new VOID IDENTIFIER
\r
1007 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
1010 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
\r
1014 interface_property_declaration
\r
1019 { lexer.properties = true; }
\r
1020 interface_accesors
\r
1021 { lexer.properties = false; }
\r
1024 int gs = (int) $7;
\r
1026 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2,
\r
1027 (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1);
\r
1031 interface_accesors
\r
1032 : opt_attributes GET SEMICOLON { $$ = 1; }
\r
1033 | opt_attributes SET SEMICOLON { $$ = 2; }
\r
1034 | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
\r
1036 | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
\r
1040 interface_event_declaration
\r
1041 : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
\r
1043 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);
\r
1047 interface_indexer_declaration
\r
1048 : opt_attributes opt_new type THIS
\r
1049 OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1051 { lexer.properties = true; }
\r
1052 interface_accesors
\r
1053 { lexer.properties = false; }
\r
1056 int a_flags = (int) $10;
\r
1058 bool do_get = (a_flags & 1) == 1;
\r
1059 bool do_set = (a_flags & 2) == 2;
\r
1061 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2, (Attributes) $1);
\r
1065 operator_declaration
\r
1066 : opt_attributes opt_modifiers operator_declarator block
\r
1068 OperatorDeclaration decl = (OperatorDeclaration) $3;
\r
1070 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
\r
1071 decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1);
\r
1073 // Note again, checking is done in semantic analysis
\r
1074 current_container.AddOperator (op);
\r
1078 operator_declarator
\r
1079 : type OPERATOR overloadable_operator
\r
1080 OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1082 CheckUnaryOperator ((Operator.OpType) $3);
\r
1084 $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6, null, null);
\r
1086 | type OPERATOR overloadable_operator
\r
1088 type IDENTIFIER COMMA
\r
1092 CheckBinaryOperator ((Operator.OpType) $3);
\r
1094 $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
\r
1095 (string) $8, (string) $9);
\r
1097 | conversion_operator_declarator
\r
1100 overloadable_operator
\r
1101 // Unary operators:
\r
1102 : BANG { $$ = Operator.OpType.Bang; }
\r
1103 | TILDE { $$ = Operator.OpType.Tilde; }
\r
1104 | OP_INC { $$ = Operator.OpType.Increment; }
\r
1105 | OP_DEC { $$ = Operator.OpType.Decrement; }
\r
1106 | TRUE { $$ = Operator.OpType.True; }
\r
1107 | FALSE { $$ = Operator.OpType.False; }
\r
1108 // Unary and binary:
\r
1109 | PLUS { $$ = Operator.OpType.Plus; }
\r
1110 | MINUS { $$ = Operator.OpType.Minus; }
\r
1112 | STAR { $$ = Operator.OpType.Star; }
\r
1113 | DIV { $$ = Operator.OpType.Div; }
\r
1114 | PERCENT { $$ = Operator.OpType.Percent; }
\r
1115 | BITWISE_AND { $$ = Operator.OpType.BitAnd; }
\r
1116 | BITWISE_OR { $$ = Operator.OpType.BitOr; }
\r
1117 | CARRET { $$ = Operator.OpType.Carret; }
\r
1118 | OP_SHIFT_LEFT { $$ = Operator.OpType.ShiftLeft; }
\r
1119 | OP_SHIFT_RIGHT { $$ = Operator.OpType.ShiftRight; }
\r
1120 | OP_EQ { $$ = Operator.OpType.Eq; }
\r
1121 | OP_NE { $$ = Operator.OpType.NotEq; }
\r
1122 | OP_GT { $$ = Operator.OpType.GreaterThan; }
\r
1123 | OP_LT { $$ = Operator.OpType.LesserThan; }
\r
1124 | OP_GE { $$ = Operator.OpType.GreaterOrEq; }
\r
1125 | OP_LE { $$ = Operator.OpType.LesserOrEq; }
\r
1128 conversion_operator_declarator
\r
1129 : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1131 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
\r
1134 | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1136 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
\r
1141 constructor_declaration
\r
1144 constructor_declarator
\r
1147 Constructor c = (Constructor) $3;
\r
1148 c.Block = (Block) $4;
\r
1149 c.ModFlags = (int) $2;
\r
1151 if ((c.ModFlags & Modifiers.STATIC) != 0){
\r
1152 if ((c.ModFlags & Modifiers.Accessibility) != 0) {
\r
1153 Location l = lexer.Location;
\r
1154 rc.Report.Error (515, l, "Access modifiers are not allowed on static constructors");
\r
1157 CheckDef (current_container.AddConstructor (c), c.Name);
\r
1159 current_local_parameters = null;
\r
1163 constructor_declarator
\r
1165 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
1166 opt_constructor_initializer
\r
1168 ConstructorInitializer i = null;
\r
1171 i = new ConstructorBaseInitializer (null);
\r
1173 i = (ConstructorInitializer) $5;
\r
1175 $$ = new Constructor ((string) $1, (Parameters) $3, i);
\r
1177 current_local_parameters = (Parameters) $3;
\r
1181 opt_constructor_initializer
\r
1182 : /* empty */ { $$ = null; }
\r
1183 | constructor_initializer
\r
1186 constructor_initializer
\r
1187 : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1189 $$ = new ConstructorBaseInitializer ((ArrayList) $4);
\r
1191 | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1193 $$ = new ConstructorThisInitializer ((ArrayList) $4);
\r
1197 destructor_declaration
\r
1198 : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
\r
1200 Method d = new Method ("System.Void", 0, "Finalize", new Parameters (null, null), (Attributes) $1);
\r
1202 d.Block = (Block) $6;
\r
1203 CheckDef (current_container.AddMethod (d), d.Name);
\r
1210 EVENT type variable_declarators SEMICOLON
\r
1212 foreach (VariableDeclaration var in (ArrayList) $5) {
\r
1214 // FIXME : Is this right ?
\r
1215 Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
\r
1216 (int) $2, null, null, (Attributes) $1);
\r
1218 CheckDef (current_container.AddEvent (e), e.Name);
\r
1224 EVENT type member_name
\r
1225 OPEN_BRACE event_accessor_declarations CLOSE_BRACE
\r
1227 DictionaryEntry pair = (DictionaryEntry) $7;
\r
1228 Block add_block = null;
\r
1229 Block rem_block = null;
\r
1231 if (pair.Key != null)
\r
1232 add_block = (Block) pair.Key;
\r
1233 if (pair.Value != null)
\r
1234 rem_block = (Block) pair.Value;
\r
1236 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block, (Attributes) $1);
\r
1238 CheckDef (current_container.AddEvent (e), e.Name);
\r
1242 event_accessor_declarations
\r
1243 : add_accessor_declaration remove_accessor_declaration
\r
1245 $$ = new DictionaryEntry ($1, $2);
\r
1247 | remove_accessor_declaration add_accessor_declaration
\r
1249 $$ = new DictionaryEntry ($2, $1);
\r
1253 add_accessor_declaration
\r
1254 : opt_attributes ADD block
\r
1260 remove_accessor_declaration
\r
1261 : opt_attributes REMOVE block
\r
1267 indexer_declaration
\r
1268 : opt_attributes opt_modifiers indexer_declarator
\r
1271 IndexerDeclaration decl = (IndexerDeclaration) $3;
\r
1273 lexer.properties = true;
\r
1274 parsing_indexer = true;
\r
1276 current_local_parameters = decl.param_list;
\r
1278 accessor_declarations
\r
1280 lexer.properties = false;
\r
1281 parsing_indexer = false;
\r
1285 // The signature is computed from the signature of the indexer. Look
\r
1286 // at section 3.6 on the spec
\r
1289 IndexerDeclaration decl = (IndexerDeclaration) $3;
\r
1290 DictionaryEntry pair = (DictionaryEntry) $6;
\r
1291 Block get_block = null;
\r
1292 Block set_block = null;
\r
1294 if (pair.Key != null)
\r
1295 get_block = (Block) pair.Key;
\r
1296 if (pair.Value != null)
\r
1297 set_block = (Block) pair.Value;
\r
1299 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
\r
1300 get_block, set_block, (Attributes) $1);
\r
1302 // Note that there is no equivalent of CheckDef for this case
\r
1303 // We shall handle this in semantic analysis
\r
1305 current_container.AddIndexer (indexer);
\r
1307 current_local_parameters = null;
\r
1311 indexer_declarator
\r
1312 : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1314 $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);
\r
1316 | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1318 $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);
\r
1330 string name = (string) $4;
\r
1331 Enum e = new Enum ((string) $5, (int) $2, name, (Attributes) $1);
\r
1333 foreach (VariableDeclaration ev in (ArrayList) $6){
\r
1334 CheckDef (e.AddEnumMember (ev.identifier,
\r
1335 (Expression) ev.expression_or_array_initializer),
\r
1339 CheckDef (current_container.AddEnum (e), name);
\r
1344 : /* empty */ { $$ = "System.Int32"; }
\r
1345 | COLON integral_type { $$ = $2; }
\r
1349 : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
\r
1355 opt_enum_member_declarations
\r
1356 : /* empty */ { $$ = new ArrayList (); }
\r
1357 | enum_member_declarations opt_comma { $$ = $1; }
\r
1360 enum_member_declarations
\r
1361 : enum_member_declaration
\r
1363 ArrayList l = new ArrayList ();
\r
1368 | enum_member_declarations COMMA enum_member_declaration
\r
1370 ArrayList l = (ArrayList) $1;
\r
1378 enum_member_declaration
\r
1379 : opt_attributes IDENTIFIER
\r
1381 $$ = new VariableDeclaration ((string) $2, null);
\r
1383 | opt_attributes IDENTIFIER ASSIGN expression
\r
1385 $$ = new VariableDeclaration ((string) $2, $4);
\r
1389 delegate_declaration
\r
1393 IDENTIFIER OPEN_PARENS
\r
1394 formal_parameter_list
\r
1398 Delegate del = new Delegate ((string) $4, (int) $2, (string) $5, (Parameters) $7, (Attributes) $1);
\r
1400 CheckDef (current_container.AddDelegate (del), del.Name);
\r
1405 IDENTIFIER OPEN_PARENS
\r
1406 formal_parameter_list
\r
1410 Delegate del = new Delegate (null, (int) $2, (string) $5, (Parameters) $7, (Attributes) $1);
\r
1412 CheckDef (current_container.AddDelegate (del), del.Name);
\r
1417 : namespace_or_type_name
\r
1420 namespace_or_type_name
\r
1421 : qualified_identifier
\r
1425 * Before you think of adding a return_type, notice that we have been
\r
1426 * using two rules in the places where it matters (one rule using type
\r
1427 * and another identical one that uses VOID as the return type). This
\r
1428 * gets rid of a shift/reduce couple
\r
1431 : type_name { /* class_type */
\r
1433 This does interfaces, delegates, struct_types, class_types,
\r
1434 parent classes, and more! 4.2
\r
1445 ArrayList types = new ArrayList ();
\r
1450 | type_list COMMA type
\r
1452 ArrayList types = (ArrayList) $1;
\r
1460 * replaces all the productions for isolating the various
\r
1461 * simple types, but we need this to reuse it easily in local_variable_type
\r
1464 : OBJECT { $$ = "System.Object"; }
\r
1465 | STRING { $$ = "System.String"; }
\r
1466 | BOOL { $$ = "System.Boolean"; }
\r
1467 | DECIMAL { $$ = "System.Decimal"; }
\r
1468 | FLOAT { $$ = "System.Single"; }
\r
1469 | DOUBLE { $$ = "System.Double"; }
\r
1474 : SBYTE { $$ = "System.SByte"; }
\r
1475 | BYTE { $$ = "System.Byte"; }
\r
1476 | SHORT { $$ = "System.Int16"; }
\r
1477 | USHORT { $$ = "System.UInt16"; }
\r
1478 | INT { $$ = "System.Int32"; }
\r
1479 | UINT { $$ = "System.UInt32"; }
\r
1480 | LONG { $$ = "System.Int64"; }
\r
1481 | ULONG { $$ = "System.UInt64"; }
\r
1482 | CHAR { $$ = "System.Char"; }
\r
1490 : type rank_specifiers
\r
1492 $$ = (string) $1 + (string) $2;
\r
1497 // Expressions, section 7.5
\r
1499 primary_expression
\r
1502 // 7.5.1: Literals
\r
1506 | qualified_identifier
\r
1508 string name = (string) $1;
\r
1511 if (name.IndexOf ('.') == -1){
\r
1513 // we need to check against current_block not being null
\r
1514 // as `expression' is allowed in argument_lists, which
\r
1515 // do not exist inside a block.
\r
1517 if (current_block != null){
\r
1518 if (current_block.IsVariableDefined (name))
\r
1519 $$ = new LocalVariableReference (current_block, name);
\r
1521 if (($$ == null) && (current_local_parameters != null)){
\r
1523 Parameter par = current_local_parameters.GetParameterByName (name, out idx);
\r
1525 $$ = new ParameterReference (current_local_parameters, idx, name);
\r
1529 $$ = new SimpleName (name);
\r
1531 | parenthesized_expression
\r
1533 | invocation_expression
\r
1537 | post_increment_expression
\r
1538 | post_decrement_expression
\r
1540 | typeof_expression
\r
1541 | sizeof_expression
\r
1542 | checked_expression
\r
1543 | unchecked_expression
\r
1550 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
\r
1551 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
\r
1552 | NULL { $$ = new NullLiteral (); }
\r
1556 : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }
\r
1557 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
\r
1558 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
\r
1562 : LITERAL_INTEGER { $$ = new IntLiteral ((Int32) lexer.Value); }
\r
1566 : TRUE { $$ = new BoolLiteral (true); }
\r
1567 | FALSE { $$ = new BoolLiteral (false); }
\r
1570 parenthesized_expression
\r
1571 : OPEN_PARENS expression CLOSE_PARENS
\r
1576 : primary_expression DOT IDENTIFIER
\r
1578 $$ = new MemberAccess ((Expression) $1, (string) $3);
\r
1580 | predefined_type DOT IDENTIFIER
\r
1582 $$ = new BuiltinTypeAccess ((string) $1, (string) $3);
\r
1590 invocation_expression
\r
1591 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1594 // if $1 is MethodGroup
\r
1595 // $$ = new Call ($1, $3);
\r
1597 // $$ = new DelegateCall ($1, $3);
\r
1599 Location l = lexer.Location;
\r
1600 rc.Report.Error (1, l, "THIS IS CRAZY");
\r
1602 $$ = new Invocation ((Expression) $1, (ArrayList) $3);
\r
1607 : /* empty */ { $$ = null; }
\r
1614 ArrayList list = new ArrayList ();
\r
1618 | argument_list COMMA argument
\r
1620 ArrayList list = (ArrayList) $1;
\r
1629 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
\r
1631 | REF variable_reference
\r
1633 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
\r
1635 | OUT variable_reference
\r
1637 $$ = new Argument ((Expression) $2, Argument.AType.Out);
\r
1641 variable_reference
\r
1642 : expression { note ("section 5.4"); $$ = $1; }
\r
1646 : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1648 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3);
\r
1655 ArrayList list = new ArrayList ();
\r
1659 | expression_list COMMA expression
\r
1661 ArrayList list = (ArrayList) $1;
\r
1675 : BASE DOT IDENTIFIER
\r
1677 $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);
\r
1679 | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1681 $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);
\r
1685 post_increment_expression
\r
1686 : primary_expression OP_INC
\r
1688 $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1);
\r
1692 post_decrement_expression
\r
1693 : primary_expression OP_DEC
\r
1695 $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1);
\r
1700 : object_or_delegate_creation_expression
\r
1701 | array_creation_expression
\r
1704 object_or_delegate_creation_expression
\r
1705 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1707 $$ = new New ((string) $2, (ArrayList) $4);
\r
1711 array_creation_expression
\r
1712 : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1713 opt_rank_specifier
\r
1714 opt_array_initializer
\r
1716 $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7);
\r
1720 opt_rank_specifier
\r
1736 | rank_specifier rank_specifiers
\r
1738 $$ = (string) $1 + (string) $2;
\r
1743 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
1745 $$ = "[" + (string) $2 + "]";
\r
1749 opt_dim_separators
\r
1765 | dim_separators COMMA
\r
1767 $$ =(string) $1 + ",";
\r
1771 opt_array_initializer
\r
1776 | array_initializer
\r
1783 : OPEN_BRACE CLOSE_BRACE
\r
1785 ArrayList list = new ArrayList ();
\r
1788 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
\r
1790 $$ = (ArrayList) $2;
\r
1794 variable_initializer_list
\r
1795 : variable_initializer
\r
1797 ArrayList list = new ArrayList ();
\r
1801 | variable_initializer_list COMMA variable_initializer
\r
1803 ArrayList list = (ArrayList) $1;
\r
1810 : TYPEOF OPEN_PARENS type CLOSE_PARENS
\r
1812 $$ = new TypeOf ((string) $3);
\r
1817 : SIZEOF OPEN_PARENS type CLOSE_PARENS {
\r
1818 $$ = new SizeOf ((string) $3);
\r
1820 note ("Verify type is unmanaged");
\r
1821 note ("if (5.8) builtin, yield constant expression");
\r
1825 checked_expression
\r
1826 : CHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1828 $$ = new CheckedExpr ((Expression) $3);
\r
1832 unchecked_expression
\r
1833 : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1835 $$ = new UnCheckedExpr ((Expression) $3);
\r
1840 : primary_expression
\r
1841 | PLUS unary_expression {
\r
1842 $$ = new Unary (Unary.Operator.Plus, (Expression) $2);
\r
1844 | MINUS unary_expression
\r
1846 $$ = new Unary (Unary.Operator.Minus, (Expression) $2);
\r
1848 | BANG unary_expression
\r
1850 $$ = new Unary (Unary.Operator.Negate, (Expression) $2);
\r
1852 | TILDE unary_expression
\r
1854 $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2);
\r
1856 | STAR unary_expression
\r
1858 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2);
\r
1860 | BITWISE_AND unary_expression
\r
1862 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);
\r
1864 | OP_INC unary_expression
\r
1866 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1868 | OP_DEC unary_expression
\r
1870 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1872 | cast_expression
\r
1874 we can not do cast expressions at this level,
\r
1875 as there is an ambiguity. Check "Cast Expressions" 7.6.8
\r
1876 for the recipe to handle this.
\r
1880 pre_increment_expression
\r
1881 : OP_INC unary_expression
\r
1883 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1887 pre_decrement_expression
\r
1888 : OP_DEC unary_expression
\r
1890 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1896 * FIXME: This is actually wrong, it should be `type' but that
\r
1897 * introduces a lot of {shift,reduce}/reduces
\r
1899 * This is really really wrong. We need to track down
\r
1900 * the source of problems with QIs because expressions like:
\r
1901 * foreach (string s in (string []) object) wont be parsed.
\r
1903 : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression
\r
1905 $$ = new Cast ((string) $2, (Expression) $4);
\r
1907 | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
\r
1909 $$ = new Cast ((string) $2, (Expression) $4);
\r
1913 multiplicative_expression
\r
1914 : unary_expression
\r
1915 | multiplicative_expression STAR unary_expression
\r
1917 $$ = new Binary (Binary.Operator.Multiply,
\r
1918 (Expression) $1, (Expression) $3);
\r
1920 | multiplicative_expression DIV unary_expression
\r
1922 $$ = new Binary (Binary.Operator.Divide,
\r
1923 (Expression) $1, (Expression) $3);
\r
1925 | multiplicative_expression PERCENT unary_expression
\r
1927 $$ = new Binary (Binary.Operator.Modulo,
\r
1928 (Expression) $1, (Expression) $3);
\r
1932 additive_expression
\r
1933 : multiplicative_expression
\r
1934 | additive_expression PLUS multiplicative_expression
\r
1936 $$ = new Binary (Binary.Operator.Add,
\r
1937 (Expression) $1, (Expression) $3);
\r
1939 | additive_expression MINUS multiplicative_expression
\r
1941 $$ = new Binary (Binary.Operator.Substract,
\r
1942 (Expression) $1, (Expression) $3);
\r
1947 : additive_expression
\r
1948 | shift_expression OP_SHIFT_LEFT additive_expression
\r
1950 $$ = new Binary (Binary.Operator.ShiftLeft,
\r
1951 (Expression) $1, (Expression) $3);
\r
1953 | shift_expression OP_SHIFT_RIGHT additive_expression
\r
1955 $$ = new Binary (Binary.Operator.ShiftRight,
\r
1956 (Expression) $1, (Expression) $3);
\r
1960 relational_expression
\r
1961 : shift_expression
\r
1962 | relational_expression OP_LT shift_expression
\r
1964 $$ = new Binary (Binary.Operator.LessThan,
\r
1965 (Expression) $1, (Expression) $3);
\r
1967 | relational_expression OP_GT shift_expression
\r
1969 $$ = new Binary (Binary.Operator.GreatherThan,
\r
1970 (Expression) $1, (Expression) $3);
\r
1972 | relational_expression OP_LE shift_expression
\r
1974 $$ = new Binary (Binary.Operator.LessOrEqual,
\r
1975 (Expression) $1, (Expression) $3);
\r
1977 | relational_expression OP_GE shift_expression
\r
1979 $$ = new Binary (Binary.Operator.GreatherOrEqual,
\r
1980 (Expression) $1, (Expression) $3);
\r
1982 | relational_expression IS type
\r
1984 $$ = new Probe (Probe.Operator.Is,
\r
1985 (Expression) $1, (string) $3);
\r
1987 | relational_expression AS type
\r
1989 $$ = new Probe (Probe.Operator.As,
\r
1990 (Expression) $1, (string) $3);
\r
1994 equality_expression
\r
1995 : relational_expression
\r
1996 | equality_expression OP_EQ relational_expression
\r
1998 $$ = new Binary (Binary.Operator.Equal,
\r
1999 (Expression) $1, (Expression) $3);
\r
2001 | equality_expression OP_NE relational_expression
\r
2003 $$ = new Binary (Binary.Operator.NotEqual,
\r
2004 (Expression) $1, (Expression) $3);
\r
2009 : equality_expression
\r
2010 | and_expression BITWISE_AND equality_expression
\r
2012 $$ = new Binary (Binary.Operator.BitwiseAnd,
\r
2013 (Expression) $1, (Expression) $3);
\r
2017 exclusive_or_expression
\r
2019 | exclusive_or_expression CARRET and_expression
\r
2021 $$ = new Binary (Binary.Operator.ExclusiveOr,
\r
2022 (Expression) $1, (Expression) $3);
\r
2026 inclusive_or_expression
\r
2027 : exclusive_or_expression
\r
2028 | inclusive_or_expression BITWISE_OR exclusive_or_expression
\r
2030 $$ = new Binary (Binary.Operator.BitwiseOr,
\r
2031 (Expression) $1, (Expression) $3);
\r
2035 conditional_and_expression
\r
2036 : inclusive_or_expression
\r
2037 | conditional_and_expression OP_AND inclusive_or_expression
\r
2039 $$ = new Binary (Binary.Operator.LogicalAnd,
\r
2040 (Expression) $1, (Expression) $3);
\r
2044 conditional_or_expression
\r
2045 : conditional_and_expression
\r
2046 | conditional_or_expression OP_OR conditional_and_expression
\r
2048 $$ = new Binary (Binary.Operator.LogicalOr,
\r
2049 (Expression) $1, (Expression) $3);
\r
2053 conditional_expression
\r
2054 : conditional_or_expression
\r
2055 | conditional_or_expression INTERR expression COLON expression
\r
2057 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);
\r
2061 assignment_expression
\r
2062 : unary_expression ASSIGN expression
\r
2064 $$ = new Assign ((Expression) $1, (Expression) $3);
\r
2066 | unary_expression OP_MULT_ASSIGN expression
\r
2068 $$ = new Assign ((Expression) $1,
\r
2069 new Binary (Binary.Operator.Multiply,
\r
2071 (Expression) $3));
\r
2073 | unary_expression OP_DIV_ASSIGN expression
\r
2075 $$ = new Assign ((Expression) $1,
\r
2076 new Binary (Binary.Operator.Divide,
\r
2078 (Expression) $3));
\r
2080 | unary_expression OP_MOD_ASSIGN expression
\r
2082 $$ = new Assign ((Expression) $1,
\r
2083 new Binary (Binary.Operator.Modulo,
\r
2085 (Expression) $3));
\r
2087 | unary_expression OP_ADD_ASSIGN expression
\r
2089 $$ = new Assign ((Expression) $1,
\r
2090 new Binary (Binary.Operator.Add,
\r
2092 (Expression) $3));
\r
2094 | unary_expression OP_SUB_ASSIGN expression
\r
2096 $$ = new Assign ((Expression) $1,
\r
2097 new Binary (Binary.Operator.Substract,
\r
2099 (Expression) $3));
\r
2101 | unary_expression OP_SHIFT_LEFT_ASSIGN expression
\r
2103 $$ = new Assign ((Expression) $1,
\r
2104 new Binary (Binary.Operator.ShiftLeft,
\r
2106 (Expression) $3));
\r
2108 | unary_expression OP_SHIFT_RIGHT_ASSIGN expression
\r
2110 $$ = new Assign ((Expression) $1,
\r
2111 new Binary (Binary.Operator.ShiftRight,
\r
2113 (Expression) $3));
\r
2115 | unary_expression OP_AND_ASSIGN expression
\r
2117 $$ = new Assign ((Expression) $1,
\r
2118 new Binary (Binary.Operator.BitwiseAnd,
\r
2120 (Expression) $3));
\r
2122 | unary_expression OP_OR_ASSIGN expression
\r
2124 $$ = new Assign ((Expression) $1,
\r
2125 new Binary (Binary.Operator.BitwiseOr,
\r
2127 (Expression) $3));
\r
2129 | unary_expression OP_XOR_ASSIGN expression
\r
2131 $$ = new Assign ((Expression) $1,
\r
2132 new Binary (Binary.Operator.ExclusiveOr,
\r
2134 (Expression) $3));
\r
2139 : conditional_expression
\r
2140 | assignment_expression
\r
2143 constant_expression
\r
2147 boolean_expression
\r
2148 : expression { CheckBoolean ((Expression) $1); $$ = $1; }
\r
2160 string full_class_name = MakeName ((string) $4);
\r
2162 new_class = new Class (rc, current_container, full_class_name, (int) $2, (Attributes) $1);
\r
2163 current_container = new_class;
\r
2164 current_container.Namespace = current_namespace;
\r
2165 tree.RecordClass (full_class_name, new_class);
\r
2171 Class new_class = (Class) current_container;
\r
2174 new_class.Bases = (ArrayList) $6;
\r
2176 current_container = current_container.Parent;
\r
2177 CheckDef (current_container.AddClass (new_class), new_class.Name);
\r
2184 : /* empty */ { $$ = (int) 0; }
\r
2190 | modifiers modifier
\r
2192 int m1 = (int) $1;
\r
2193 int m2 = (int) $2;
\r
2195 if ((m1 & m2) != 0) {
\r
2196 Location l = lexer.Location;
\r
2197 rc.Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
\r
2199 $$ = (int) (m1 | m2);
\r
2204 : NEW { $$ = Modifiers.NEW; }
\r
2205 | PUBLIC { $$ = Modifiers.PUBLIC; }
\r
2206 | PROTECTED { $$ = Modifiers.PROTECTED; }
\r
2207 | INTERNAL { $$ = Modifiers.INTERNAL; }
\r
2208 | PRIVATE { $$ = Modifiers.PRIVATE; }
\r
2209 | ABSTRACT { $$ = Modifiers.ABSTRACT; }
\r
2210 | SEALED { $$ = Modifiers.SEALED; }
\r
2211 | STATIC { $$ = Modifiers.STATIC; }
\r
2212 | READONLY { $$ = Modifiers.READONLY; }
\r
2213 | VIRTUAL { $$ = Modifiers.VIRTUAL; }
\r
2214 | OVERRIDE { $$ = Modifiers.OVERRIDE; }
\r
2215 | EXTERN { $$ = Modifiers.EXTERN; }
\r
2219 : /* empty */ { $$ = null; }
\r
2220 | class_base { $$ = $1; }
\r
2224 : COLON type_list { $$ = $2; }
\r
2228 // Statements (8.2)
\r
2232 // A block is "contained" on the following places:
\r
2234 // property_declaration as part of the accessor body (get/set)
\r
2235 // operator_declaration
\r
2236 // constructor_declaration
\r
2237 // destructor_declaration
\r
2238 // event_declaration as part of add_accessor_declaration or remove_accessor_declaration
\r
2243 current_block = new Block (current_block);
\r
2245 opt_statement_list CLOSE_BRACE
\r
2247 while (current_block.Implicit)
\r
2248 current_block = current_block.Parent;
\r
2249 $$ = current_block;
\r
2250 current_block = current_block.Parent;
\r
2254 opt_statement_list
\r
2261 | statement_list statement
\r
2265 : declaration_statement
\r
2267 if ((Block) $1 != current_block){
\r
2268 current_block.AddStatement ((Statement) $1);
\r
2269 current_block = (Block) $1;
\r
2272 | embedded_statement
\r
2274 current_block.AddStatement ((Statement) $1);
\r
2276 | labeled_statement
\r
2278 current_block.AddStatement ((Statement) $1);
\r
2282 embedded_statement
\r
2285 | expression_statement
\r
2286 | selection_statement
\r
2287 | iteration_statement
\r
2290 | checked_statement
\r
2291 | unchecked_statement
\r
2299 $$ = new EmptyStatement ();
\r
2304 : IDENTIFIER COLON statement
\r
2306 string lab = (String) $1;
\r
2309 block = new Block (current_block, lab);
\r
2310 block.AddStatement ((Statement) $3);
\r
2313 if (!current_block.AddLabel (lab, block)){
\r
2314 Location l = lexer.Location;
\r
2315 rc.Report.Error (140, l, "The label '" + lab + "' is a duplicate");
\r
2321 declaration_statement
\r
2322 : local_variable_declaration SEMICOLON // done
\r
2323 | local_constant_declaration SEMICOLON // finishme
\r
2327 * The following is from Rhys' grammar:
\r
2328 * > Types in local variable declarations must be recognized as
\r
2329 * > expressions to prevent reduce/reduce errors in the grammar.
\r
2330 * > The expressions are converted into types during semantic analysis.
\r
2332 local_variable_type
\r
2333 : primary_expression type_suffixes
\r
2335 // FIXME: Do something smart here regarding the composition of the type.
\r
2337 // Ok, the above "primary_expression" is there to get rid of
\r
2338 // both reduce/reduce and shift/reduces in the grammar, it should
\r
2339 // really just be "type_name". If you use type_name, a reduce/reduce
\r
2340 // creeps up. If you use qualified_identifier (which is all we need
\r
2341 // really) two shift/reduces appear.
\r
2343 // So, instead we do a super trick: we just allow ($1) to be a
\r
2344 // SimpleName Expression.
\r
2346 if (((Expression) $1) is SimpleName)
\r
2347 $$ = ((SimpleName) $1).Name;
\r
2349 Location l = lexer.Location;
\r
2350 rc.Report.Error (-1, l, "Invalid Type definition");
\r
2351 $$ = "System.Object";
\r
2354 | builtin_types type_suffixes
\r
2356 $$ = (string) $1 + (string) $2;
\r
2360 // FIXME : How can the type of a local variable be void ? I don't quite see ;-)
\r
2363 // // FIXME: this is a string that represents the type
\r
2364 // // Figure out something to make this work.
\r
2374 | type_suffix_list
\r
2379 | type_suffix_list type_suffix
\r
2381 $$ = (string) $1 + (string) $2;
\r
2386 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
2388 $$ = "[" + (string) $2 + "]";
\r
2392 local_variable_declaration
\r
2393 : local_variable_type variable_declarators
\r
2395 $$ = declare_local_variables ((string) $1, (ArrayList) $2);
\r
2399 local_constant_declaration
\r
2400 : CONST type constant_declarator
\r
2404 expression_statement
\r
2405 : statement_expression SEMICOLON
\r
2412 // We have to do the wrapping here and not in the case above,
\r
2413 // because statement_expression is used for example in for_statement
\r
2415 statement_expression
\r
2416 : invocation_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2417 | object_creation_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2418 | assignment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2419 | post_increment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2420 | post_decrement_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2421 | pre_increment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2422 | pre_decrement_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2425 object_creation_expression
\r
2426 : object_or_delegate_creation_expression
\r
2427 { note ("complain if this is a delegate maybe?"); }
\r
2430 selection_statement
\r
2432 | switch_statement
\r
2436 : IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2437 embedded_statement
\r
2439 $$ = new If ((Expression) $3, (Statement) $5);
\r
2441 | IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2442 embedded_statement ELSE embedded_statement
\r
2444 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
\r
2449 : SWITCH OPEN_PARENS expression CLOSE_PARENS
\r
2452 $$ = new Switch ((Expression) $3, (ArrayList) $5);
\r
2458 opt_switch_sections
\r
2465 opt_switch_sections
\r
2466 : /* empty */ { $$ = new ArrayList (); }
\r
2473 ArrayList sections = new ArrayList ();
\r
2475 sections.Add ($1);
\r
2478 | switch_sections switch_section
\r
2480 ArrayList sections = (ArrayList) $1;
\r
2482 sections.Add ($2);
\r
2490 current_block = new Block (current_block);
\r
2494 while (current_block.Implicit)
\r
2495 current_block = current_block.Parent;
\r
2496 $$ = new SwitchSection ((ArrayList) $1, current_block);
\r
2497 current_block = current_block.Parent;
\r
2504 ArrayList labels = new ArrayList ();
\r
2509 | switch_labels switch_label
\r
2511 ArrayList labels = (ArrayList) ($1);
\r
2519 : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2); }
\r
2520 | DEFAULT COLON { $$ = new SwitchLabel (null); }
\r
2523 iteration_statement
\r
2527 | foreach_statement
\r
2531 : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
\r
2533 $$ = new While ((Expression) $3, (Statement) $5);
\r
2538 : DO embedded_statement
\r
2539 WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
\r
2541 $$ = new Do ((Statement) $2, (Expression) $5);
\r
2546 : FOR OPEN_PARENS
\r
2547 opt_for_initializer SEMICOLON
\r
2548 opt_for_condition SEMICOLON
\r
2549 opt_for_iterator CLOSE_PARENS
\r
2550 embedded_statement
\r
2552 $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
\r
2556 opt_for_initializer
\r
2557 : /* empty */ { $$ = new EmptyStatement (); }
\r
2558 | for_initializer
\r
2562 : local_variable_declaration
\r
2563 | statement_expression_list
\r
2567 : /* empty */ { $$ = new BoolLiteral (true); }
\r
2568 | boolean_expression
\r
2572 : /* empty */ { $$ = new EmptyStatement (); }
\r
2577 : statement_expression_list
\r
2580 statement_expression_list
\r
2581 : statement_expression
\r
2583 Block b = new Block (null, true);
\r
2585 b.AddStatement ((Statement) $1);
\r
2588 | statement_expression_list COMMA statement_expression
\r
2590 Block b = (Block) $1;
\r
2592 b.AddStatement ((Statement) $3);
\r
2598 : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS
\r
2599 embedded_statement
\r
2601 string temp_id = current_block.MakeInternalID ();
\r
2602 Expression assign_e, ma;
\r
2603 Statement getcurrent;
\r
2604 Block foreach_block, child_block;
\r
2606 foreach_block = new Block (current_block, true);
\r
2608 foreach_block.AddVariable ("System.IEnumerator", temp_id);
\r
2609 foreach_block.AddVariable ((string) $3, (string) $4);
\r
2610 assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id),
\r
2612 new MemberAccess ((Expression) $6, "GetEnumerator"), null));
\r
2613 current_block.AddStatement (new StatementExpression (assign_e));
\r
2614 ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");
\r
2615 child_block = new Block (current_block);
\r
2617 getcurrent = new StatementExpression (
\r
2619 new LocalVariableReference (foreach_block, (string) $4),
\r
2622 new MemberAccess (
\r
2623 new LocalVariableReference (foreach_block, temp_id), "Current"))));
\r
2625 child_block.AddStatement (getcurrent);
\r
2626 child_block.AddStatement ((Statement) $8);
\r
2627 foreach_block.AddStatement (new While (ma, (Statement) child_block));
\r
2629 $$ = foreach_block;
\r
2635 | continue_statement
\r
2637 | return_statement
\r
2644 $$ = new Break ();
\r
2648 continue_statement
\r
2649 : CONTINUE SEMICOLON
\r
2651 $$ = new Continue ();
\r
2656 : GOTO IDENTIFIER SEMICOLON
\r
2658 $$ = new Goto ((string) $2);
\r
2660 | GOTO CASE constant_expression SEMICOLON
\r
2661 | GOTO DEFAULT SEMICOLON
\r
2665 : RETURN opt_expression SEMICOLON
\r
2667 $$ = new Return ((Expression) $2);
\r
2672 : THROW opt_expression SEMICOLON
\r
2674 $$ = new Throw ((Expression) $2);
\r
2684 : TRY block catch_clauses
\r
2687 ArrayList s = new ArrayList ();
\r
2689 foreach (Catch cc in (ArrayList) $3) {
\r
2690 if (cc.Type == null)
\r
2696 // Now s contains the list of specific catch clauses
\r
2697 // and g contains the general one.
\r
2699 $$ = new Try ((Block) $2, s, g, null);
\r
2701 | TRY block opt_catch_clauses FINALLY block
\r
2704 ArrayList s = new ArrayList ();
\r
2706 foreach (Catch cc in (ArrayList) $3) {
\r
2707 if (cc.Type == null)
\r
2713 $$ = new Try ((Block) $2, s, g, (Block) $5);
\r
2718 : /* empty */ { $$ = null; }
\r
2725 ArrayList l = new ArrayList ();
\r
2730 | catch_clauses catch_clause
\r
2732 ArrayList l = (ArrayList) $1;
\r
2740 : /* empty */ { $$ = null; }
\r
2745 : CATCH opt_catch_args block
\r
2747 string type = null;
\r
2751 DictionaryEntry cc = (DictionaryEntry) $2;
\r
2752 type = (string) cc.Key;
\r
2753 id = (string) cc.Value;
\r
2756 $$ = new Catch (type, id, (Block) $3);
\r
2761 : /* empty */ { $$ = null; }
\r
2766 : OPEN_PARENS type opt_identifier CLOSE_PARENS
\r
2768 $$ = new DictionaryEntry ($2, $3);
\r
2775 $$ = new Checked ((Block) $2);
\r
2779 unchecked_statement
\r
2782 $$ = new Unchecked ((Block) $2);
\r
2787 : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
\r
2789 $$ = new Lock ((Expression) $3, (Statement) $5);
\r
2794 : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
\r
2798 resource_acquisition
\r
2799 : local_variable_declaration
\r
2807 // A class used to pass around variable declarations and constants
\r
2809 public class VariableDeclaration {
\r
2810 public string identifier;
\r
2811 public object expression_or_array_initializer;
\r
2813 public VariableDeclaration (string id, object eoai){
\r
2814 this.identifier = id;
\r
2815 this.expression_or_array_initializer = eoai;
\r
2820 // A class used to hold info about an indexer declarator
\r
2823 public class IndexerDeclaration {
\r
2824 public string type;
\r
2825 public string interface_type;
\r
2826 public Parameters param_list;
\r
2828 public IndexerDeclaration (string type, string interface_type, Parameters param_list)
\r
2831 this.interface_type = interface_type;
\r
2832 this.param_list = param_list;
\r
2837 // A class used to hold info about an operator declarator
\r
2840 public class OperatorDeclaration {
\r
2841 public Operator.OpType optype;
\r
2842 public string ret_type;
\r
2843 public string arg1type;
\r
2844 public string arg1name;
\r
2845 public string arg2type;
\r
2846 public string arg2name;
\r
2848 public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
\r
2849 string arg2type, string arg2name)
\r
2852 this.ret_type = ret_type;
\r
2853 this.arg1type = arg1type;
\r
2854 this.arg1name = arg1name;
\r
2855 this.arg2type = arg2type;
\r
2856 this.arg2name = arg2name;
\r
2862 // Given the @class_name name, it creates a fully qualified name
\r
2863 // based on the containing declaration space
\r
2866 MakeName (string class_name)
\r
2868 string ns = current_namespace.Name;
\r
2869 string container_name = current_container.Name;
\r
2871 if (container_name == ""){
\r
2873 return ns + "." + class_name;
\r
2875 return class_name;
\r
2877 return container_name + "." + class_name;
\r
2881 // Used to report back to the user the result of a declaration
\r
2882 // in the current declaration space
\r
2885 CheckDef (DeclSpace.AdditionResult result, string name)
\r
2887 if (result == DeclSpace.AdditionResult.Success)
\r
2890 Location l = lexer.Location;
\r
2893 case DeclSpace.AdditionResult.NameExists:
\r
2894 rc.Report.Error (102, l, "The namespace `" + current_container.Name +
\r
2895 "' already contains a definition for `"+
\r
2900 // NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
\r
2902 // case DeclSpace.AdditionResult.MethodDuplicated:
\r
2903 // error (111, "Class `"+current_container.Name+
\r
2904 // "' already defines a member called '" +
\r
2905 // name + "' with the same parameter types");
\r
2908 case DeclSpace.AdditionResult.EnclosingClash:
\r
2909 rc.Report.Error (542, l, "Member names cannot be the same as their enclosing type");
\r
2912 case DeclSpace.AdditionResult.NotAConstructor:
\r
2913 rc.Report.Error (1520, l, "Class, struct, or interface method must have a return type");
\r
2919 CheckDef (bool result, string name)
\r
2923 CheckDef (DeclSpace.AdditionResult.NameExists, name);
\r
2926 Block declare_local_variables (string type, ArrayList variable_declarators)
\r
2928 Block implicit_block;
\r
2929 ArrayList inits = null;
\r
2932 // We use the `Used' property to check whether statements
\r
2933 // have been added to the current block. If so, we need
\r
2934 // to create another block to contain the new declaration
\r
2935 // otherwise, as an optimization, we use the same block to
\r
2936 // add the declaration.
\r
2938 // FIXME: A further optimization is to check if the statements
\r
2939 // that were added were added as part of the initialization
\r
2940 // below. In which case, no other statements have been executed
\r
2941 // and we might be able to reduce the number of blocks for
\r
2942 // situations like this:
\r
2944 // int j = 1; int k = j + 1;
\r
2946 if (current_block.Used)
\r
2947 implicit_block = new Block (current_block, true);
\r
2949 implicit_block = new Block (current_block, true);
\r
2951 foreach (VariableDeclaration decl in variable_declarators){
\r
2952 if (implicit_block.AddVariable (type, decl.identifier)){
\r
2953 if (decl.expression_or_array_initializer != null){
\r
2954 if (inits == null)
\r
2955 inits = new ArrayList ();
\r
2959 Location l = lexer.Location;
\r
2960 rc.Report.Error (128, l, "A local variable `" + decl.identifier +
\r
2961 "' is already defined in this scope");
\r
2965 if (inits == null)
\r
2966 return implicit_block;
\r
2968 foreach (VariableDeclaration decl in inits){
\r
2969 if (decl.expression_or_array_initializer is Expression){
\r
2970 Expression expr = (Expression) decl.expression_or_array_initializer;
\r
2973 assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr);
\r
2974 implicit_block.AddStatement (new StatementExpression (assign));
\r
2976 Console.WriteLine ("Not handling Array initializers yet");
\r
2980 return implicit_block;
\r
2983 void CheckConstant (Expression expr)
\r
2988 void CheckBoolean (Expression expr)
\r
2993 void CheckAttributeTarget (string a)
\r
2997 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
\r
3001 Location l = lexer.Location;
\r
3002 rc.Report.Error (658, l, "Invalid attribute target");
\r
3008 void CheckUnaryOperator (Operator.OpType op)
\r
3012 case Operator.OpType.Bang : case Operator.OpType.Tilde : case Operator.OpType.Increment :
\r
3013 case Operator.OpType.Decrement :
\r
3014 case Operator.OpType.True : case Operator.OpType.False : case Operator.OpType.Plus : case Operator.OpType.Minus :
\r
3019 Location l = lexer.Location;
\r
3020 rc.Report.Error (1019, l, "Overloadable unary operator expected");
\r
3026 void CheckBinaryOperator (Operator.OpType op)
\r
3030 case Operator.OpType.Plus : case Operator.OpType.Minus : case Operator.OpType.Star : case Operator.OpType.Div :
\r
3031 case Operator.OpType.Percent : case Operator.OpType.BitAnd : case Operator.OpType.BitOr :
\r
3032 case Operator.OpType.Carret : case Operator.OpType.ShiftLeft : case Operator.OpType.ShiftRight :
\r
3033 case Operator.OpType.Eq : case Operator.OpType.NotEq :
\r
3034 case Operator.OpType.GreaterThan : case Operator.OpType.LesserThan : case Operator.OpType.GreaterOrEq :
\r
3035 case Operator.OpType.LesserOrEq :
\r
3040 Location l = lexer.Location;
\r
3041 rc.Report.Error (1020, l, "Overloadable binary operator expected");
\r
3047 void output (string s)
\r
3049 Console.WriteLine (s);
\r
3052 void note (string s)
\r
3054 // Used to put annotations
\r
3059 public Tokenizer Lexer {
\r
3065 public CSharpParser(RootContext rc, string name, System.IO.Stream input)
\r
3067 current_namespace = new Namespace (null, "");
\r
3069 this.tree = rc.Tree;
\r
3071 this.input = input;
\r
3072 current_container = tree.Types;
\r
3073 current_container.Namespace = current_namespace;
\r
3075 lexer = new Tokenizer (input, name);
\r
3078 public override int parse ()
\r
3080 StringBuilder value = new StringBuilder ();
\r
3082 global_errors = 0;
\r
3084 if (yacc_verbose_flag)
\r
3085 yyparse (lexer, new yydebug.yyDebugSimple ());
\r
3088 } catch (Exception e){
\r
3089 // Console.WriteLine ("Fatal error: " + name);
\r
3090 // Console.WriteLine (lexer.location);
\r
3092 Console.WriteLine (lexer.location + " : Parsing error");
\r
3093 Console.WriteLine (e);
\r
3097 return global_errors;
\r