4 // This loop is pointless:
5 // while (current_block != prev_block)
6 // current_block = current_block.Parent;
8 // cs-parser.jay: The Parser for the C# compiler
10 // Author: Miguel de Icaza (miguel@gnu.org)
12 // Licensed under the terms of the GNU GPL
14 // (C) 2001 Ximian, Inc (http://www.ximian.com)
17 // (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM
18 // And come to think of it, it is not that great, it duplicates a lot of code
19 // for something which is not really needed. We still have piles of typecasts
20 // anwyays (due to the nature of the stack being a collection of Objects).
22 // (2) Figure out why error productions dont work. `type-declaration' is a
23 // great spot to put an `error' because you can reproduce it with this input:
26 // (3) Move Modifier checking from each object into the parser itself, that will
27 // get rid of the global "error" symbol that we use now to report errors.
28 // We still need to pass a pointer to the tree.ErrorHandler, but that is a
36 using System.Collections;
42 public class CSharpParser : GenericParser {
43 Namespace current_namespace;
44 TypeContainer current_container;
47 // Current block is used to add statements as we find
54 // Current interface is used by the various declaration
55 // productions in the interface declaration to "add"
56 // the interfaces as we find them.
58 Interface current_interface;
61 // This is used by the unary_expression code to resolve
62 // a name against a parameter.
64 Parameters current_local_parameters;
67 // Using during property parsing to describe the implicit
68 // value parameter that is passed to the "set" and "get"accesor
69 // methods (properties and indexers).
71 string implicit_value_parameter_type;
72 Parameters indexer_parameters;
75 // Used to determine if we are parsing the get/set pair
76 // of an indexer or a property
81 // An out-of-band stack.
87 %token NONE /* This token is never returned by our lexer */
88 %token ERROR // This is used not by the parser, but by the tokenizer.
92 *These are the C# keywords
175 /* C# keywords which are not really keywords */
179 /* C# single character operators/punctuation. */
180 %token OPEN_BRACE "{"
181 %token CLOSE_BRACE "}"
182 %token OPEN_BRACKET "["
183 %token CLOSE_BRACKET "]"
184 %token OPEN_PARENS "("
185 %token CLOSE_PARENS ")"
198 %token BITWISE_AND "&"
199 %token BITWISE_OR "|"
206 /* C# multi-character operators. */
209 %token OP_SHIFT_LEFT "<<"
210 %token OP_SHIFT_RIGHT ">>"
217 %token OP_MULT_ASSIGN "*="
218 %token OP_DIV_ASSIGN "/="
219 %token OP_MOD_ASSIGN "%="
220 %token OP_ADD_ASSIGN "+="
221 %token OP_SUB_ASSIGN "-="
222 %token OP_SHIFT_LEFT_ASSIGN "<<="
223 %token OP_SHIFT_RIGHT_ASSIGN ">>="
224 %token OP_AND_ASSIGN "&="
225 %token OP_XOR_ASSIGN "^="
226 %token OP_OR_ASSIGN "|="
230 %token LITERAL_INTEGER "int literal"
231 %token LITERAL_FLOAT "float literal"
232 %token LITERAL_DOUBLE "double literal"
233 %token LITERAL_DECIMAL "decimal literal"
234 %token LITERAL_CHARACTER "character literal"
235 %token LITERAL_STRING "string literal"
239 /* Add precedence rules to solve dangling else s/r conflict */
248 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
250 %left STAR DIV PERCENT
251 %right BANG CARRET UMINUS
252 %nonassoc OP_INC OP_DEC
254 %left OPEN_BRACKET OPEN_BRACE
258 %start compilation_unit
259 /*%start namespace_declaration */
263 : opt_using_directives opt_namespace_member_declarations opt_attributes opt_EOF
265 // Check that using comes only before namespace elements
276 | using_directives using_directive
280 : using_alias_directive
281 | using_namespace_directive
284 using_alias_directive
285 : USING IDENTIFIER ASSIGN
286 namespace_or_type_name SEMICOLON
288 current_namespace.UsingAlias ((string) $2, (string) $4, lexer.Location);
292 using_namespace_directive
293 : USING namespace_name SEMICOLON
295 current_namespace.Using ((string) $2);
299 // namespace_declarations
300 // : namespace_declaration
301 // | namespace_declarations namespace_declaration
303 namespace_declaration
304 : NAMESPACE qualified_identifier
306 current_namespace = RootContext.Tree.RecordNamespace (current_namespace, name, (string) $2);
308 namespace_body opt_semicolon
310 current_namespace = current_namespace.Parent;
326 | qualified_identifier DOT IDENTIFIER {
327 $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
332 : namespace_or_type_name
338 opt_namespace_member_declarations
349 opt_namespace_member_declarations
351 | namespace_member_declarations
354 namespace_member_declarations
355 : namespace_member_declaration
356 | namespace_member_declarations namespace_member_declaration
359 namespace_member_declaration
366 Class c = (Class) $1;
367 mod_flags = c.ModFlags;
369 } else if ($1 is Struct){
370 Struct s = (Struct) $1;
371 mod_flags = s.ModFlags;
376 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
378 1527, lexer.Location,
379 "Namespace elements cant be explicitly " +
380 "declared private or protected in `" + name + "'");
383 | namespace_declaration
389 | interface_declaration
391 | delegate_declaration
393 // Enable this when we have handled all errors, because this acts as a generic fallback
396 // Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
404 : /* empty */ { $$ = null; }
405 | attribute_section opt_attributes
407 Attributes attrs = null;
408 AttributeSection sect = (AttributeSection) $1;
410 if (sect.Target == "assembly"){
411 RootContext.AddGlobalAttributes (sect, lexer.Location);
417 attrs = (Attributes) $2;
418 attrs.AddAttribute (sect);
422 attrs = new Attributes (sect, lexer.Location);
430 : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET
432 string target = null;
435 target = (string) $2;
437 $$ = new AttributeSection (target, (ArrayList) $3);
439 | OPEN_BRACKET attribute_list CLOSE_BRACKET
441 $$ = new AttributeSection (null, (ArrayList) $2);
445 attribute_target_specifier
446 : attribute_target COLON
455 CheckAttributeTarget ((string) $1);
458 | EVENT { $$ = "event"; }
459 | RETURN { $$ = "return"; }
465 ArrayList attrs = new ArrayList ();
471 | attribute_list COMMA attribute
473 ArrayList attrs = (ArrayList) $1;
485 opt_attribute_arguments
487 $$ = new Attribute ((string) $1, (ArrayList) $3, (Location) $2);
492 : type_name { /* reserved attribute name or identifier: 17.4 */ }
495 opt_attribute_arguments
496 : /* empty */ { $$ = null; }
497 | OPEN_PARENS attribute_arguments CLOSE_PARENS
505 : opt_positional_argument_list
510 ArrayList args = new ArrayList ();
516 | positional_argument_list COMMA named_argument_list
518 ArrayList args = new ArrayList ();
524 | named_argument_list
526 ArrayList args = new ArrayList ();
535 opt_positional_argument_list
536 : /* empty */ { $$ = null; }
537 | positional_argument_list
540 positional_argument_list
543 ArrayList args = new ArrayList ();
544 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
548 | positional_argument_list COMMA expression
550 ArrayList args = (ArrayList) $1;
551 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
560 ArrayList args = new ArrayList ();
565 | named_argument_list COMMA named_argument
567 ArrayList args = (ArrayList) $1;
575 : IDENTIFIER ASSIGN expression
577 $$ = new DictionaryEntry (
579 new Argument ((Expression) $3, Argument.AType.Expression));
585 : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
588 opt_class_member_declarations
590 | class_member_declarations
593 class_member_declarations
594 : class_member_declaration
595 | class_member_declarations
596 class_member_declaration
599 class_member_declaration
600 : constant_declaration // done
601 | field_declaration // done
602 | method_declaration // done
603 | property_declaration // done
604 | event_declaration // done
605 | indexer_declaration // done
606 | operator_declaration // done
607 | constructor_declaration // done
608 | destructor_declaration // done
618 string full_struct_name = MakeName ((string) $4);
620 new_struct = new Struct (current_container, full_struct_name, (int) $2,
621 (Attributes) $1, lexer.Location);
622 current_container = new_struct;
623 current_container.Namespace = current_namespace;
624 RootContext.Tree.RecordStruct (full_struct_name, new_struct);
626 opt_struct_interfaces
630 Struct new_struct = (Struct) current_container;
632 current_container = current_container.Parent;
633 CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
638 opt_struct_interfaces
645 | struct_interfaces struct_interface
653 : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
656 opt_struct_member_declarations
658 | struct_member_declarations
661 struct_member_declarations
662 : struct_member_declaration
663 | struct_member_declarations struct_member_declaration
666 struct_member_declaration
667 : constant_declaration
670 | property_declaration
672 | indexer_declaration
673 | operator_declaration
674 | constructor_declaration
678 * This is only included so we can flag error 575:
679 * destructors only allowed on class types
681 | destructor_declaration
692 foreach (VariableDeclaration constant in (ArrayList) $5){
693 Const c = new Const (
694 (string) $4, (string) constant.identifier,
695 (Expression) constant.expression_or_array_initializer, (int) $2, (Attributes) $1,
698 CheckDef (current_container.AddConstant (c), c.Name);
704 : constant_declarator
706 ArrayList constants = new ArrayList ();
710 | constant_declarators COMMA constant_declarator
712 ArrayList constants = (ArrayList) $1;
719 : IDENTIFIER ASSIGN constant_expression
721 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
732 string type = (string) $3;
735 foreach (VariableDeclaration var in (ArrayList) $4){
736 Field field = new Field (type, mod, var.identifier,
737 var.expression_or_array_initializer, (Attributes) $1, var.Location);
739 CheckDef (current_container.AddField (field), field.Name);
745 : variable_declarator
747 ArrayList decl = new ArrayList ();
751 | variable_declarators COMMA variable_declarator
753 ArrayList decls = (ArrayList) $1;
760 : IDENTIFIER ASSIGN variable_initializer
762 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
766 $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
779 | STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
781 $$ = new StackAlloc ((string) $2, (Expression) $4, lexer.Location);
789 Method method = (Method) $1;
790 Block b = (Block) $2;
791 const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT);
794 if ((method.ModFlags & extern_abstract) == 0){
796 501, lexer.Location, current_container.MakeName (method.Name) +
797 "must declare a body because it is not marked abstract or extern");
800 if ((method.ModFlags & Modifiers.EXTERN) != 0){
802 179, lexer.Location, current_container.MakeName (method.Name) +
803 " is declared extern, but has a body");
807 method.Block = (Block) $2;
808 CheckDef (current_container.AddMethod (method), method.Name);
810 current_local_parameters = null;
824 1585, lexer.Location, "Member modifier `" +
825 Modifiers.Name (i) + "' must precede member type and name");
838 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
840 Method method = new Method ((string) $3, (int) $2, (string) $4,
841 (Parameters) $6, (Attributes) $1, lexer.Location);
843 current_local_parameters = (Parameters) $6;
851 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
853 Method method = new Method ("System.Void", (int) $2, (string) $4,
854 (Parameters) $6, (Attributes) $1, lexer.Location);
856 current_local_parameters = (Parameters) $6;
863 | SEMICOLON { $$ = null; }
866 opt_formal_parameter_list
867 : /* empty */ { $$ = Parameters.GetEmptyReadOnlyParameters (); }
868 | formal_parameter_list
871 formal_parameter_list
874 ArrayList pars_list = (ArrayList) $1;
876 Parameter [] pars = new Parameter [pars_list.Count];
877 pars_list.CopyTo (pars);
879 $$ = new Parameters (pars, null, lexer.Location);
881 | fixed_parameters COMMA parameter_array
883 ArrayList pars_list = (ArrayList) $1;
885 Parameter [] pars = new Parameter [pars_list.Count];
886 pars_list.CopyTo (pars);
888 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
892 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
899 ArrayList pars = new ArrayList ();
904 | fixed_parameters COMMA fixed_parameter
906 ArrayList pars = (ArrayList) $1;
915 opt_parameter_modifier
919 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
923 opt_parameter_modifier
924 : /* empty */ { $$ = Parameter.Modifier.NONE; }
929 : REF { $$ = Parameter.Modifier.REF; }
930 | OUT { $$ = Parameter.Modifier.OUT; }
934 : opt_attributes PARAMS type IDENTIFIER
936 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
937 note ("type must be a single-dimension array type");
942 : qualified_identifier
951 implicit_value_parameter_type = (string) $3;
953 lexer.PropertyParsing = true;
957 accessor_declarations
959 lexer.PropertyParsing = false;
964 Pair pair = (Pair) $7;
965 Block get_block = null;
966 Block set_block = null;
968 if (pair.First != null)
969 get_block = (Block) pair.First;
970 if (pair.Second != null)
971 set_block = (Block) pair.Second;
973 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block,
974 (Attributes) $1, (Location) $6);
976 CheckDef (current_container.AddProperty (prop), prop.Name);
977 implicit_value_parameter_type = null;
981 accessor_declarations
982 : get_accessor_declaration opt_set_accessor_declaration
984 $$ = new Pair ($1, $2);
986 | set_accessor_declaration opt_get_accessor_declaration
988 $$ = new Pair ($2, $1);
992 opt_get_accessor_declaration
993 : /* empty */ { $$ = null; }
994 | get_accessor_declaration
997 opt_set_accessor_declaration
998 : /* empty */ { $$ = null; }
999 | set_accessor_declaration
1002 get_accessor_declaration
1003 : opt_attributes GET
1005 // If this is not the case, then current_local_parameters has already
1006 // been set in indexer_declaration
1007 if (parsing_indexer == false)
1008 current_local_parameters = null;
1010 current_local_parameters = indexer_parameters;
1011 lexer.PropertyParsing = false;
1016 current_local_parameters = null;
1017 lexer.PropertyParsing = true;
1021 set_accessor_declaration
1022 : opt_attributes SET
1025 Parameter implicit_value_parameter = new Parameter (
1026 implicit_value_parameter_type, "value",
1027 Parameter.Modifier.NONE, null);
1029 if (parsing_indexer == false) {
1030 args = new Parameter [1];
1031 args [0] = implicit_value_parameter;
1033 Parameter [] fp = indexer_parameters.FixedParameters;
1034 int count = fp.Length;
1036 args = new Parameter [count + 1];
1038 fp.CopyTo (args, 0);
1039 args [count] = implicit_value_parameter;
1042 current_local_parameters = new Parameters (args, null, lexer.Location);
1043 lexer.PropertyParsing = false;
1048 current_local_parameters = null;
1049 lexer.PropertyParsing = true;
1055 | SEMICOLON { $$ = new Block (null); }
1058 interface_declaration
1061 INTERFACE IDENTIFIER
1063 Interface new_interface;
1064 string full_interface_name = MakeName ((string) $4);
1066 new_interface = new Interface (current_container, full_interface_name, (int) $2,
1067 (Attributes) $1, lexer.Location);
1068 if (current_interface != null) {
1069 Location l = lexer.Location;
1070 Report.Error (-2, l, "Internal compiler error: interface inside interface");
1072 current_interface = new_interface;
1073 new_interface.Namespace = current_namespace;
1074 RootContext.Tree.RecordInterface (full_interface_name, new_interface);
1077 interface_body opt_semicolon
1079 Interface new_interface = (Interface) current_interface;
1082 new_interface.Bases = (ArrayList) $6;
1084 current_interface = null;
1085 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
1090 : /* empty */ { $$ = null; }
1095 : COLON interface_type_list { $$ = $2; }
1101 ArrayList interfaces = new ArrayList ();
1103 interfaces.Add ($1);
1106 | interface_type_list COMMA interface_type
1108 ArrayList interfaces = (ArrayList) $1;
1109 interfaces.Add ($3);
1116 opt_interface_member_declarations
1120 opt_interface_member_declarations
1122 | interface_member_declarations
1125 interface_member_declarations
1126 : interface_member_declaration
1127 | interface_member_declarations interface_member_declaration
1130 interface_member_declaration
1131 : interface_method_declaration
1133 InterfaceMethod m = (InterfaceMethod) $1;
1135 CheckDef (current_interface.AddMethod (m), m.Name);
1137 | interface_property_declaration
1139 InterfaceProperty p = (InterfaceProperty) $1;
1141 CheckDef (current_interface.AddProperty (p), p.Name);
1143 | interface_event_declaration
1145 InterfaceEvent e = (InterfaceEvent) $1;
1147 CheckDef (current_interface.AddEvent (e), e.Name);
1149 | interface_indexer_declaration
1151 InterfaceIndexer i = (InterfaceIndexer) $1;
1153 CheckDef (current_interface.AddIndexer (i), "indexer");
1158 : /* empty */ { $$ = false; }
1159 | NEW { $$ = true; }
1162 interface_method_declaration
1163 : opt_attributes opt_new type IDENTIFIER
1164 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1167 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2,
1168 (Parameters) $6, (Attributes) $1, lexer.Location);
1170 | opt_attributes opt_new VOID IDENTIFIER
1171 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1174 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6,
1175 (Attributes) $1, lexer.Location);
1179 interface_property_declaration
1184 { lexer.PropertyParsing = true; }
1186 { lexer.PropertyParsing = false; }
1191 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2,
1192 (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1,
1198 : opt_attributes GET SEMICOLON { $$ = 1; }
1199 | opt_attributes SET SEMICOLON { $$ = 2; }
1200 | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
1202 | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
1206 interface_event_declaration
1207 : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
1209 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);
1213 interface_indexer_declaration
1214 : opt_attributes opt_new type THIS
1215 OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1217 { lexer.PropertyParsing = true; }
1219 { lexer.PropertyParsing = false; }
1222 int a_flags = (int) $10;
1224 bool do_get = (a_flags & 1) == 1;
1225 bool do_set = (a_flags & 2) == 2;
1227 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set,
1228 (bool) $2, (Attributes) $1, lexer.Location);
1232 operator_declaration
1233 : opt_attributes opt_modifiers operator_declarator operator_body
1235 OperatorDeclaration decl = (OperatorDeclaration) $3;
1237 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
1238 decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
1240 // Note again, checking is done in semantic analysis
1241 current_container.AddOperator (op);
1243 current_local_parameters = null;
1249 | SEMICOLON { $$ = null; }
1252 : type OPERATOR overloadable_operator
1253 OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1255 Operator.OpType op = (Operator.OpType) $3;
1256 CheckUnaryOperator (op);
1258 if (op == Operator.OpType.Addition)
1259 op = Operator.OpType.UnaryPlus;
1261 if (op == Operator.OpType.Subtraction)
1262 op = Operator.OpType.UnaryNegation;
1264 Parameter [] pars = new Parameter [1];
1266 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1268 current_local_parameters = new Parameters (pars, null, lexer.Location);
1270 $$ = new OperatorDeclaration (op, (string) $1, (string) $5, (string) $6,
1271 null, null, lexer.Location);
1273 | type OPERATOR overloadable_operator
1275 type IDENTIFIER COMMA
1279 CheckBinaryOperator ((Operator.OpType) $3);
1281 Parameter [] pars = new Parameter [2];
1283 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1284 pars [1] = new Parameter ((string) $8, (string) $9, Parameter.Modifier.NONE, null);
1286 current_local_parameters = new Parameters (pars, null, lexer.Location);
1288 $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
1289 (string) $8, (string) $9, lexer.Location);
1291 | conversion_operator_declarator
1294 overloadable_operator
1296 : BANG { $$ = Operator.OpType.LogicalNot; }
1297 | TILDE { $$ = Operator.OpType.OnesComplement; }
1298 | OP_INC { $$ = Operator.OpType.Increment; }
1299 | OP_DEC { $$ = Operator.OpType.Decrement; }
1300 | TRUE { $$ = Operator.OpType.True; }
1301 | FALSE { $$ = Operator.OpType.False; }
1302 // Unary and binary:
1303 | PLUS { $$ = Operator.OpType.Addition; }
1304 | MINUS { $$ = Operator.OpType.Subtraction; }
1306 | STAR { $$ = Operator.OpType.Multiply; }
1307 | DIV { $$ = Operator.OpType.Division; }
1308 | PERCENT { $$ = Operator.OpType.Modulus; }
1309 | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
1310 | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
1311 | CARRET { $$ = Operator.OpType.ExclusiveOr; }
1312 | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
1313 | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
1314 | OP_EQ { $$ = Operator.OpType.Equality; }
1315 | OP_NE { $$ = Operator.OpType.Inequality; }
1316 | OP_GT { $$ = Operator.OpType.GreaterThan; }
1317 | OP_LT { $$ = Operator.OpType.LessThan; }
1318 | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
1319 | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
1322 conversion_operator_declarator
1323 : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1325 Parameter [] pars = new Parameter [1];
1327 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1329 current_local_parameters = new Parameters (pars, null, lexer.Location);
1331 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
1332 null, null, lexer.Location);
1334 | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1336 Parameter [] pars = new Parameter [1];
1338 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1340 current_local_parameters = new Parameters (pars, null, lexer.Location);
1342 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
1343 null, null, lexer.Location);
1347 syntax_error (lexer.Location, "'operator' expected");
1351 syntax_error (lexer.Location, "'operator' expected");
1355 constructor_declaration
1358 constructor_declarator
1361 Constructor c = (Constructor) $3;
1362 c.Block = (Block) $4;
1363 c.ModFlags = (int) $2;
1364 c.OptAttributes = (Attributes) $1;
1366 if ((c.ModFlags & Modifiers.STATIC) != 0){
1367 if ((c.ModFlags & Modifiers.Accessibility) != 0) {
1368 Location l = lexer.Location;
1369 Report.Error (515, l, "Access modifiers are not allowed on static constructors");
1372 if (c.Initializer != null){
1373 Location l = lexer.Location;
1374 Report.Error (514, l, "Static constructors can not have an explicit this or base constructor invocations");
1377 if (!c.Parameters.Empty){
1378 Location l = lexer.Location;
1379 Report.Error (132, l, "Static constructors should not have parameters");
1383 CheckDef (current_container.AddConstructor (c), c.Name);
1385 current_local_parameters = null;
1389 constructor_declarator
1391 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1393 oob_stack.Push (lexer.Location);
1395 current_local_parameters = (Parameters) $3;
1397 opt_constructor_initializer
1399 Location l = (Location) oob_stack.Pop ();
1400 $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $6, l);
1404 opt_constructor_initializer
1405 : /* empty */ { $$ = null; }
1406 | constructor_initializer
1409 constructor_initializer
1410 : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
1412 $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
1414 | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
1416 $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
1420 destructor_declaration
1421 : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
1423 if ((string) $3 != current_container.Basename){
1424 Report.Error (574, lexer.Location, "Name of destructor must match name of class");
1425 } else if (!(current_container is Class)){
1426 Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
1428 Location l = lexer.Location;
1430 Method d = new Method (
1431 "System.Void", 0, "Finalize",
1432 new Parameters (null, null, l), (Attributes) $1, l);
1434 d.Block = (Block) $6;
1435 CheckDef (current_container.AddMethod (d), d.Name);
1443 EVENT type variable_declarators SEMICOLON
1445 foreach (VariableDeclaration var in (ArrayList) $5) {
1447 Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
1448 (int) $2, null, null, (Attributes) $1, lexer.Location);
1450 CheckDef (current_container.AddEvent (e), e.Name);
1456 EVENT type member_name
1459 implicit_value_parameter_type = (string) $4;
1460 lexer.EventParsing = true;
1462 event_accessor_declarations
1464 lexer.EventParsing = false;
1468 Pair pair = (Pair) $8;
1469 Block add_block = null;
1470 Block rem_block = null;
1472 if (pair.First != null)
1473 add_block = (Block) pair.First;
1474 if (pair.Second != null)
1475 rem_block = (Block) pair.Second;
1477 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block,
1478 (Attributes) $1, lexer.Location);
1480 CheckDef (current_container.AddEvent (e), e.Name);
1481 implicit_value_parameter_type = null;
1485 event_accessor_declarations
1486 : add_accessor_declaration remove_accessor_declaration
1488 $$ = new Pair ($1, $2);
1490 | remove_accessor_declaration add_accessor_declaration
1492 $$ = new Pair ($2, $1);
1496 add_accessor_declaration
1497 : opt_attributes ADD
1499 Parameter [] args = new Parameter [1];
1500 Parameter implicit_value_parameter = new Parameter (
1501 implicit_value_parameter_type, "value",
1502 Parameter.Modifier.NONE, null);
1504 args [0] = implicit_value_parameter;
1506 current_local_parameters = new Parameters (args, null, lexer.Location);
1507 lexer.EventParsing = false;
1512 lexer.EventParsing = true;
1516 remove_accessor_declaration
1517 : opt_attributes REMOVE
1519 Parameter [] args = new Parameter [1];
1520 Parameter implicit_value_parameter = new Parameter (
1521 implicit_value_parameter_type, "value",
1522 Parameter.Modifier.NONE, null);
1524 args [0] = implicit_value_parameter;
1526 current_local_parameters = new Parameters (args, null, lexer.Location);
1527 lexer.EventParsing = false;
1532 lexer.EventParsing = true;
1537 : opt_attributes opt_modifiers indexer_declarator
1540 IndexerDeclaration decl = (IndexerDeclaration) $3;
1542 implicit_value_parameter_type = decl.type;
1544 lexer.PropertyParsing = true;
1545 parsing_indexer = true;
1547 indexer_parameters = decl.param_list;
1548 $$ = lexer.Location;
1550 accessor_declarations
1552 lexer.PropertyParsing = false;
1553 parsing_indexer = false;
1557 // The signature is computed from the signature of the indexer. Look
1558 // at section 3.6 on the spec
1561 IndexerDeclaration decl = (IndexerDeclaration) $3;
1562 Pair pair = (Pair) $6;
1563 Block get_block = null;
1564 Block set_block = null;
1566 if (pair.First != null)
1567 get_block = (Block) pair.First;
1568 if (pair.Second != null)
1569 set_block = (Block) pair.Second;
1571 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
1572 get_block, set_block, (Attributes) $1, (Location) $5);
1574 // Note that there is no equivalent of CheckDef for this case
1575 // We shall handle this in semantic analysis
1577 current_container.AddIndexer (indexer);
1579 current_local_parameters = null;
1580 implicit_value_parameter_type = null;
1581 indexer_parameters = null;
1586 : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1588 Parameters pars = (Parameters) $4;
1590 if (pars.FixedParameters == null){
1591 Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1594 $$ = new IndexerDeclaration ((string) $1, null, pars);
1596 | type qualified_identifier DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1598 Parameters pars = (Parameters) $6;
1600 if (pars.FixedParameters == null){
1601 Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1603 $$ = new IndexerDeclaration ((string) $1, (string) $2, pars);
1615 string full_name = MakeName ((string) $4);
1616 Enum e = new Enum (current_container, (string) $5, (int) $2, full_name, (Attributes) $1, lexer.Location);
1618 foreach (VariableDeclaration ev in (ArrayList) $6){
1619 CheckDef (e.AddEnumMember (ev.identifier,
1620 (Expression) ev.expression_or_array_initializer,
1621 (Location) ev.Location),
1625 e.Namespace = current_namespace;
1627 CheckDef (current_container.AddEnum (e), full_name);
1628 RootContext.Tree.RecordEnum (full_name, e);
1634 : /* empty */ { $$ = "System.Int32"; }
1635 | COLON type { $$ = $2; }
1639 : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
1645 opt_enum_member_declarations
1646 : /* empty */ { $$ = new ArrayList (); }
1647 | enum_member_declarations opt_comma { $$ = $1; }
1650 enum_member_declarations
1651 : enum_member_declaration
1653 ArrayList l = new ArrayList ();
1658 | enum_member_declarations COMMA enum_member_declaration
1660 ArrayList l = (ArrayList) $1;
1668 enum_member_declaration
1669 : opt_attributes IDENTIFIER
1671 $$ = new VariableDeclaration ((string) $2, null, lexer.Location);
1673 | opt_attributes IDENTIFIER
1675 $$ = lexer.Location;
1679 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location);
1683 delegate_declaration
1687 IDENTIFIER OPEN_PARENS
1688 opt_formal_parameter_list
1692 Delegate del = new Delegate ((string) $4, (int) $2,
1693 MakeName ((string) $5), (Parameters) $7,
1694 (Attributes) $1, lexer.Location);
1696 CheckDef (current_container.AddDelegate (del), del.Name);
1701 IDENTIFIER OPEN_PARENS
1702 opt_formal_parameter_list
1706 Delegate del = new Delegate ("System.Void", (int) $2, (string) $5, (Parameters) $7,
1707 (Attributes) $1, lexer.Location);
1709 CheckDef (current_container.AddDelegate (del), del.Name);
1714 : namespace_or_type_name
1717 namespace_or_type_name
1718 : qualified_identifier
1722 * Before you think of adding a return_type, notice that we have been
1723 * using two rules in the places where it matters (one rule using type
1724 * and another identical one that uses VOID as the return type). This
1725 * gets rid of a shift/reduce couple
1728 : type_name { /* class_type */
1730 This does interfaces, delegates, struct_types, class_types,
1731 parent classes, and more! 4.2
1745 // Note that here only unmanaged types are allowed but we
1746 // can't perform checks during this phase - we do it during
1747 // semantic analysis.
1749 $$ = (string) $1 + "*";
1753 $$ = "System.Void*";
1760 $$ = new SimpleName ((string) $1, lexer.Location);
1762 | non_expression_type rank_specifier
1764 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1766 | non_expression_type STAR
1768 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1770 | expression rank_specifiers
1772 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1776 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1783 ArrayList types = new ArrayList ();
1788 | type_list COMMA type
1790 ArrayList types = (ArrayList) $1;
1798 * replaces all the productions for isolating the various
1799 * simple types, but we need this to reuse it easily in local_variable_type
1802 : OBJECT { $$ = "System.Object"; }
1803 | STRING { $$ = "System.String"; }
1804 | BOOL { $$ = "System.Boolean"; }
1805 | DECIMAL { $$ = "System.Decimal"; }
1806 | FLOAT { $$ = "System.Single"; }
1807 | DOUBLE { $$ = "System.Double"; }
1812 : SBYTE { $$ = "System.SByte"; }
1813 | BYTE { $$ = "System.Byte"; }
1814 | SHORT { $$ = "System.Int16"; }
1815 | USHORT { $$ = "System.UInt16"; }
1816 | INT { $$ = "System.Int32"; }
1817 | UINT { $$ = "System.UInt32"; }
1818 | LONG { $$ = "System.Int64"; }
1819 | ULONG { $$ = "System.UInt64"; }
1820 | CHAR { $$ = "System.Char"; }
1821 | VOID { $$ = "System.Void"; }
1829 : type rank_specifiers
1831 $$ = (string) $1 + (string) $2;
1836 // Expressions, section 7.5
1844 | qualified_identifier
1846 string name = (string) $1;
1849 $$ = DecomposeQI (name, lexer.Location);
1851 | parenthesized_expression
1853 | invocation_expression
1857 | post_increment_expression
1858 | post_decrement_expression
1862 | checked_expression
1863 | unchecked_expression
1864 | pointer_member_access
1865 // TODO: pointer_element_access
1866 // TODO: sizeof-expression
1873 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
1874 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
1875 | NULL { $$ = NullLiteral.Null; }
1879 : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }
1880 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
1881 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1886 object v = lexer.Value;
1889 // FIXME: Possible optimization would be to
1890 // compute the *Literal objects directly in the scanner
1893 $$ = new IntLiteral ((Int32) v);
1895 $$ = new UIntLiteral ((UInt32) v);
1897 $$ = new LongLiteral ((Int64) v);
1898 else if (v is ulong)
1899 $$ = new ULongLiteral ((UInt64) v);
1901 Console.WriteLine ("OOPS. Unexpected result from scanner");
1906 : TRUE { $$ = new BoolLiteral (true); }
1907 | FALSE { $$ = new BoolLiteral (false); }
1910 parenthesized_expression
1911 : OPEN_PARENS expression CLOSE_PARENS
1916 : primary_expression DOT IDENTIFIER
1918 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1920 | predefined_type DOT IDENTIFIER
1922 $$ = new MemberAccess (new SimpleName ((string) $1, lexer.Location), (string) $3, lexer.Location);
1930 invocation_expression
1931 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
1934 Location l = lexer.Location;
1935 Report.Error (1, l, "THIS IS CRAZY");
1937 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
1942 : /* empty */ { $$ = null; }
1949 ArrayList list = new ArrayList ();
1953 | argument_list COMMA argument
1955 ArrayList list = (ArrayList) $1;
1964 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
1966 | REF variable_reference
1968 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
1970 | OUT variable_reference
1972 $$ = new Argument ((Expression) $2, Argument.AType.Out);
1977 : expression { note ("section 5.4"); $$ = $1; }
1981 : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
1983 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
1985 | primary_expression rank_specifiers
1987 // So the super-trick is that primary_expression
1988 // can only be either a SimpleName or a MemberAccess.
1989 // The MemberAccess case arises when you have a fully qualified type-name like :
1991 // SimpleName is when you have
1994 Expression expr = (Expression) $1;
1995 if (!(expr is SimpleName || expr is MemberAccess)) {
1996 Location l = lexer.Location;
1997 Report.Error (-1, l, "Invalid Type definition");
1998 $$ = "System.Object";
2002 // So we extract the string corresponding to the SimpleName
2005 $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
2012 ArrayList list = new ArrayList ();
2016 | expression_list COMMA expression
2018 ArrayList list = (ArrayList) $1;
2027 $$ = new This (lexer.Location);
2032 : BASE DOT IDENTIFIER
2034 $$ = new BaseAccess ((string) $3, lexer.Location);
2036 | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
2038 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
2042 post_increment_expression
2043 : primary_expression OP_INC
2045 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
2046 (Expression) $1, lexer.Location);
2050 post_decrement_expression
2051 : primary_expression OP_DEC
2053 $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
2054 (Expression) $1, lexer.Location);
2059 : object_or_delegate_creation_expression
2060 | array_creation_expression
2063 object_or_delegate_creation_expression
2064 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2066 $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
2070 array_creation_expression
2071 : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
2073 opt_array_initializer
2075 $$ = new ArrayCreation ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7,
2078 | NEW type rank_specifiers array_initializer
2080 $$ = new ArrayCreation ((string) $2, (string) $3, (ArrayList) $4, lexer.Location);
2084 Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
2104 | rank_specifiers rank_specifier
2106 $$ = (string) $2 + (string) $1;
2111 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2113 $$ = "[" + (string) $2 + "]";
2133 | dim_separators COMMA
2135 $$ = (string) $1 + ",";
2139 opt_array_initializer
2151 : OPEN_BRACE CLOSE_BRACE
2153 ArrayList list = new ArrayList ();
2156 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
2158 $$ = (ArrayList) $2;
2162 variable_initializer_list
2163 : variable_initializer
2165 ArrayList list = new ArrayList ();
2169 | variable_initializer_list COMMA variable_initializer
2171 ArrayList list = (ArrayList) $1;
2178 : TYPEOF OPEN_PARENS type CLOSE_PARENS
2180 $$ = new TypeOf ((string) $3, lexer.Location);
2185 : SIZEOF OPEN_PARENS type CLOSE_PARENS {
2186 $$ = new SizeOf ((string) $3, lexer.Location);
2188 note ("Verify type is unmanaged");
2189 note ("if (5.8) builtin, yield constant expression");
2194 : CHECKED OPEN_PARENS expression CLOSE_PARENS
2196 $$ = new CheckedExpr ((Expression) $3);
2200 unchecked_expression
2201 : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
2203 $$ = new UnCheckedExpr ((Expression) $3);
2207 pointer_member_access
2208 : primary_expression OP_PTR IDENTIFIER
2212 deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lexer.Location);
2213 $$ = new MemberAccess (deref, (string) $3, lexer.Location);
2217 : primary_expression
2218 | BANG prefixed_unary_expression
2220 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2222 | TILDE prefixed_unary_expression
2224 $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
2226 | OPEN_PARENS expression CLOSE_PARENS unary_expression
2228 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2230 | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
2232 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2237 // The idea to split this out is from Rhys' grammar
2238 // to solve the problem with casts.
2240 prefixed_unary_expression
2242 | PLUS prefixed_unary_expression
2244 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2246 | MINUS prefixed_unary_expression
2248 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2250 | OP_INC prefixed_unary_expression
2252 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2253 (Expression) $2, lexer.Location);
2255 | OP_DEC prefixed_unary_expression
2257 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2258 (Expression) $2, lexer.Location);
2260 | STAR prefixed_unary_expression
2262 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
2264 | BITWISE_AND prefixed_unary_expression
2266 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
2270 pre_increment_expression
2271 : OP_INC prefixed_unary_expression
2273 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2274 (Expression) $2, lexer.Location);
2278 pre_decrement_expression
2279 : OP_DEC prefixed_unary_expression
2281 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2282 (Expression) $2, lexer.Location);
2286 multiplicative_expression
2287 : prefixed_unary_expression
2288 | multiplicative_expression STAR prefixed_unary_expression
2290 $$ = new Binary (Binary.Operator.Multiply,
2291 (Expression) $1, (Expression) $3, lexer.Location);
2293 | multiplicative_expression DIV prefixed_unary_expression
2295 $$ = new Binary (Binary.Operator.Division,
2296 (Expression) $1, (Expression) $3, lexer.Location);
2298 | multiplicative_expression PERCENT prefixed_unary_expression
2300 $$ = new Binary (Binary.Operator.Modulus,
2301 (Expression) $1, (Expression) $3, lexer.Location);
2306 : multiplicative_expression
2307 | additive_expression PLUS multiplicative_expression
2309 $$ = new Binary (Binary.Operator.Addition,
2310 (Expression) $1, (Expression) $3, lexer.Location);
2312 | additive_expression MINUS multiplicative_expression
2314 $$ = new Binary (Binary.Operator.Subtraction,
2315 (Expression) $1, (Expression) $3, lexer.Location);
2320 : additive_expression
2321 | shift_expression OP_SHIFT_LEFT additive_expression
2323 $$ = new Binary (Binary.Operator.LeftShift,
2324 (Expression) $1, (Expression) $3, lexer.Location);
2326 | shift_expression OP_SHIFT_RIGHT additive_expression
2328 $$ = new Binary (Binary.Operator.RightShift,
2329 (Expression) $1, (Expression) $3, lexer.Location);
2333 relational_expression
2335 | relational_expression OP_LT shift_expression
2337 $$ = new Binary (Binary.Operator.LessThan,
2338 (Expression) $1, (Expression) $3, lexer.Location);
2340 | relational_expression OP_GT shift_expression
2342 $$ = new Binary (Binary.Operator.GreaterThan,
2343 (Expression) $1, (Expression) $3, lexer.Location);
2345 | relational_expression OP_LE shift_expression
2347 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2348 (Expression) $1, (Expression) $3, lexer.Location);
2350 | relational_expression OP_GE shift_expression
2352 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2353 (Expression) $1, (Expression) $3, lexer.Location);
2355 | relational_expression IS type
2357 $$ = new Is ((Expression) $1, (string) $3, lexer.Location);
2359 | relational_expression AS type
2361 $$ = new As ((Expression) $1, (string) $3, lexer.Location);
2366 : relational_expression
2367 | equality_expression OP_EQ relational_expression
2369 $$ = new Binary (Binary.Operator.Equality,
2370 (Expression) $1, (Expression) $3, lexer.Location);
2372 | equality_expression OP_NE relational_expression
2374 $$ = new Binary (Binary.Operator.Inequality,
2375 (Expression) $1, (Expression) $3, lexer.Location);
2380 : equality_expression
2381 | and_expression BITWISE_AND equality_expression
2383 $$ = new Binary (Binary.Operator.BitwiseAnd,
2384 (Expression) $1, (Expression) $3, lexer.Location);
2388 exclusive_or_expression
2390 | exclusive_or_expression CARRET and_expression
2392 $$ = new Binary (Binary.Operator.ExclusiveOr,
2393 (Expression) $1, (Expression) $3, lexer.Location);
2397 inclusive_or_expression
2398 : exclusive_or_expression
2399 | inclusive_or_expression BITWISE_OR exclusive_or_expression
2401 $$ = new Binary (Binary.Operator.BitwiseOr,
2402 (Expression) $1, (Expression) $3, lexer.Location);
2406 conditional_and_expression
2407 : inclusive_or_expression
2408 | conditional_and_expression OP_AND inclusive_or_expression
2410 $$ = new Binary (Binary.Operator.LogicalAnd,
2411 (Expression) $1, (Expression) $3, lexer.Location);
2415 conditional_or_expression
2416 : conditional_and_expression
2417 | conditional_or_expression OP_OR conditional_and_expression
2419 $$ = new Binary (Binary.Operator.LogicalOr,
2420 (Expression) $1, (Expression) $3, lexer.Location);
2424 conditional_expression
2425 : conditional_or_expression
2426 | conditional_or_expression INTERR expression COLON expression
2428 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2432 assignment_expression
2433 : prefixed_unary_expression ASSIGN expression
2435 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2437 | prefixed_unary_expression OP_MULT_ASSIGN expression
2439 Location l = lexer.Location;
2441 $$ = new Assign ((Expression) $1,
2442 new Binary (Binary.Operator.Multiply,
2444 (Expression) $3, l), l);
2446 | prefixed_unary_expression OP_DIV_ASSIGN expression
2448 Location l = lexer.Location;
2450 $$ = new Assign ((Expression) $1,
2451 new Binary (Binary.Operator.Division,
2453 (Expression) $3, l), l);
2455 | prefixed_unary_expression OP_MOD_ASSIGN expression
2457 Location l = lexer.Location;
2459 $$ = new Assign ((Expression) $1,
2460 new Binary (Binary.Operator.Modulus,
2462 (Expression) $3, l), l);
2464 | prefixed_unary_expression OP_ADD_ASSIGN expression
2466 Location l = lexer.Location;
2468 $$ = new Assign ((Expression) $1,
2469 new Binary (Binary.Operator.Addition,
2471 (Expression) $3, l), l);
2473 | prefixed_unary_expression OP_SUB_ASSIGN expression
2475 Location l = lexer.Location;
2477 $$ = new Assign ((Expression) $1,
2478 new Binary (Binary.Operator.Subtraction,
2480 (Expression) $3, l), l);
2482 | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
2484 Location l = lexer.Location;
2486 $$ = new Assign ((Expression) $1,
2487 new Binary (Binary.Operator.LeftShift,
2489 (Expression) $3, l), l);
2491 | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2493 Location l = lexer.Location;
2495 $$ = new Assign ((Expression) $1,
2496 new Binary (Binary.Operator.RightShift,
2498 (Expression) $3, l), l);
2500 | prefixed_unary_expression OP_AND_ASSIGN expression
2502 Location l = lexer.Location;
2504 $$ = new Assign ((Expression) $1,
2505 new Binary (Binary.Operator.BitwiseAnd,
2507 (Expression) $3, l), l);
2509 | prefixed_unary_expression OP_OR_ASSIGN expression
2511 Location l = lexer.Location;
2513 $$ = new Assign ((Expression) $1,
2514 new Binary (Binary.Operator.BitwiseOr,
2516 (Expression) $3, l), l);
2518 | prefixed_unary_expression OP_XOR_ASSIGN expression
2520 Location l = lexer.Location;
2522 $$ = new Assign ((Expression) $1,
2523 new Binary (Binary.Operator.ExclusiveOr,
2525 (Expression) $3, l), l);
2530 : conditional_expression
2531 | assignment_expression
2553 name = MakeName ((string) $4);
2555 new_class = new Class (current_container, name, (int) $2,
2556 (Attributes) $1, lexer.Location);
2557 current_container = new_class;
2558 current_container.Namespace = current_namespace;
2559 RootContext.Tree.RecordClass (name, new_class);
2565 Class new_class = (Class) current_container;
2568 new_class.Bases = (ArrayList) $6;
2570 current_container = current_container.Parent;
2571 CheckDef (current_container.AddClass (new_class), new_class.Name);
2578 : /* empty */ { $$ = (int) 0; }
2584 | modifiers modifier
2589 if ((m1 & m2) != 0) {
2590 Location l = lexer.Location;
2591 Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2593 $$ = (int) (m1 | m2);
2598 : NEW { $$ = Modifiers.NEW; }
2599 | PUBLIC { $$ = Modifiers.PUBLIC; }
2600 | PROTECTED { $$ = Modifiers.PROTECTED; }
2601 | INTERNAL { $$ = Modifiers.INTERNAL; }
2602 | PRIVATE { $$ = Modifiers.PRIVATE; }
2603 | ABSTRACT { $$ = Modifiers.ABSTRACT; }
2604 | SEALED { $$ = Modifiers.SEALED; }
2605 | STATIC { $$ = Modifiers.STATIC; }
2606 | READONLY { $$ = Modifiers.READONLY; }
2607 | VIRTUAL { $$ = Modifiers.VIRTUAL; }
2608 | OVERRIDE { $$ = Modifiers.OVERRIDE; }
2609 | EXTERN { $$ = Modifiers.EXTERN; }
2610 | VOLATILE { $$ = Modifiers.VOLATILE; }
2611 | UNSAFE { $$ = Modifiers.UNSAFE; }
2615 : /* empty */ { $$ = null; }
2616 | class_base { $$ = $1; }
2620 : COLON type_list { $$ = $2; }
2628 // A block is "contained" on the following places:
2630 // property_declaration as part of the accessor body (get/set)
2631 // operator_declaration
2632 // constructor_declaration
2633 // destructor_declaration
2634 // event_declaration as part of add_accessor_declaration or remove_accessor_declaration
2639 current_block = new Block (current_block);
2641 opt_statement_list CLOSE_BRACE
2643 while (current_block.Implicit)
2644 current_block = current_block.Parent;
2646 current_block = current_block.Parent;
2657 | statement_list statement
2661 : declaration_statement
2663 if ((Block) $1 != current_block){
2664 current_block.AddStatement ((Statement) $1);
2665 current_block = (Block) $1;
2668 | embedded_statement
2670 Statement s = (Statement) $1;
2673 current_block.AddStatement ((Statement) $1);
2681 | expression_statement
2682 | selection_statement
2683 | iteration_statement
2687 | unchecked_statement
2697 $$ = new EmptyStatement ();
2704 LabeledStatement labeled = new LabeledStatement ((string) $1);
2706 if (!current_block.AddLabel ((string) $1, labeled)){
2707 Location l = lexer.Location;
2708 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2710 current_block.AddStatement (labeled);
2715 declaration_statement
2716 : local_variable_declaration SEMICOLON
2718 DictionaryEntry de = (DictionaryEntry) $1;
2720 $$ = declare_local_variables ((string) de.Key, (ArrayList) de.Value, lexer.Location);
2723 | local_constant_declaration SEMICOLON
2725 DictionaryEntry de = (DictionaryEntry) $1;
2727 $$ = declare_local_constant ((string) de.Key, (VariableDeclaration) de.Value);
2732 * The following is from Rhys' grammar:
2733 * > Types in local variable declarations must be recognized as
2734 * > expressions to prevent reduce/reduce errors in the grammar.
2735 * > The expressions are converted into types during semantic analysis.
2738 : primary_expression opt_rank_specifier
2740 // FIXME: Do something smart here regarding the composition of the type.
2742 // Ok, the above "primary_expression" is there to get rid of
2743 // both reduce/reduce and shift/reduces in the grammar, it should
2744 // really just be "type_name". If you use type_name, a reduce/reduce
2745 // creeps up. If you use qualified_identifier (which is all we need
2746 // really) two shift/reduces appear.
2749 // So the super-trick is that primary_expression
2750 // can only be either a SimpleName or a MemberAccess.
2751 // The MemberAccess case arises when you have a fully qualified type-name like :
2753 // SimpleName is when you have
2756 Expression expr = (Expression) $1;
2757 if (!(expr is SimpleName || expr is MemberAccess)) {
2758 Location l = lexer.Location;
2759 Report.Error (-1, l, "Invalid Type definition");
2760 $$ = "System.Object";
2764 // So we extract the string corresponding to the SimpleName
2767 $$ = GetQualifiedIdentifier (expr) + (string) $2;
2769 | builtin_types opt_rank_specifier
2771 $$ = (string) $1 + (string) $2;
2775 local_variable_pointer_type
2776 : primary_expression STAR
2778 Expression expr = (Expression) $1;
2779 if (!(expr is SimpleName || expr is MemberAccess)) {
2780 Location l = lexer.Location;
2781 Report.Error (-1, l, "Invalid Type definition");
2782 $$ = "System.Object";
2785 $$ = GetQualifiedIdentifier (expr) + "*";
2787 | builtin_types STAR
2789 $$ = (string) $1 + "*";
2793 $$ = "System.Void*";
2795 | local_variable_pointer_type STAR
2797 $$ = (string) $1 + "*";
2801 local_variable_declaration
2802 : local_variable_type variable_declarators
2804 $$ = new DictionaryEntry ($1, $2);
2806 | local_variable_pointer_type opt_rank_specifier variable_declarators
2808 $$ = new DictionaryEntry ((string) $1 + (string) $2, $3);
2812 local_constant_declaration
2813 : CONST local_variable_type constant_declarator
2815 $$ = new DictionaryEntry ($2, $3);
2819 expression_statement
2820 : statement_expression SEMICOLON
2827 // We have to do the wrapping here and not in the case above,
2828 // because statement_expression is used for example in for_statement
2830 statement_expression
2831 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
2832 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
2833 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
2834 | post_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
2835 | post_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
2836 | pre_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
2837 | pre_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
2839 Report.Error (1002, lexer.Location, "Expecting `;'");
2843 object_creation_expression
2844 : object_or_delegate_creation_expression
2845 { note ("complain if this is a delegate maybe?"); }
2854 : if_statement_open if_statement_rest
2863 oob_stack.Push (lexer.Location);
2868 : boolean_expression CLOSE_PARENS
2871 Location l = (Location) oob_stack.Pop ();
2873 $$ = new If ((Expression) $1, (Statement) $3, l);
2875 if (RootContext.WarningLevel >= 3){
2876 if ($3 is EmptyStatement)
2877 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
2881 | boolean_expression CLOSE_PARENS
2882 embedded_statement ELSE embedded_statement
2884 Location l = (Location) oob_stack.Pop ();
2886 $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l);
2891 : SWITCH OPEN_PARENS
2893 oob_stack.Push (lexer.Location);
2895 expression CLOSE_PARENS
2898 $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
2914 Report.Error (1522, lexer.Location, "Empty switch block");
2922 ArrayList sections = new ArrayList ();
2927 | switch_sections switch_section
2929 ArrayList sections = (ArrayList) $1;
2939 current_block = new Block (current_block);
2943 while (current_block.Implicit)
2944 current_block = current_block.Parent;
2945 $$ = new SwitchSection ((ArrayList) $1, current_block);
2946 current_block = current_block.Parent;
2953 ArrayList labels = new ArrayList ();
2958 | switch_labels switch_label
2960 ArrayList labels = (ArrayList) ($1);
2968 : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
2969 | DEFAULT COLON { $$ = new SwitchLabel (null, lexer.Location); }
2972 1523, lexer.Location,
2973 "The keyword case or default must precede code in switch block");
2987 oob_stack.Push (lexer.Location);
2989 boolean_expression CLOSE_PARENS embedded_statement
2991 Location l = (Location) oob_stack.Pop ();
2992 $$ = new While ((Expression) $4, (Statement) $6, l);
2994 if (RootContext.WarningLevel >= 3){
2995 if ($6 is EmptyStatement)
2996 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3002 : DO embedded_statement
3003 WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
3005 $$ = new Do ((Statement) $2, (Expression) $5, lexer.Location);
3011 opt_for_initializer SEMICOLON
3013 Block assign_block = new Block (current_block);
3014 current_block = assign_block;
3016 if ($3 is DictionaryEntry){
3017 DictionaryEntry de = (DictionaryEntry) $3;
3019 string type = (string) de.Key;
3020 ArrayList var_declarators = (ArrayList) de.Value;
3022 foreach (VariableDeclaration decl in var_declarators){
3026 vi = current_block.AddVariable (
3027 type, decl.identifier, current_local_parameters, decl.Location);
3029 Report.Error (128, decl.Location,
3030 "A local variable `" + decl.identifier +
3031 "' is already defined in this scope");
3033 Location l = lexer.Location;
3035 if (decl.expression_or_array_initializer is Expression){
3036 expr = (Expression) decl.expression_or_array_initializer;
3040 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3042 string base_type = type.Substring (0, type.IndexOf ("["));
3043 string rank = type.Substring (type.IndexOf ("["));
3045 expr = new ArrayCreation (base_type, rank, init, decl.Location);
3048 LocalVariableReference var;
3049 var = new LocalVariableReference (
3050 assign_block, decl.identifier, l);
3052 Assign a = new Assign (var, expr, decl.Location);
3054 assign_block.AddStatement (new StatementExpression (a));
3060 oob_stack.Push (lexer.Location);
3062 opt_for_condition SEMICOLON
3063 opt_for_iterator CLOSE_PARENS
3066 Location l = (Location) oob_stack.Pop ();
3068 For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
3070 if (RootContext.WarningLevel >= 3){
3071 if ($10 is EmptyStatement)
3072 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3075 current_block.AddStatement (f);
3076 while (current_block.Implicit)
3077 current_block = current_block.Parent;
3079 current_block = current_block.Parent;
3084 : /* empty */ { $$ = new EmptyStatement (); }
3089 : local_variable_declaration
3090 | statement_expression_list
3094 : /* empty */ { $$ = null; }
3095 | boolean_expression
3099 : /* empty */ { $$ = new EmptyStatement (); }
3104 : statement_expression_list
3107 statement_expression_list
3108 : statement_expression
3110 // CHANGE: was `null'
3111 Block b = new Block (current_block, true);
3113 b.AddStatement ((Statement) $1);
3116 | statement_expression_list COMMA statement_expression
3118 Block b = (Block) $1;
3120 b.AddStatement ((Statement) $3);
3126 : FOREACH OPEN_PARENS type IDENTIFIER IN
3128 oob_stack.Push (lexer.Location);
3130 expression CLOSE_PARENS
3132 oob_stack.Push (current_block);
3134 Block foreach_block = new Block (current_block, true);
3135 LocalVariableReference v;
3136 Location l = lexer.Location;
3139 vi = foreach_block.AddVariable ((string) $3, (string) $4, current_local_parameters, l);
3142 128, l, "A local variable `" + (string) $4 + "' is already "+
3143 "defined in this scope");
3146 v = new LocalVariableReference (foreach_block, (string) $4, l);
3147 current_block = foreach_block;
3150 oob_stack.Push (current_block);
3154 Block foreach_block = (Block) oob_stack.Pop ();
3155 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
3156 Block prev_block = (Block) oob_stack.Pop ();
3157 Location l = (Location) oob_stack.Pop ();
3159 current_block = prev_block;
3161 Foreach f = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
3162 foreach_block.AddStatement (f);
3170 | continue_statement
3179 $$ = new Break (lexer.Location);
3184 : CONTINUE SEMICOLON
3186 $$ = new Continue (lexer.Location);
3191 : GOTO IDENTIFIER SEMICOLON
3193 $$ = new Goto (current_block, (string) $2, lexer.Location);
3195 | GOTO CASE constant_expression SEMICOLON
3197 $$ = new GotoCase ((Expression) $3, lexer.Location);
3199 | GOTO DEFAULT SEMICOLON
3201 $$ = new GotoDefault (lexer.Location);
3206 : RETURN opt_expression SEMICOLON
3208 $$ = new Return ((Expression) $2, lexer.Location);
3213 : THROW opt_expression SEMICOLON
3215 $$ = new Throw ((Expression) $2, lexer.Location);
3225 : TRY block catch_clauses
3228 ArrayList s = new ArrayList ();
3230 foreach (Catch cc in (ArrayList) $3) {
3231 if (cc.Type == null)
3237 // Now s contains the list of specific catch clauses
3238 // and g contains the general one.
3240 $$ = new Try ((Block) $2, s, g, null);
3242 | TRY block opt_catch_clauses FINALLY block
3245 ArrayList s = new ArrayList ();
3246 ArrayList catch_list = (ArrayList) $3;
3248 if (catch_list != null){
3249 foreach (Catch cc in catch_list) {
3250 if (cc.Type == null)
3257 $$ = new Try ((Block) $2, s, g, (Block) $5);
3261 Report.Error (1524, lexer.Location, "Expected catch or finally");
3266 : /* empty */ { $$ = null; }
3273 ArrayList l = new ArrayList ();
3278 | catch_clauses catch_clause
3280 ArrayList l = (ArrayList) $1;
3288 : /* empty */ { $$ = null; }
3293 : CATCH opt_catch_args
3295 string type = null, id = null;
3298 DictionaryEntry cc = (DictionaryEntry) $2;
3299 type = (string) cc.Key;
3300 id = (string) cc.Value;
3303 ArrayList one = new ArrayList ();
3304 Location loc = lexer.Location;
3306 one.Add (new VariableDeclaration (id, null, loc));
3309 current_block = new Block (current_block);
3310 Block b = declare_local_variables (type, one, loc);
3317 string type = null, id = null;
3320 DictionaryEntry cc = (DictionaryEntry) $2;
3321 type = (string) cc.Key;
3322 id = (string) cc.Value;
3325 while (current_block != (Block) $1)
3326 current_block = current_block.Parent;
3331 $$ = new Catch (type, id , (Block) $4, lexer.Location);
3336 : /* empty */ { $$ = null; }
3341 : OPEN_PARENS type opt_identifier CLOSE_PARENS
3343 $$ = new DictionaryEntry ($2, $3);
3350 $$ = new Checked ((Block) $2);
3357 $$ = new Unchecked ((Block) $2);
3364 if (!RootContext.Unsafe){
3365 Report.Error (227, lexer.Location,
3366 "Unsafe code can only be used if --unsafe is used");
3369 $$ = new Unsafe ((Block) $3);
3375 pointer_type fixed_pointer_declarators
3378 Block assign_block = new Block (current_block, true);
3379 ArrayList list = (ArrayList) $4;
3380 string type = (string) $3;
3381 Location l = lexer.Location;
3382 int top = list.Count;
3384 for (int i = 0; i < top; i++){
3385 Pair p = (Pair) list [i];
3388 v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
3391 128, l, "A local variable `" + (string) p.First + "' is already "+
3392 "defined in this scope");
3398 current_block.AddStatement (assign_block);
3399 current_block = assign_block;
3400 oob_stack.Push (assign_block);
3405 Location l = (Location) oob_stack.Pop ();
3406 Block assign_block = (Block) oob_stack.Pop ();
3408 ArrayList list = (ArrayList) $4;
3409 int top = list.Count;
3411 $$ = new Fixed ((string) $3, (ArrayList) $4, (Statement) $7, l);
3415 fixed_pointer_declarators
3416 : fixed_pointer_declarator {
3417 ArrayList declarators = new ArrayList ();
3418 declarators.Add ($1);
3421 | fixed_pointer_declarators COMMA fixed_pointer_declarator
3423 ArrayList declarators = (ArrayList) $1;
3424 declarators.Add ($3);
3429 fixed_pointer_declarator
3430 : IDENTIFIER ASSIGN expression
3432 $$ = new Pair ($1, $3);
3437 : LOCK OPEN_PARENS expression CLOSE_PARENS
3443 $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
3448 : USING OPEN_PARENS resource_acquisition CLOSE_PARENS
3450 Block assign_block = new Block (current_block);
3451 current_block = assign_block;
3453 oob_stack.Push (lexer.Location);
3455 if ($3 is DictionaryEntry){
3456 DictionaryEntry de = (DictionaryEntry) $3;
3457 Location l = lexer.Location;
3459 string type = (string) de.Key;
3460 ArrayList var_declarators = (ArrayList) de.Value;
3462 foreach (VariableDeclaration decl in var_declarators){
3463 if (current_block.AddVariable (
3464 type, decl.identifier,
3465 current_local_parameters, decl.Location) == null){
3466 Report.Error (128, decl.Location,
3467 "A local variable `" + decl.identifier + "' is already" +
3468 "defined in this scope");
3472 ArrayList vars = new ArrayList ();
3474 foreach (VariableDeclaration decl in var_declarators){
3477 if (decl.expression_or_array_initializer is Expression){
3478 expr = (Expression) decl.expression_or_array_initializer;
3482 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3484 string base_type = type.Substring (0, type.IndexOf ("["));
3485 string rank = type.Substring (type.IndexOf ("["));
3487 expr = new ArrayCreation (base_type, rank, init, decl.Location);
3490 LocalVariableReference var;
3493 var = new LocalVariableReference (assign_block, decl.identifier, l);
3494 vi = var.VariableInfo;
3497 // This is so that it is not a warning on using variables
3500 vars.Add (new DictionaryEntry (var, expr));
3502 // Assign a = new Assign (var, expr, decl.Location);
3503 // assign_block.AddStatement (new StatementExpression (a));
3505 $3 = new DictionaryEntry (type, vars);
3510 Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
3511 current_block.AddStatement (u);
3512 while (current_block.Implicit)
3513 current_block = current_block.Parent;
3515 current_block = current_block.Parent;
3519 resource_acquisition
3520 : local_variable_declaration
3527 // A class used to pass around variable declarations and constants
3529 public class VariableDeclaration {
3530 public string identifier;
3531 public object expression_or_array_initializer;
3532 public Location Location;
3534 public VariableDeclaration (string id, object eoai, Location l){
3535 this.identifier = id;
3536 this.expression_or_array_initializer = eoai;
3542 // A class used to hold info about an indexer declarator
3545 public class IndexerDeclaration {
3547 public string interface_type;
3548 public Parameters param_list;
3550 public IndexerDeclaration (string type, string interface_type, Parameters param_list)
3553 this.interface_type = interface_type;
3554 this.param_list = param_list;
3559 // A class used to hold info about an operator declarator
3562 public class OperatorDeclaration {
3563 public Operator.OpType optype;
3564 public string ret_type;
3565 public string arg1type;
3566 public string arg1name;
3567 public string arg2type;
3568 public string arg2name;
3569 public Location location;
3571 public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
3572 string arg2type, string arg2name, Location location)
3575 this.ret_type = ret_type;
3576 this.arg1type = arg1type;
3577 this.arg1name = arg1name;
3578 this.arg2type = arg2type;
3579 this.arg2name = arg2name;
3580 this.location = location;
3586 // Given the @class_name name, it creates a fully qualified name
3587 // based on the containing declaration space
3590 MakeName (string class_name)
3592 string ns = current_namespace.Name;
3593 string container_name = current_container.Name;
3595 if (container_name == ""){
3597 return ns + "." + class_name;
3601 return container_name + "." + class_name;
3605 // Used to report back to the user the result of a declaration
3606 // in the current declaration space
3609 CheckDef (AdditionResult result, string name)
3611 if (result == AdditionResult.Success)
3614 Location l = lexer.Location;
3617 case AdditionResult.NameExists:
3618 Report.Error (102, l, "The namespace `" + current_container.Name +
3619 "' already contains a definition for `"+
3625 // This is handled only for static Constructors, because
3626 // in reality we handle these by the semantic analysis later
3628 case AdditionResult.MethodExists:
3630 111, l, "Class `"+current_container.Name+
3631 "' already defines a member called '" +
3632 name + "' with the same parameter types (more than one default constructor)");
3635 case AdditionResult.EnclosingClash:
3636 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
3639 case AdditionResult.NotAConstructor:
3640 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
3646 CheckDef (bool result, string name)
3650 CheckDef (AdditionResult.NameExists, name);
3654 // This routine should be removed soon. I am in the process of making
3655 // changes to never keep anything but SimpleNames during parsing, as
3656 // that breaks some kinds of code (documented in the ChangeLog).
3659 SimpleLookup (string name, Location loc)
3662 // we need to check against current_block not being null
3663 // as `expression' is allowed in argument_lists, which
3664 // do not exist inside a block.
3667 if (current_block != null){
3668 if (current_block.IsVariableDefined (name)){
3669 return new LocalVariableReference (current_block, name, loc);
3674 if (current_local_parameters != null){
3676 Parameter par = current_local_parameters.GetParameterByName (name, out idx);
3678 return new ParameterReference (current_local_parameters, idx, name);
3684 Expression DecomposeQI (string name, Location loc)
3688 if (name.IndexOf ('.') == -1){
3689 o = SimpleLookup (name, loc);
3691 return new SimpleName (name, loc);
3694 int pos = name.LastIndexOf (".");
3695 string left = name.Substring (0, pos);
3696 string right = name.Substring (pos + 1);
3698 o = DecomposeQI (left, loc);
3699 return new MemberAccess (o, right, loc);
3704 // This method is used to get at the complete string representation of
3705 // a fully-qualified type name, hiding inside a MemberAccess ;-)
3706 // This is necessary because local_variable_type admits primary_expression
3707 // as the type of the variable. So we do some extra checking
3709 string GetQualifiedIdentifier (Expression expr)
3711 if (expr is SimpleName)
3712 return ((SimpleName)expr).Name;
3713 else if (expr is MemberAccess)
3714 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3716 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
3720 Block declare_local_variables (string type, ArrayList variable_declarators, Location loc)
3722 Block implicit_block;
3723 ArrayList inits = null;
3726 // We use the `Used' property to check whether statements
3727 // have been added to the current block. If so, we need
3728 // to create another block to contain the new declaration
3729 // otherwise, as an optimization, we use the same block to
3730 // add the declaration.
3732 // FIXME: A further optimization is to check if the statements
3733 // that were added were added as part of the initialization
3734 // below. In which case, no other statements have been executed
3735 // and we might be able to reduce the number of blocks for
3736 // situations like this:
3738 // int j = 1; int k = j + 1;
3740 if (current_block.Used)
3741 implicit_block = new Block (current_block, true);
3743 implicit_block = current_block;
3745 foreach (VariableDeclaration decl in variable_declarators){
3747 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3748 if (decl.expression_or_array_initializer != null){
3750 inits = new ArrayList ();
3754 Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3755 "' is already defined in this scope");
3760 return implicit_block;
3762 foreach (VariableDeclaration decl in inits){
3766 if (decl.expression_or_array_initializer is Expression){
3767 expr = (Expression) decl.expression_or_array_initializer;
3770 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3772 string base_type = type.Substring (0, type.IndexOf ("["));
3773 string rank = type.Substring (type.IndexOf ("["));
3775 expr = new ArrayCreation (base_type, rank, init, decl.Location);
3779 LocalVariableReference var;
3780 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3782 assign = new Assign (var, expr, decl.Location);
3784 implicit_block.AddStatement (new StatementExpression (assign));
3787 return implicit_block;
3790 Block declare_local_constant (string type, VariableDeclaration decl)
3792 Block implicit_block;
3794 if (current_block.Used)
3795 implicit_block = new Block (current_block, true);
3797 implicit_block = current_block;
3799 if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3800 current_local_parameters, decl.Location))){
3801 Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3802 "' is already defined in this scope");
3805 return implicit_block;
3808 void CheckAttributeTarget (string a)
3812 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3816 Location l = lexer.Location;
3817 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3823 void CheckUnaryOperator (Operator.OpType op)
3827 case Operator.OpType.LogicalNot:
3828 case Operator.OpType.OnesComplement:
3829 case Operator.OpType.Increment:
3830 case Operator.OpType.Decrement:
3831 case Operator.OpType.True:
3832 case Operator.OpType.False:
3833 case Operator.OpType.Addition:
3834 case Operator.OpType.Subtraction:
3839 Location l = lexer.Location;
3840 Report.Error (1019, l, "Overloadable unary operator expected");
3846 void CheckBinaryOperator (Operator.OpType op)
3850 case Operator.OpType.Addition:
3851 case Operator.OpType.Subtraction:
3852 case Operator.OpType.Multiply:
3853 case Operator.OpType.Division:
3854 case Operator.OpType.Modulus:
3855 case Operator.OpType.BitwiseAnd:
3856 case Operator.OpType.BitwiseOr:
3857 case Operator.OpType.ExclusiveOr:
3858 case Operator.OpType.LeftShift:
3859 case Operator.OpType.RightShift:
3860 case Operator.OpType.Equality:
3861 case Operator.OpType.Inequality:
3862 case Operator.OpType.GreaterThan:
3863 case Operator.OpType.LessThan:
3864 case Operator.OpType.GreaterThanOrEqual:
3865 case Operator.OpType.LessThanOrEqual:
3869 Location l = lexer.Location;
3870 Report.Error (1020, l, "Overloadable binary operator expected");
3876 void syntax_error (Location l, string msg)
3878 Report.Error (1003, l, "Syntax error, " + msg);
3881 void output (string s)
3883 Console.WriteLine (s);
3886 void note (string s)
3888 // Used to put annotations
3893 public Tokenizer Lexer {
3899 public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
3901 current_namespace = new Namespace (null, "");
3904 current_container = RootContext.Tree.Types;
3905 current_container.Namespace = current_namespace;
3906 oob_stack = new Stack ();
3908 lexer = new Tokenizer (input, name, defines);
3911 public override int parse ()
3913 StringBuilder value = new StringBuilder ();
3917 if (yacc_verbose_flag)
3918 yyparse (lexer, new yydebug.yyDebugSimple ());
3921 } catch (Exception e){
3922 // Console.WriteLine ("Fatal error: " + name);
3923 // Console.WriteLine (lexer.location);
3926 // Please do not remove this, it is used during debugging
3929 Console.WriteLine (lexer.location + " : Parsing error ");
3930 Console.WriteLine (e);
3934 return global_errors;