3 // cs-parser.jay: The Parser for the C# compiler
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Ravi Pratap (ravi@ximian.com)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001 Ximian, Inc (http://www.ximian.com)
13 // (1) Figure out why error productions dont work. `type-declaration' is a
14 // great spot to put an `error' because you can reproduce it with this input:
17 // Possible optimization:
18 // Run memory profiler with parsing only, and consider dropping
19 // arraylists where not needed. Some pieces can use linked lists.
27 using System.Collections;
32 public class CSharpParser {
33 NamespaceEntry current_namespace;
34 TypeContainer current_container;
36 IIteratorContainer iterator_container;
39 // Current block is used to add statements as we find
46 // Current interface is used by the various declaration
47 // productions in the interface declaration to "add"
48 // the interfaces as we find them.
50 Interface current_interface;
53 // This is used by the unary_expression code to resolve
54 // a name against a parameter.
56 Parameters current_local_parameters;
59 // Using during property parsing to describe the implicit
60 // value parameter that is passed to the "set" and "get"accesor
61 // methods (properties and indexers).
63 Expression implicit_value_parameter_type;
64 Parameters indexer_parameters;
67 // Used to determine if we are parsing the get/set pair
68 // of an indexer or a property
73 // An out-of-band stack.
82 public bool yacc_verbose_flag;
84 // Name of the file we are parsing
94 %token NONE /* This token is never returned by our lexer */
95 %token ERROR // This is used not by the parser, but by the tokenizer.
99 *These are the C# keywords
187 /* C# keywords which are not really keywords */
193 /* C# single character operators/punctuation. */
194 %token OPEN_BRACE "{"
195 %token CLOSE_BRACE "}"
196 %token OPEN_BRACKET "["
197 %token CLOSE_BRACKET "]"
198 %token OPEN_PARENS "("
199 %token CLOSE_PARENS ")"
211 %token OP_GENERICS_LT "<"
213 %token OP_GENERICS_GT ">"
214 %token BITWISE_AND "&"
215 %token BITWISE_OR "|"
222 /* C# multi-character operators. */
225 %token OP_SHIFT_LEFT "<<"
226 %token OP_SHIFT_RIGHT ">>"
233 %token OP_MULT_ASSIGN "*="
234 %token OP_DIV_ASSIGN "/="
235 %token OP_MOD_ASSIGN "%="
236 %token OP_ADD_ASSIGN "+="
237 %token OP_SUB_ASSIGN "-="
238 %token OP_SHIFT_LEFT_ASSIGN "<<="
239 %token OP_SHIFT_RIGHT_ASSIGN ">>="
240 %token OP_AND_ASSIGN "&="
241 %token OP_XOR_ASSIGN "^="
242 %token OP_OR_ASSIGN "|="
246 %token LITERAL_INTEGER "int literal"
247 %token LITERAL_FLOAT "float literal"
248 %token LITERAL_DOUBLE "double literal"
249 %token LITERAL_DECIMAL "decimal literal"
250 %token LITERAL_CHARACTER "character literal"
251 %token LITERAL_STRING "string literal"
254 %token CLOSE_PARENS_CAST
255 %token CLOSE_PARENS_NO_CAST
256 %token CLOSE_PARENS_OPEN_PARENS
257 %token CLOSE_PARENS_MINUS
259 /* Add precedence rules to solve dangling else s/r conflict */
268 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
270 %left STAR DIV PERCENT
271 %right BANG CARRET UMINUS
272 %nonassoc OP_INC OP_DEC
274 %left OPEN_BRACKET OPEN_BRACE
278 %start compilation_unit
282 : outer_declarations opt_EOF
283 | outer_declarations attribute_sections opt_EOF
284 | attribute_sections opt_EOF
285 | opt_EOF /* allow empty files */
295 | outer_declarations outer_declaration
300 | namespace_member_declaration
305 | using_directives using_directive
309 : using_alias_directive
310 | using_namespace_directive
313 using_alias_directive
314 : USING IDENTIFIER ASSIGN
315 namespace_or_type_name SEMICOLON
317 current_namespace.UsingAlias ((string) $2, (Expression) $4, lexer.Location);
320 CheckIdentifierToken (yyToken);
324 using_namespace_directive
325 : USING namespace_name SEMICOLON
327 current_namespace.Using ((string) $2, lexer.Location);
332 // Strictly speaking, namespaces don't have attributes but
333 // we parse global attributes along with namespace declarations and then
336 namespace_declaration
337 : opt_attributes NAMESPACE qualified_identifier
339 Attributes attrs = (Attributes) $1;
342 foreach (AttributeSection asec in attrs.AttributeSections)
343 if (asec.Target == "assembly")
344 RootContext.AddGlobalAttributeSection (current_container, asec);
346 Report.Error(1518, Lexer.Location,
347 "Attributes cannot be applied to namespaces."
348 + " Expected class, delegate, enum, interface, or struct");
351 current_namespace = RootContext.Tree.RecordNamespace (current_namespace, file, (string) $3, lexer.Location);
353 namespace_body opt_semicolon
355 current_namespace = current_namespace.Parent;
371 | qualified_identifier DOT IDENTIFIER {
372 $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
377 : qualified_identifier
383 opt_namespace_member_declarations
394 opt_namespace_member_declarations
396 | namespace_member_declarations
399 namespace_member_declarations
400 : namespace_member_declaration
401 | namespace_member_declarations namespace_member_declaration
404 namespace_member_declaration
411 Class c = (Class) $1;
412 mod_flags = c.ModFlags;
414 } else if ($1 is Struct){
415 Struct s = (Struct) $1;
416 mod_flags = s.ModFlags;
421 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
423 1527, lexer.Location,
424 "Namespace elements cant be explicitly " +
425 "declared private or protected in `" + name + "'");
427 current_namespace.DeclarationFound = true;
429 | namespace_declaration {
430 current_namespace.DeclarationFound = true;
437 | interface_declaration
439 | delegate_declaration
441 // Enable this when we have handled all errors, because this acts as a generic fallback
444 // Console.WriteLine ("Token=" + yyToken);
445 // Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
455 | attribute_sections { $$ = $1; }
461 AttributeSection sect = (AttributeSection) $1;
463 if (sect.Target == "assembly")
464 RootContext.AddGlobalAttributeSection (current_container, sect);
467 $$ = new Attributes ((AttributeSection) $1);
469 | attribute_sections attribute_section
471 Attributes attrs = null;
472 AttributeSection sect = (AttributeSection) $2;
474 if (sect.Target == "assembly")
475 RootContext.AddGlobalAttributeSection (current_container, sect);
478 attrs = (Attributes) $1;
479 attrs.AddAttributeSection (sect);
487 : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
489 string target = null;
492 target = (string) $2;
494 $$ = new AttributeSection (target, (ArrayList) $3);
496 | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
498 $$ = new AttributeSection (null, (ArrayList) $2);
502 attribute_target_specifier
503 : attribute_target COLON
512 CheckAttributeTarget ((string) $1);
515 | EVENT { $$ = "event"; }
516 | RETURN { $$ = "return"; }
522 ArrayList attrs = new ArrayList (4);
528 | attribute_list COMMA attribute
530 ArrayList attrs = (ArrayList) $1;
542 opt_attribute_arguments
545 // Attributes need a string, not an expression: generic types will fail here.
547 $$ = new Attribute (((Expression) $1).ToString (), (ArrayList) $3, (Location) $2);
552 : type_name { /* reserved attribute name or identifier: 17.4 */ }
555 opt_attribute_arguments
556 : /* empty */ { $$ = null; }
557 | OPEN_PARENS attribute_arguments CLOSE_PARENS
565 : opt_positional_argument_list
570 ArrayList args = new ArrayList (4);
576 | positional_argument_list COMMA named_argument_list
578 ArrayList args = new ArrayList (4);
584 | named_argument_list
586 ArrayList args = new ArrayList (4);
595 opt_positional_argument_list
596 : /* empty */ { $$ = null; }
597 | positional_argument_list
600 positional_argument_list
603 ArrayList args = new ArrayList (4);
604 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
608 | positional_argument_list COMMA expression
610 ArrayList args = (ArrayList) $1;
611 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
620 ArrayList args = new ArrayList (4);
625 | named_argument_list COMMA named_argument
627 ArrayList args = (ArrayList) $1;
635 : IDENTIFIER ASSIGN expression
637 $$ = new DictionaryEntry (
639 new Argument ((Expression) $3, Argument.AType.Expression));
645 : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
648 opt_class_member_declarations
650 | class_member_declarations
653 class_member_declarations
654 : class_member_declaration
655 | class_member_declarations
656 class_member_declaration
659 class_member_declaration
660 : constant_declaration // done
661 | field_declaration // done
662 | method_declaration // done
663 | property_declaration // done
664 | event_declaration // done
665 | indexer_declaration // done
666 | operator_declaration // done
667 | constructor_declaration // done
668 | destructor_declaration // done
678 string full_struct_name = MakeName ((string) $4);
680 new_struct = new Struct (current_namespace, current_container, full_struct_name,
681 (int) $2, (Attributes) $1, lexer.Location);
682 current_container = new_struct;
683 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
689 Struct new_struct = (Struct) current_container;
692 new_struct.Bases = (ArrayList) $6;
694 current_container = current_container.Parent;
695 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
698 | opt_attributes opt_modifiers STRUCT error {
699 CheckIdentifierToken (yyToken);
704 : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
707 opt_struct_member_declarations
709 | struct_member_declarations
712 struct_member_declarations
713 : struct_member_declaration
714 | struct_member_declarations struct_member_declaration
717 struct_member_declaration
718 : constant_declaration
721 | property_declaration
723 | indexer_declaration
724 | operator_declaration
725 | constructor_declaration
729 * This is only included so we can flag error 575:
730 * destructors only allowed on class types
732 | destructor_declaration
743 foreach (VariableDeclaration constant in (ArrayList) $5){
744 Location l = constant.Location;
746 Const c = new Const (
747 (Expression) $4, (string) constant.identifier,
748 (Expression) constant.expression_or_array_initializer, (int) $2,
751 CheckDef (current_container.AddConstant (c), c.Name, l);
757 : constant_declarator
759 ArrayList constants = new ArrayList (4);
763 | constant_declarators COMMA constant_declarator
765 ArrayList constants = (ArrayList) $1;
772 : IDENTIFIER ASSIGN constant_expression
774 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
785 Expression type = (Expression) $3;
788 foreach (VariableDeclaration var in (ArrayList) $4){
789 Location l = var.Location;
791 Field field = new Field (type, mod, var.identifier,
792 var.expression_or_array_initializer,
795 CheckDef (current_container.AddField (field), field.Name, l);
803 Report.Error (670, lexer.Location, "void type is not allowed for fields");
808 : variable_declarator
810 ArrayList decl = new ArrayList (4);
814 | variable_declarators COMMA variable_declarator
816 ArrayList decls = (ArrayList) $1;
823 : IDENTIFIER ASSIGN variable_initializer
825 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
829 $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
842 | STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
844 $$ = new StackAlloc ((Expression) $2, (Expression) $4, lexer.Location);
850 iterator_container = (IIteratorContainer) $1;
854 Method method = (Method) $1;
855 Block b = (Block) $3;
856 const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT);
859 if ((method.ModFlags & extern_abstract) == 0){
861 501, lexer.Location, current_container.MakeName (method.Name) +
862 "must declare a body because it is not marked abstract or extern");
865 if ((method.ModFlags & Modifiers.EXTERN) != 0){
867 179, lexer.Location, current_container.MakeName (method.Name) +
868 " is declared extern, but has a body");
872 method.Block = (Block) $3;
873 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
875 current_local_parameters = null;
876 iterator_container = null;
890 1585, lexer.Location, "Member modifier `" +
891 Modifiers.Name (i) + "' must precede member type and name");
904 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
906 Method method = new Method ((Expression) $3, (int) $2, (string) $4,
907 (Parameters) $6, (Attributes) $1, lexer.Location);
909 current_local_parameters = (Parameters) $6;
917 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
919 Method method = new Method (TypeManager.system_void_expr, (int) $2, (string) $4,
920 (Parameters) $6, (Attributes) $1, lexer.Location);
922 current_local_parameters = (Parameters) $6;
929 | SEMICOLON { $$ = null; }
932 opt_formal_parameter_list
933 : /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; }
934 | formal_parameter_list
937 formal_parameter_list
940 ArrayList pars_list = (ArrayList) $1;
942 Parameter [] pars = new Parameter [pars_list.Count];
943 pars_list.CopyTo (pars);
945 $$ = new Parameters (pars, null, lexer.Location);
947 | fixed_parameters COMMA parameter_array
949 ArrayList pars_list = (ArrayList) $1;
951 Parameter [] pars = new Parameter [pars_list.Count];
952 pars_list.CopyTo (pars);
954 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
958 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
965 ArrayList pars = new ArrayList (4);
970 | fixed_parameters COMMA fixed_parameter
972 ArrayList pars = (ArrayList) $1;
981 opt_parameter_modifier
985 $$ = new Parameter ((Expression) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
988 opt_parameter_modifier
991 CheckIdentifierToken (yyToken);
996 opt_parameter_modifier
997 : /* empty */ { $$ = Parameter.Modifier.NONE; }
1002 : REF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
1003 | OUT { $$ = Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF; }
1007 : opt_attributes PARAMS type IDENTIFIER
1009 $$ = new Parameter ((Expression) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
1010 note ("type must be a single-dimension array type");
1012 | opt_attributes PARAMS type error {
1013 CheckIdentifierToken (yyToken);
1019 : qualified_identifier
1022 property_declaration
1028 implicit_value_parameter_type = (Expression) $3;
1030 lexer.PropertyParsing = true;
1032 $$ = lexer.Location;
1034 accessor_declarations
1036 lexer.PropertyParsing = false;
1041 Pair pair = (Pair) $7;
1042 Accessor get_block = (Accessor) pair.First;
1043 Accessor set_block = (Accessor) pair.Second;
1045 Location loc = (Location) $6;
1046 prop = new Property ((Expression) $3, (string) $4, (int) $2, get_block, set_block,
1047 (Attributes) $1, loc);
1049 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
1050 implicit_value_parameter_type = null;
1054 accessor_declarations
1055 : get_accessor_declaration opt_set_accessor_declaration
1057 $$ = new Pair ($1, $2);
1059 | set_accessor_declaration opt_get_accessor_declaration
1061 $$ = new Pair ($2, $1);
1065 opt_get_accessor_declaration
1066 : /* empty */ { $$ = null; }
1067 | get_accessor_declaration
1070 opt_set_accessor_declaration
1071 : /* empty */ { $$ = null; }
1072 | set_accessor_declaration
1075 get_accessor_declaration
1076 : opt_attributes GET
1078 // If this is not the case, then current_local_parameters has already
1079 // been set in indexer_declaration
1080 if (parsing_indexer == false)
1081 current_local_parameters = null;
1083 current_local_parameters = indexer_parameters;
1084 lexer.PropertyParsing = false;
1088 $$ = new Accessor ((Block) $4, (Attributes) $1);
1089 current_local_parameters = null;
1090 lexer.PropertyParsing = true;
1094 set_accessor_declaration
1095 : opt_attributes SET
1098 Parameter implicit_value_parameter = new Parameter (
1099 implicit_value_parameter_type, "value",
1100 Parameter.Modifier.NONE, null);
1102 if (parsing_indexer == false) {
1103 args = new Parameter [1];
1104 args [0] = implicit_value_parameter;
1105 current_local_parameters = new Parameters (args, null, lexer.Location);
1107 Parameter [] fpars = indexer_parameters.FixedParameters;
1110 int count = fpars.Length;
1112 args = new Parameter [count + 1];
1113 fpars.CopyTo (args, 0);
1114 args [count] = implicit_value_parameter;
1117 current_local_parameters = new Parameters (
1118 args, indexer_parameters.ArrayParameter, lexer.Location);
1121 lexer.PropertyParsing = false;
1125 $$ = new Accessor ((Block) $4, (Attributes) $1);
1126 current_local_parameters = null;
1127 lexer.PropertyParsing = true;
1133 | SEMICOLON { $$ = null; }
1136 interface_declaration
1139 INTERFACE IDENTIFIER
1141 Interface new_interface;
1142 string full_interface_name = MakeName ((string) $4);
1144 new_interface = new Interface (current_namespace, current_container, full_interface_name,
1145 (int) $2, (Attributes) $1, lexer.Location);
1146 if (current_interface != null) {
1147 Location l = lexer.Location;
1148 Report.Error (-2, l, "Internal compiler error: interface inside interface");
1150 current_interface = new_interface;
1151 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1154 interface_body opt_semicolon
1156 Interface new_interface = (Interface) current_interface;
1159 new_interface.Bases = (ArrayList) $6;
1161 current_interface = null;
1162 CheckDef (current_container.AddInterface (new_interface),
1163 new_interface.Name, new_interface.Location);
1165 | opt_attributes opt_modifiers INTERFACE error {
1166 CheckIdentifierToken (yyToken);
1171 : /* empty */ { $$ = null; }
1176 : COLON interface_type_list { $$ = $2; }
1182 ArrayList interfaces = new ArrayList (4);
1184 interfaces.Add ($1);
1187 | interface_type_list COMMA interface_type
1189 ArrayList interfaces = (ArrayList) $1;
1190 interfaces.Add ($3);
1197 opt_interface_member_declarations
1201 opt_interface_member_declarations
1203 | interface_member_declarations
1206 interface_member_declarations
1207 : interface_member_declaration
1208 | interface_member_declarations interface_member_declaration
1211 interface_member_declaration
1212 : interface_method_declaration
1214 InterfaceMethod m = (InterfaceMethod) $1;
1216 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1218 | interface_property_declaration
1220 InterfaceProperty p = (InterfaceProperty) $1;
1222 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1224 | interface_event_declaration
1226 InterfaceEvent e = (InterfaceEvent) $1;
1228 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1230 | interface_indexer_declaration
1232 InterfaceIndexer i = (InterfaceIndexer) $1;
1234 CheckDef (current_interface.AddIndexer (i), "indexer", i.Location);
1239 : /* empty */ { $$ = false; }
1240 | NEW { $$ = true; }
1243 interface_method_declaration
1244 : opt_attributes opt_new type IDENTIFIER
1245 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1248 $$ = new InterfaceMethod ((Expression) $3, (string) $4, (bool) $2,
1249 (Parameters) $6, (Attributes) $1, lexer.Location);
1251 | opt_attributes opt_new VOID IDENTIFIER
1252 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1255 $$ = new InterfaceMethod (
1256 TypeManager.system_void_expr, (string) $4, (bool) $2, (Parameters) $6,
1257 (Attributes) $1, lexer.Location);
1261 interface_property_declaration
1266 { lexer.PropertyParsing = true; }
1268 { lexer.PropertyParsing = false; }
1273 $$ = new InterfaceProperty ((Expression) $3, (string) $4, (bool) $2,
1274 (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1,
1280 CheckIdentifierToken (yyToken);
1286 : opt_attributes GET SEMICOLON { $$ = 1; }
1287 | opt_attributes SET SEMICOLON { $$ = 2; }
1288 | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
1290 | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
1294 interface_event_declaration
1295 : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
1297 $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
1300 | opt_attributes opt_new EVENT type error {
1301 CheckIdentifierToken (yyToken);
1306 interface_indexer_declaration
1307 : opt_attributes opt_new type THIS
1308 OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1310 { lexer.PropertyParsing = true; }
1312 { lexer.PropertyParsing = false; }
1315 int a_flags = (int) $10;
1317 bool do_get = (a_flags & 1) == 1;
1318 bool do_set = (a_flags & 2) == 2;
1320 $$ = new InterfaceIndexer ((Expression) $3, (Parameters) $6, do_get, do_set,
1321 (bool) $2, (Attributes) $1, lexer.Location);
1325 operator_declaration
1326 : opt_attributes opt_modifiers operator_declarator operator_body
1328 OperatorDeclaration decl = (OperatorDeclaration) $3;
1330 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
1331 decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
1333 // Note again, checking is done in semantic analysis
1334 current_container.AddOperator (op);
1336 current_local_parameters = null;
1342 | SEMICOLON { $$ = null; }
1345 : type OPERATOR overloadable_operator
1346 OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1348 Operator.OpType op = (Operator.OpType) $3;
1349 CheckUnaryOperator (op);
1351 if (op == Operator.OpType.Addition)
1352 op = Operator.OpType.UnaryPlus;
1354 if (op == Operator.OpType.Subtraction)
1355 op = Operator.OpType.UnaryNegation;
1357 Parameter [] pars = new Parameter [1];
1359 pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1361 current_local_parameters = new Parameters (pars, null, lexer.Location);
1363 $$ = new OperatorDeclaration (op, (Expression) $1, (Expression) $5, (string) $6,
1364 null, null, lexer.Location);
1366 | type OPERATOR overloadable_operator
1368 type IDENTIFIER COMMA
1372 CheckBinaryOperator ((Operator.OpType) $3);
1374 Parameter [] pars = new Parameter [2];
1376 pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1377 pars [1] = new Parameter ((Expression) $8, (string) $9, Parameter.Modifier.NONE, null);
1379 current_local_parameters = new Parameters (pars, null, lexer.Location);
1381 $$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1,
1382 (Expression) $5, (string) $6,
1383 (Expression) $8, (string) $9, lexer.Location);
1385 | conversion_operator_declarator
1388 overloadable_operator
1390 : BANG { $$ = Operator.OpType.LogicalNot; }
1391 | TILDE { $$ = Operator.OpType.OnesComplement; }
1392 | OP_INC { $$ = Operator.OpType.Increment; }
1393 | OP_DEC { $$ = Operator.OpType.Decrement; }
1394 | TRUE { $$ = Operator.OpType.True; }
1395 | FALSE { $$ = Operator.OpType.False; }
1396 // Unary and binary:
1397 | PLUS { $$ = Operator.OpType.Addition; }
1398 | MINUS { $$ = Operator.OpType.Subtraction; }
1400 | STAR { $$ = Operator.OpType.Multiply; }
1401 | DIV { $$ = Operator.OpType.Division; }
1402 | PERCENT { $$ = Operator.OpType.Modulus; }
1403 | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
1404 | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
1405 | CARRET { $$ = Operator.OpType.ExclusiveOr; }
1406 | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
1407 | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
1408 | OP_EQ { $$ = Operator.OpType.Equality; }
1409 | OP_NE { $$ = Operator.OpType.Inequality; }
1410 | OP_GT { $$ = Operator.OpType.GreaterThan; }
1411 | OP_LT { $$ = Operator.OpType.LessThan; }
1412 | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
1413 | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
1416 conversion_operator_declarator
1417 : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1419 Parameter [] pars = new Parameter [1];
1421 pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1423 current_local_parameters = new Parameters (pars, null, lexer.Location);
1425 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (Expression) $3, (Expression) $5, (string) $6,
1426 null, null, lexer.Location);
1428 | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1430 Parameter [] pars = new Parameter [1];
1432 pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
1434 current_local_parameters = new Parameters (pars, null, lexer.Location);
1436 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (Expression) $3, (Expression) $5, (string) $6,
1437 null, null, lexer.Location);
1441 syntax_error (lexer.Location, "'operator' expected");
1445 syntax_error (lexer.Location, "'operator' expected");
1449 constructor_declaration
1452 constructor_declarator
1455 Constructor c = (Constructor) $3;
1456 c.Block = (Block) $4;
1457 c.OptAttributes = (Attributes) $1;
1458 c.ModFlags = (int) $2;
1460 if (c.Name == current_container.Basename){
1461 if ((c.ModFlags & Modifiers.STATIC) != 0){
1462 if ((c.ModFlags & Modifiers.Accessibility) != 0){
1464 515, c.Location, String.Format (
1465 "`{0}.{1}': static constructor can not have access modifiers",
1466 c.Name, current_container.Name));
1469 c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
1471 if (c.Initializer != null){
1474 "Static constructors can not have an explicit this or base " +
1475 "constructor invocations");
1478 if (!c.Parameters.Empty){
1480 132, c.Location, "Static constructors should not have parameters");
1483 c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
1486 // We let another layer check the validity of the constructor.
1487 Console.WriteLine ("{0} and {1}", c.Name, current_container.Basename);
1490 CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
1492 current_local_parameters = null;
1496 constructor_declarator
1498 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1500 oob_stack.Push (lexer.Location);
1502 current_local_parameters = (Parameters) $3;
1504 opt_constructor_initializer
1506 Location l = (Location) oob_stack.Pop ();
1507 $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $6, l);
1513 | SEMICOLON { $$ = null; }
1516 opt_constructor_initializer
1517 : /* empty */ { $$ = null; }
1518 | constructor_initializer
1521 constructor_initializer
1522 : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
1524 $$ = new ConstructorBaseInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
1526 | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
1528 $$ = new ConstructorThisInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
1531 Report.Error (1018, lexer.Location, "Keyword this or base expected");
1537 : /* EMPTY */ { $$ = 0; }
1538 | UNSAFE { $$ = Modifiers.UNSAFE; }
1539 | EXTERN { $$ = Modifiers.EXTERN; }
1542 destructor_declaration
1543 : opt_attributes opt_finalizer TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
1545 if ((string) $4 != current_container.Basename){
1546 Report.Error (574, lexer.Location, "Name of destructor must match name of class");
1547 } else if (!(current_container is Class)){
1548 Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
1550 Location l = lexer.Location;
1553 if (!RootContext.StdLib && current_container.Name == "System.Object")
1554 m |= Modifiers.PROTECTED | Modifiers.VIRTUAL;
1556 m |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
1558 if ((m & Modifiers.UNSAFE) != 0){
1559 if (!RootContext.Unsafe){
1560 Report.Error (227, l,
1561 "Unsafe code requires the --unsafe command " +
1562 "line option to be specified");
1566 Method d = new Method (
1567 TypeManager.system_void_expr, m, "Finalize",
1568 new Parameters (null, null, l), (Attributes) $1, l);
1570 d.Block = (Block) $7;
1571 CheckDef (current_container.AddMethod (d), d.Name, d.Location);
1579 EVENT type variable_declarators SEMICOLON
1581 foreach (VariableDeclaration var in (ArrayList) $5) {
1583 Event e = new Event ((Expression) $4, var.identifier,
1584 var.expression_or_array_initializer,
1585 (int) $2, null, null, (Attributes) $1, lexer.Location);
1587 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1593 EVENT type member_name
1596 implicit_value_parameter_type = (Expression) $4;
1597 lexer.EventParsing = true;
1598 oob_stack.Push (lexer.Location);
1600 event_accessor_declarations
1602 lexer.EventParsing = false;
1606 Location loc = (Location) oob_stack.Pop ();
1608 Pair pair = (Pair) $8;
1609 Accessor add_accessor = null;
1610 Accessor rem_accessor = null;
1612 if (pair.First != null)
1613 add_accessor = (Accessor) pair.First;
1614 if (pair.Second != null)
1615 rem_accessor = (Accessor) pair.Second;
1617 Event e = new Event ((Expression) $4, (string) $5, null, (int) $2, add_accessor, rem_accessor,
1618 (Attributes) $1, loc);
1620 CheckDef (current_container.AddEvent (e), e.Name, loc);
1621 implicit_value_parameter_type = null;
1625 event_accessor_declarations
1626 : add_accessor_declaration remove_accessor_declaration
1628 $$ = new Pair ($1, $2);
1630 | remove_accessor_declaration add_accessor_declaration
1632 $$ = new Pair ($2, $1);
1636 add_accessor_declaration
1637 : opt_attributes ADD
1639 Parameter [] args = new Parameter [1];
1640 Parameter implicit_value_parameter = new Parameter (
1641 implicit_value_parameter_type, "value",
1642 Parameter.Modifier.NONE, null);
1644 args [0] = implicit_value_parameter;
1646 current_local_parameters = new Parameters (args, null, lexer.Location);
1647 lexer.EventParsing = false;
1651 $$ = new Accessor ((Block) $4, (Attributes) $1);
1652 lexer.EventParsing = true;
1654 | opt_attributes ADD error {
1655 Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
1660 remove_accessor_declaration
1661 : opt_attributes REMOVE
1663 Parameter [] args = new Parameter [1];
1664 Parameter implicit_value_parameter = new Parameter (
1665 implicit_value_parameter_type, "value",
1666 Parameter.Modifier.NONE, null);
1668 args [0] = implicit_value_parameter;
1670 current_local_parameters = new Parameters (args, null, lexer.Location);
1671 lexer.EventParsing = false;
1675 $$ = new Accessor ((Block) $4, (Attributes) $1);
1676 lexer.EventParsing = true;
1678 | opt_attributes REMOVE error {
1679 Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
1685 : opt_attributes opt_modifiers indexer_declarator
1688 IndexerDeclaration decl = (IndexerDeclaration) $3;
1690 implicit_value_parameter_type = decl.type;
1692 lexer.PropertyParsing = true;
1693 parsing_indexer = true;
1695 indexer_parameters = decl.param_list;
1696 oob_stack.Push (lexer.Location);
1698 accessor_declarations
1700 lexer.PropertyParsing = false;
1701 parsing_indexer = false;
1705 // The signature is computed from the signature of the indexer. Look
1706 // at section 3.6 on the spec
1707 Location loc = (Location) oob_stack.Pop ();
1709 IndexerDeclaration decl = (IndexerDeclaration) $3;
1710 Pair pair = (Pair) $6;
1711 Accessor get_block = (Accessor) pair.First;
1712 Accessor set_block = (Accessor) pair.Second;
1714 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
1715 get_block, set_block, (Attributes) $1, loc);
1717 // Note that there is no equivalent of CheckDef for this case
1718 // We shall handle this in semantic analysis
1720 current_container.AddIndexer (indexer);
1722 current_local_parameters = null;
1723 implicit_value_parameter_type = null;
1724 indexer_parameters = null;
1729 : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1731 Parameters pars = (Parameters) $4;
1733 if (pars.FixedParameters == null && pars.ArrayParameter == null){
1734 Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1737 $$ = new IndexerDeclaration ((Expression) $1, null, pars);
1739 | type qualified_identifier DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1741 Parameters pars = (Parameters) $6;
1743 if (pars.FixedParameters == null && pars.ArrayParameter == null){
1744 Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1746 $$ = new IndexerDeclaration ((Expression) $1, (string) $2, pars);
1758 Location enum_location = lexer.Location;
1760 string full_name = MakeName ((string) $4);
1761 Enum e = new Enum (current_namespace, current_container, (Expression) $5, (int) $2,
1762 full_name, (Attributes) $1, enum_location);
1764 foreach (VariableDeclaration ev in (ArrayList) $6) {
1765 Location loc = (Location) ev.Location;
1767 CheckDef (e.AddEnumMember (ev.identifier,
1768 (Expression) ev.expression_or_array_initializer,
1769 loc, ev.OptAttributes),
1770 ev.identifier, loc);
1773 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1774 RootContext.Tree.RecordDecl (full_name, e);
1780 : /* empty */ { $$ = TypeManager.system_int32_expr; }
1781 | COLON type { $$ = $2; }
1785 : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
1791 opt_enum_member_declarations
1792 : /* empty */ { $$ = new ArrayList (4); }
1793 | enum_member_declarations opt_comma { $$ = $1; }
1796 enum_member_declarations
1797 : enum_member_declaration
1799 ArrayList l = new ArrayList (4);
1804 | enum_member_declarations COMMA enum_member_declaration
1806 ArrayList l = (ArrayList) $1;
1814 enum_member_declaration
1815 : opt_attributes IDENTIFIER
1817 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1819 | opt_attributes IDENTIFIER
1821 $$ = lexer.Location;
1825 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1829 delegate_declaration
1833 IDENTIFIER OPEN_PARENS
1834 opt_formal_parameter_list
1838 Location l = lexer.Location;
1839 Delegate del = new Delegate (current_namespace, current_container, (Expression) $4,
1840 (int) $2, MakeName ((string) $5), (Parameters) $7,
1841 (Attributes) $1, l);
1843 CheckDef (current_container.AddDelegate (del), del.Name, l);
1848 IDENTIFIER OPEN_PARENS
1849 opt_formal_parameter_list
1853 Location l = lexer.Location;
1854 Delegate del = new Delegate (
1855 current_namespace, current_container,
1856 TypeManager.system_void_expr, (int) $2, MakeName ((string) $5),
1857 (Parameters) $7, (Attributes) $1, l);
1859 CheckDef (current_container.AddDelegate (del), del.Name, l);
1864 : namespace_or_type_name
1867 namespace_or_type_name
1868 : IDENTIFIER opt_type_argument_list {
1870 $$ = new SimpleName ((string) $1, lexer.Location);
1872 $$ = new ConstructedType ((string) $1, (TypeArguments) $2, lexer.Location);
1874 | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list
1879 // Third argument will become an Expression, when we have sorted out
1880 // the issues with SimpleName first
1882 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1888 // Figure out what to do with the list
1890 opt_type_argument_list
1891 : /* empty */ { $$ = null; }
1892 | OP_GENERICS_LT type_arguments OP_GENERICS_GT
1900 TypeArguments type_args = new TypeArguments ();
1901 type_args.Add ((Expression) $1);
1904 | type_arguments COMMA type {
1905 TypeArguments type_args = (TypeArguments) $1;
1906 type_args.Add ((Expression) $3);
1912 * Before you think of adding a return_type, notice that we have been
1913 * using two rules in the places where it matters (one rule using type
1914 * and another identical one that uses VOID as the return type). This
1915 * gets rid of a shift/reduce couple
1918 : type_name { /* class_type */
1930 // Note that here only unmanaged types are allowed but we
1931 // can't perform checks during this phase - we do it during
1932 // semantic analysis.
1934 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1938 $$ = new ComposedCast (TypeManager.system_void_expr, "*", lexer.Location);
1944 | non_expression_type rank_specifier
1946 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1948 | non_expression_type STAR
1950 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1952 | expression rank_specifiers
1954 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1958 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1962 // We need this because the parser will happily go and reduce IDENTIFIER STAR
1963 // through this different path
1965 | multiplicative_expression STAR
1967 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1974 ArrayList types = new ArrayList (4);
1979 | type_list COMMA type
1981 ArrayList types = (ArrayList) $1;
1989 * replaces all the productions for isolating the various
1990 * simple types, but we need this to reuse it easily in local_variable_type
1993 : OBJECT { $$ = TypeManager.system_object_expr; }
1994 | STRING { $$ = TypeManager.system_string_expr; }
1995 | BOOL { $$ = TypeManager.system_boolean_expr; }
1996 | DECIMAL { $$ = TypeManager.system_decimal_expr; }
1997 | FLOAT { $$ = TypeManager.system_single_expr; }
1998 | DOUBLE { $$ = TypeManager.system_double_expr; }
2003 : SBYTE { $$ = TypeManager.system_sbyte_expr; }
2004 | BYTE { $$ = TypeManager.system_byte_expr; }
2005 | SHORT { $$ = TypeManager.system_int16_expr; }
2006 | USHORT { $$ = TypeManager.system_uint16_expr; }
2007 | INT { $$ = TypeManager.system_int32_expr; }
2008 | UINT { $$ = TypeManager.system_uint32_expr; }
2009 | LONG { $$ = TypeManager.system_int64_expr; }
2010 | ULONG { $$ = TypeManager.system_uint64_expr; }
2011 | CHAR { $$ = TypeManager.system_char_expr; }
2012 | VOID { $$ = TypeManager.system_void_expr; }
2020 : type rank_specifiers
2022 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
2027 // Expressions, section 7.5
2039 | parenthesized_expression
2041 | invocation_expression
2045 | post_increment_expression
2046 | post_decrement_expression
2050 | checked_expression
2051 | unchecked_expression
2052 | pointer_member_access
2053 | anonymous_method_expression
2060 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
2061 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
2062 | NULL { $$ = NullLiteral.Null; }
2066 : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }
2067 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
2068 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
2073 object v = lexer.Value;
2079 $$ = IntLiteral.Zero;
2081 $$ = IntLiteral.One;
2083 $$ = new IntLiteral (i);
2084 } else if (v is uint)
2085 $$ = new UIntLiteral ((UInt32) v);
2087 $$ = new LongLiteral ((Int64) v);
2088 else if (v is ulong)
2089 $$ = new ULongLiteral ((UInt64) v);
2091 Console.WriteLine ("OOPS. Unexpected result from scanner");
2096 : TRUE { $$ = new BoolLiteral (true); }
2097 | FALSE { $$ = new BoolLiteral (false); }
2100 parenthesized_expression_0
2101 : OPEN_PARENS expression CLOSE_PARENS
2104 lexer.Deambiguate_CloseParens ();
2105 // After this, the next token returned is one of
2106 // CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST, CLOSE_PARENS_OPEN_PARENS
2107 // or CLOSE_PARENS_MINUS.
2111 parenthesized_expression
2112 : parenthesized_expression_0 CLOSE_PARENS_NO_CAST
2116 | parenthesized_expression_0 CLOSE_PARENS_MINUS
2118 // If a parenthesized expression is followed by a minus, we need to wrap
2119 // the expression inside a ParenthesizedExpression for the CS0075 check
2120 // in Binary.DoResolve().
2121 $$ = new ParenthesizedExpression ((Expression) $1, lexer.Location);
2126 : primary_expression DOT IDENTIFIER
2128 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2130 | predefined_type DOT IDENTIFIER
2132 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
2140 invocation_expression
2141 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
2144 Location l = lexer.Location;
2145 Report.Error (1, l, "Parse error");
2147 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
2149 | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS CLOSE_PARENS
2151 $$ = new Invocation ((Expression) $1, new ArrayList (), lexer.Location);
2153 | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS primary_expression
2155 $$ = new InvocationOrCast ((Expression) $1, (Expression) $3, lexer.Location);
2160 : /* empty */ { $$ = null; }
2167 ArrayList list = new ArrayList (4);
2171 | argument_list COMMA argument
2173 ArrayList list = (ArrayList) $1;
2177 | argument_list error {
2178 CheckToken (1026, yyToken, ", or ) expected");
2185 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2187 | REF variable_reference
2189 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2191 | OUT variable_reference
2193 $$ = new Argument ((Expression) $2, Argument.AType.Out);
2198 : expression { note ("section 5.4"); $$ = $1; }
2202 : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
2204 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2206 | primary_expression rank_specifiers
2208 // So the super-trick is that primary_expression
2209 // can only be either a SimpleName or a MemberAccess.
2210 // The MemberAccess case arises when you have a fully qualified type-name like :
2212 // SimpleName is when you have
2215 Expression expr = (Expression) $1;
2216 if (expr is ComposedCast){
2217 $$ = new ComposedCast (expr, (string) $2, lexer.Location);
2218 } else if (!(expr is SimpleName || expr is MemberAccess || expr is ConstructedType)){
2219 Error_ExpectingTypeName (lexer.Location, expr);
2220 $$ = TypeManager.system_object_expr;
2223 // So we extract the string corresponding to the SimpleName
2226 $$ = new ComposedCast (expr, (string) $2, lexer.Location);
2234 ArrayList list = new ArrayList (4);
2238 | expression_list COMMA expression
2240 ArrayList list = (ArrayList) $1;
2249 $$ = new This (current_block, lexer.Location);
2254 : BASE DOT IDENTIFIER
2256 $$ = new BaseAccess ((string) $3, lexer.Location);
2258 | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
2260 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
2263 Report.Error (175, "Use of keyword `base' is not valid in this context");
2268 post_increment_expression
2269 : primary_expression OP_INC
2271 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
2272 (Expression) $1, lexer.Location);
2276 post_decrement_expression
2277 : primary_expression OP_DEC
2279 $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
2280 (Expression) $1, lexer.Location);
2285 : object_or_delegate_creation_expression
2286 | array_creation_expression
2289 object_or_delegate_creation_expression
2290 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2292 $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
2296 array_creation_expression
2297 : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
2299 opt_array_initializer
2301 $$ = new ArrayCreation ((Expression) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
2303 | NEW type rank_specifiers array_initializer
2305 $$ = new ArrayCreation ((Expression) $2, (string) $3, (ArrayList) $4, lexer.Location);
2309 Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
2325 : rank_specifier opt_rank_specifier
2327 $$ = (string) $2 + (string) $1;
2332 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2334 $$ = "[" + (string) $2 + "]";
2354 | dim_separators COMMA
2356 $$ = (string) $1 + ",";
2360 opt_array_initializer
2372 : OPEN_BRACE CLOSE_BRACE
2374 ArrayList list = new ArrayList (4);
2377 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
2379 $$ = (ArrayList) $2;
2383 variable_initializer_list
2384 : variable_initializer
2386 ArrayList list = new ArrayList (4);
2390 | variable_initializer_list COMMA variable_initializer
2392 ArrayList list = (ArrayList) $1;
2399 : TYPEOF OPEN_PARENS VOID CLOSE_PARENS
2401 $$ = new TypeOfVoid (lexer.Location);
2403 | TYPEOF OPEN_PARENS type CLOSE_PARENS
2405 $$ = new TypeOf ((Expression) $3, lexer.Location);
2410 : SIZEOF OPEN_PARENS type CLOSE_PARENS {
2411 $$ = new SizeOf ((Expression) $3, lexer.Location);
2416 : CHECKED OPEN_PARENS expression CLOSE_PARENS
2418 $$ = new CheckedExpr ((Expression) $3, lexer.Location);
2422 unchecked_expression
2423 : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
2425 $$ = new UnCheckedExpr ((Expression) $3, lexer.Location);
2429 pointer_member_access
2430 : primary_expression OP_PTR IDENTIFIER
2434 deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lexer.Location);
2435 $$ = new MemberAccess (deref, (string) $3, lexer.Location);
2439 anonymous_method_expression
2440 : DELEGATE opt_anonymous_method_signature {
2441 oob_stack.Push (current_local_parameters);
2442 current_local_parameters = (Parameters)$2;
2444 if (!RootContext.V2){
2445 Report.Error (-213, lexer.Location, "Anonymous methods are only supported in V2");
2448 $$ = new AnonymousMethod ((Parameters) $2, (Block) $4, lexer.Location);
2449 current_local_parameters = (Parameters) oob_stack.Pop ();
2453 opt_anonymous_method_signature
2454 : /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; }
2455 | anonymous_method_signature
2458 anonymous_method_signature
2459 : OPEN_PARENS opt_anonymous_method_parameter_list CLOSE_PARENS
2462 $$ = Parameters.EmptyReadOnlyParameters;
2464 ArrayList par_list = (ArrayList) $2;
2465 Parameter [] pars = new Parameter [par_list.Count];
2466 par_list.CopyTo (pars);
2467 $$ = new Parameters (pars, null, lexer.Location);
2472 opt_anonymous_method_parameter_list
2473 : /* empty */ { $$ = null; }
2474 | anonymous_method_parameter_list { $$ = $1; }
2477 anonymous_method_parameter_list
2478 : anonymous_method_parameter
2480 ArrayList a = new ArrayList (4);
2484 | anonymous_method_parameter_list COMMA anonymous_method_parameter
2486 ArrayList a = (ArrayList) $1;
2492 anonymous_method_parameter
2493 : opt_parameter_modifier type IDENTIFIER {
2494 $$ = new Parameter ((Expression) $2, (string) $2, (Parameter.Modifier) $1, null);
2499 : primary_expression
2500 | BANG prefixed_unary_expression
2502 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2504 | TILDE prefixed_unary_expression
2506 $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
2512 : parenthesized_expression_0 CLOSE_PARENS_CAST unary_expression
2514 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
2516 | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression
2518 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
2524 | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
2526 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2531 // The idea to split this out is from Rhys' grammar
2532 // to solve the problem with casts.
2534 prefixed_unary_expression
2536 | PLUS prefixed_unary_expression
2538 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2540 | MINUS prefixed_unary_expression
2542 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2544 | OP_INC prefixed_unary_expression
2546 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2547 (Expression) $2, lexer.Location);
2549 | OP_DEC prefixed_unary_expression
2551 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2552 (Expression) $2, lexer.Location);
2554 | STAR prefixed_unary_expression
2556 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
2558 | BITWISE_AND prefixed_unary_expression
2560 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
2564 pre_increment_expression
2565 : OP_INC prefixed_unary_expression
2567 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2568 (Expression) $2, lexer.Location);
2572 pre_decrement_expression
2573 : OP_DEC prefixed_unary_expression
2575 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2576 (Expression) $2, lexer.Location);
2580 multiplicative_expression
2581 : prefixed_unary_expression
2582 | multiplicative_expression STAR prefixed_unary_expression
2584 $$ = new Binary (Binary.Operator.Multiply,
2585 (Expression) $1, (Expression) $3, lexer.Location);
2587 | multiplicative_expression DIV prefixed_unary_expression
2589 $$ = new Binary (Binary.Operator.Division,
2590 (Expression) $1, (Expression) $3, lexer.Location);
2592 | multiplicative_expression PERCENT prefixed_unary_expression
2594 $$ = new Binary (Binary.Operator.Modulus,
2595 (Expression) $1, (Expression) $3, lexer.Location);
2600 : multiplicative_expression
2601 | additive_expression PLUS multiplicative_expression
2603 $$ = new Binary (Binary.Operator.Addition,
2604 (Expression) $1, (Expression) $3, lexer.Location);
2606 | additive_expression MINUS multiplicative_expression
2608 $$ = new Binary (Binary.Operator.Subtraction,
2609 (Expression) $1, (Expression) $3, lexer.Location);
2614 : additive_expression
2615 | shift_expression OP_SHIFT_LEFT additive_expression
2617 $$ = new Binary (Binary.Operator.LeftShift,
2618 (Expression) $1, (Expression) $3, lexer.Location);
2620 | shift_expression OP_SHIFT_RIGHT additive_expression
2622 $$ = new Binary (Binary.Operator.RightShift,
2623 (Expression) $1, (Expression) $3, lexer.Location);
2627 relational_expression
2629 | relational_expression OP_LT shift_expression
2631 $$ = new Binary (Binary.Operator.LessThan,
2632 (Expression) $1, (Expression) $3, lexer.Location);
2634 | relational_expression OP_GT shift_expression
2636 $$ = new Binary (Binary.Operator.GreaterThan,
2637 (Expression) $1, (Expression) $3, lexer.Location);
2639 | relational_expression OP_LE shift_expression
2641 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2642 (Expression) $1, (Expression) $3, lexer.Location);
2644 | relational_expression OP_GE shift_expression
2646 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2647 (Expression) $1, (Expression) $3, lexer.Location);
2649 | relational_expression IS type
2651 $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
2653 | relational_expression AS type
2655 $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
2660 : relational_expression
2661 | equality_expression OP_EQ relational_expression
2663 $$ = new Binary (Binary.Operator.Equality,
2664 (Expression) $1, (Expression) $3, lexer.Location);
2666 | equality_expression OP_NE relational_expression
2668 $$ = new Binary (Binary.Operator.Inequality,
2669 (Expression) $1, (Expression) $3, lexer.Location);
2674 : equality_expression
2675 | and_expression BITWISE_AND equality_expression
2677 $$ = new Binary (Binary.Operator.BitwiseAnd,
2678 (Expression) $1, (Expression) $3, lexer.Location);
2682 exclusive_or_expression
2684 | exclusive_or_expression CARRET and_expression
2686 $$ = new Binary (Binary.Operator.ExclusiveOr,
2687 (Expression) $1, (Expression) $3, lexer.Location);
2691 inclusive_or_expression
2692 : exclusive_or_expression
2693 | inclusive_or_expression BITWISE_OR exclusive_or_expression
2695 $$ = new Binary (Binary.Operator.BitwiseOr,
2696 (Expression) $1, (Expression) $3, lexer.Location);
2700 conditional_and_expression
2701 : inclusive_or_expression
2702 | conditional_and_expression OP_AND inclusive_or_expression
2704 $$ = new Binary (Binary.Operator.LogicalAnd,
2705 (Expression) $1, (Expression) $3, lexer.Location);
2709 conditional_or_expression
2710 : conditional_and_expression
2711 | conditional_or_expression OP_OR conditional_and_expression
2713 $$ = new Binary (Binary.Operator.LogicalOr,
2714 (Expression) $1, (Expression) $3, lexer.Location);
2718 conditional_expression
2719 : conditional_or_expression
2720 | conditional_or_expression INTERR expression COLON expression
2722 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2726 assignment_expression
2727 : prefixed_unary_expression ASSIGN expression
2729 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2731 | prefixed_unary_expression OP_MULT_ASSIGN expression
2733 Location l = lexer.Location;
2735 $$ = new CompoundAssign (
2736 Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
2738 | prefixed_unary_expression OP_DIV_ASSIGN expression
2740 Location l = lexer.Location;
2742 $$ = new CompoundAssign (
2743 Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
2745 | prefixed_unary_expression OP_MOD_ASSIGN expression
2747 Location l = lexer.Location;
2749 $$ = new CompoundAssign (
2750 Binary.Operator.Modulus, (Expression) $1, (Expression) $3, l);
2752 | prefixed_unary_expression OP_ADD_ASSIGN expression
2754 Location l = lexer.Location;
2756 $$ = new CompoundAssign (
2757 Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
2759 | prefixed_unary_expression OP_SUB_ASSIGN expression
2761 Location l = lexer.Location;
2763 $$ = new CompoundAssign (
2764 Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
2766 | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
2768 Location l = lexer.Location;
2770 $$ = new CompoundAssign (
2771 Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, l);
2773 | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2775 Location l = lexer.Location;
2777 $$ = new CompoundAssign (
2778 Binary.Operator.RightShift, (Expression) $1, (Expression) $3, l);
2780 | prefixed_unary_expression OP_AND_ASSIGN expression
2782 Location l = lexer.Location;
2784 $$ = new CompoundAssign (
2785 Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3, l);
2787 | prefixed_unary_expression OP_OR_ASSIGN expression
2789 Location l = lexer.Location;
2791 $$ = new CompoundAssign (
2792 Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3, l);
2794 | prefixed_unary_expression OP_XOR_ASSIGN expression
2796 Location l = lexer.Location;
2798 $$ = new CompoundAssign (
2799 Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3, l);
2804 : conditional_expression
2805 | assignment_expression
2827 name = MakeName ((string) $4);
2829 new_class = new Class (current_namespace, current_container, name, (int) $2,
2830 (Attributes) $1, lexer.Location);
2831 current_container = new_class;
2832 RootContext.Tree.RecordDecl (name, new_class);
2834 opt_type_parameter_list
2836 opt_type_parameter_constraints_clauses
2840 Class new_class = (Class) current_container;
2842 if ($8 != null && $6 == null)
2843 Report.Error (-200, new_class.Location,
2844 "Type parameter constraints only valid if there is a type parameter list");
2847 CheckDef (new_class.SetParameterInfo ((ArrayList) $6, (ArrayList) $8, new_class.Location), new_class.Name, new_class.Location);
2849 new_class.Bases = (ArrayList) $7;
2850 current_container = current_container.Parent;
2851 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
2859 Report.Error (-200, lexer.Location,
2860 "Type parameter constraints only valid if there is a type parameter list");
2867 : /* empty */ { $$ = (int) 0; }
2873 | modifiers modifier
2878 if ((m1 & m2) != 0) {
2879 Location l = lexer.Location;
2880 Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2882 $$ = (int) (m1 | m2);
2887 : NEW { $$ = Modifiers.NEW; }
2888 | PUBLIC { $$ = Modifiers.PUBLIC; }
2889 | PROTECTED { $$ = Modifiers.PROTECTED; }
2890 | INTERNAL { $$ = Modifiers.INTERNAL; }
2891 | PRIVATE { $$ = Modifiers.PRIVATE; }
2892 | ABSTRACT { $$ = Modifiers.ABSTRACT; }
2893 | SEALED { $$ = Modifiers.SEALED; }
2894 | STATIC { $$ = Modifiers.STATIC; }
2895 | READONLY { $$ = Modifiers.READONLY; }
2896 | VIRTUAL { $$ = Modifiers.VIRTUAL; }
2897 | OVERRIDE { $$ = Modifiers.OVERRIDE; }
2898 | EXTERN { $$ = Modifiers.EXTERN; }
2899 | VOLATILE { $$ = Modifiers.VOLATILE; }
2900 | UNSAFE { $$ = Modifiers.UNSAFE; }
2904 : /* empty */ { $$ = null; }
2905 | class_base { $$ = $1; }
2909 : COLON type_list { $$ = $2; }
2912 opt_type_parameter_list
2913 : /* empty */ { $$ = null; }
2914 | type_parameter_list { $$ = $1; }
2918 : OP_GENERICS_LT type_parameters OP_GENERICS_GT { $$ = $2; }
2924 // Do some profiling to find the optimal size, for now we
2925 // assume most people will be generic on one type (saves space
2927 ArrayList type_parameters = new ArrayList (1);
2928 type_parameters.Add ($1);
2929 $$ = type_parameters;
2931 | type_parameters COMMA type_parameter {
2932 ArrayList type_parameters = (ArrayList) $1;
2934 type_parameters.Add ($3);
2935 $$ = type_parameters;
2943 opt_type_parameter_constraints_clauses
2944 : /* empty */ { $$ = null; }
2945 | type_parameter_constraints_clauses
2949 type_parameter_constraints_clauses
2950 : type_parameter_constraints_clause
2951 | type_parameter_constraints_clauses type_parameter_constraints_clause {
2952 ArrayList constraints = (ArrayList) $1;
2954 constraints.Add ($2);
2959 type_parameter_constraints_clause
2960 : WHERE type_parameter COLON type_parameter_constraints {
2961 ArrayList constraints = new ArrayList (1);
2962 constraints.Add (new Constraints ((string) $2, (ArrayList) $4, lexer.Location));
2967 type_parameter_constraints
2968 : type_parameter_constraint {
2969 ArrayList constraints = new ArrayList (1);
2970 constraints.Add ($1);
2973 | type_parameter_constraints COMMA type_parameter_constraint {
2974 ArrayList constraints = (ArrayList) $1;
2976 constraints.Add ($3);
2981 type_parameter_constraint
2983 | NEW OPEN_PARENS CLOSE_PARENS {
2993 // A block is "contained" on the following places:
2995 // property_declaration as part of the accessor body (get/set)
2996 // operator_declaration
2997 // constructor_declaration
2998 // destructor_declaration
2999 // event_declaration as part of add_accessor_declaration or remove_accessor_declaration
3004 current_block = new Block (current_block, current_local_parameters,
3005 lexer.Location, Location.Null);
3007 opt_statement_list CLOSE_BRACE
3009 while (current_block.Implicit)
3010 current_block = current_block.Parent;
3012 current_block.SetEndLocation (lexer.Location);
3013 current_block = current_block.Parent;
3024 | statement_list statement
3028 : declaration_statement
3030 if ($1 != null && (Block) $1 != current_block){
3031 current_block.AddStatement ((Statement) $1);
3032 current_block = (Block) $1;
3035 | embedded_statement
3037 Statement s = (Statement) $1;
3040 current_block.AddStatement ((Statement) $1);
3048 | expression_statement
3049 | selection_statement
3050 | iteration_statement
3054 | unchecked_statement
3064 $$ = new EmptyStatement ();
3071 LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
3073 if (!current_block.AddLabel ((string) $1, labeled)){
3074 Location l = lexer.Location;
3075 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
3077 current_block.AddStatement (labeled);
3082 declaration_statement
3083 : local_variable_declaration SEMICOLON
3086 DictionaryEntry de = (DictionaryEntry) $1;
3088 $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
3092 | local_constant_declaration SEMICOLON
3095 DictionaryEntry de = (DictionaryEntry) $1;
3097 $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
3103 * The following is from Rhys' grammar:
3104 * > Types in local variable declarations must be recognized as
3105 * > expressions to prevent reduce/reduce errors in the grammar.
3106 * > The expressions are converted into types during semantic analysis.
3109 : primary_expression opt_rank_specifier
3111 // FIXME: Do something smart here regarding the composition of the type.
3113 // Ok, the above "primary_expression" is there to get rid of
3114 // both reduce/reduce and shift/reduces in the grammar, it should
3115 // really just be "type_name". If you use type_name, a reduce/reduce
3116 // creeps up. If you use qualified_identifier (which is all we need
3117 // really) two shift/reduces appear.
3120 // So the super-trick is that primary_expression
3121 // can only be either a SimpleName or a MemberAccess.
3122 // The MemberAccess case arises when you have a fully qualified type-name like :
3124 // SimpleName is when you have
3127 Expression expr = (Expression) $1;
3128 if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is ConstructedType)) {
3129 Error_ExpectingTypeName (lexer.Location, expr);
3133 // So we extract the string corresponding to the SimpleName
3137 if ((string) $2 == "")
3140 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3143 | builtin_types opt_rank_specifier
3145 if ((string) $2 == "")
3148 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3152 local_variable_pointer_type
3153 : primary_expression STAR
3155 Expression expr = (Expression) $1;
3156 Location l = lexer.Location;
3158 if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is ConstructedType)) {
3159 Error_ExpectingTypeName (l, expr);
3163 $$ = new ComposedCast ((Expression) $1, "*", l);
3165 | builtin_types STAR
3167 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);;
3171 $$ = new ComposedCast (TypeManager.system_void_expr, "*", lexer.Location);;
3173 | local_variable_pointer_type STAR
3175 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
3179 local_variable_declaration
3180 : local_variable_type variable_declarators
3183 $$ = new DictionaryEntry ($1, $2);
3187 | local_variable_pointer_type opt_rank_specifier variable_declarators
3192 if ((string) $2 == "")
3193 t = (Expression) $1;
3195 t = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
3196 $$ = new DictionaryEntry (t, $3);
3202 local_constant_declaration
3203 : CONST local_variable_type constant_declarator
3206 $$ = new DictionaryEntry ($2, $3);
3212 expression_statement
3213 : statement_expression SEMICOLON
3220 // We have to do the wrapping here and not in the case above,
3221 // because statement_expression is used for example in for_statement
3223 statement_expression
3224 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3225 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3226 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3227 | post_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3228 | post_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3229 | pre_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3230 | pre_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
3232 Report.Error (1002, lexer.Location, "Expecting `;'");
3237 object_creation_expression
3238 : object_or_delegate_creation_expression
3239 { note ("complain if this is a delegate maybe?"); }
3248 : if_statement_open if_statement_rest
3257 oob_stack.Push (lexer.Location);
3262 : boolean_expression CLOSE_PARENS
3265 Location l = (Location) oob_stack.Pop ();
3267 $$ = new If ((Expression) $1, (Statement) $3, l);
3269 if (RootContext.WarningLevel >= 3){
3270 if ($3 is EmptyStatement)
3271 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3275 | boolean_expression CLOSE_PARENS
3276 embedded_statement ELSE embedded_statement
3278 Location l = (Location) oob_stack.Pop ();
3280 $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l);
3285 : SWITCH OPEN_PARENS
3287 oob_stack.Push (lexer.Location);
3288 switch_stack.Push (current_block);
3290 expression CLOSE_PARENS
3293 $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
3294 current_block = (Block) switch_stack.Pop ();
3310 Report.Error (1522, lexer.Location, "Empty switch block");
3318 ArrayList sections = new ArrayList (4);
3323 | switch_sections switch_section
3325 ArrayList sections = (ArrayList) $1;
3335 current_block = current_block.CreateSwitchBlock (lexer.Location);
3339 Block topmost = current_block;
3341 while (topmost.Implicit)
3342 topmost = topmost.Parent;
3343 $$ = new SwitchSection ((ArrayList) $1, topmost);
3350 ArrayList labels = new ArrayList (4);
3355 | switch_labels switch_label
3357 ArrayList labels = (ArrayList) ($1);
3365 : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
3366 | DEFAULT COLON { $$ = new SwitchLabel (null, lexer.Location); }
3369 1523, lexer.Location,
3370 "The keyword case or default must precede code in switch block");
3384 oob_stack.Push (lexer.Location);
3386 boolean_expression CLOSE_PARENS embedded_statement
3388 Location l = (Location) oob_stack.Pop ();
3389 $$ = new While ((Expression) $4, (Statement) $6, l);
3391 if (RootContext.WarningLevel >= 3){
3392 if ($6 is EmptyStatement)
3393 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3399 : DO embedded_statement
3401 oob_stack.Push (lexer.Location);
3403 boolean_expression CLOSE_PARENS SEMICOLON
3405 Location l = (Location) oob_stack.Pop ();
3407 $$ = new Do ((Statement) $2, (Expression) $6, l);
3413 opt_for_initializer SEMICOLON
3415 Block assign_block = new Block (current_block);
3416 current_block = assign_block;
3418 if ($3 is DictionaryEntry){
3419 DictionaryEntry de = (DictionaryEntry) $3;
3421 Expression type = (Expression) de.Key;
3422 ArrayList var_declarators = (ArrayList) de.Value;
3424 foreach (VariableDeclaration decl in var_declarators){
3428 vi = current_block.AddVariable (
3429 type, decl.identifier, current_local_parameters, decl.Location);
3433 Location l = lexer.Location;
3435 if (decl.expression_or_array_initializer is Expression){
3436 expr = (Expression) decl.expression_or_array_initializer;
3437 } else if (decl.expression_or_array_initializer == null) {
3440 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3441 expr = new ArrayCreation (type, "", init, decl.Location);
3444 LocalVariableReference var;
3445 var = new LocalVariableReference (assign_block, decl.identifier, l);
3448 Assign a = new Assign (var, expr, decl.Location);
3450 assign_block.AddStatement (new StatementExpression (a, lexer.Location));
3456 oob_stack.Push (lexer.Location);
3458 opt_for_condition SEMICOLON
3459 opt_for_iterator CLOSE_PARENS
3462 Location l = (Location) oob_stack.Pop ();
3464 For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
3466 if (RootContext.WarningLevel >= 3){
3467 if ($10 is EmptyStatement)
3468 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3471 current_block.AddStatement (f);
3472 while (current_block.Implicit)
3473 current_block = current_block.Parent;
3475 current_block = current_block.Parent;
3480 : /* empty */ { $$ = new EmptyStatement (); }
3485 : local_variable_declaration
3486 | statement_expression_list
3490 : /* empty */ { $$ = null; }
3491 | boolean_expression
3495 : /* empty */ { $$ = new EmptyStatement (); }
3500 : statement_expression_list
3503 statement_expression_list
3504 : statement_expression
3506 // CHANGE: was `null'
3507 Block b = new Block (current_block, Block.Flags.Implicit);
3509 b.AddStatement ((Statement) $1);
3512 | statement_expression_list COMMA statement_expression
3514 Block b = (Block) $1;
3516 b.AddStatement ((Statement) $3);
3522 : FOREACH OPEN_PARENS type IDENTIFIER IN
3524 oob_stack.Push (lexer.Location);
3526 expression CLOSE_PARENS
3528 oob_stack.Push (current_block);
3530 Block foreach_block = new Block (current_block, Block.Flags.Implicit);
3531 LocalVariableReference v = null;
3532 Location l = lexer.Location;
3535 vi = foreach_block.AddVariable ((Expression) $3, (string) $4, current_local_parameters, l);
3539 // Get a writable reference to this read-only variable.
3540 v = new LocalVariableReference (foreach_block, (string) $4, l, vi, false);
3542 current_block = foreach_block;
3545 oob_stack.Push (current_block);
3549 Block foreach_block = (Block) oob_stack.Pop ();
3550 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
3551 Block prev_block = (Block) oob_stack.Pop ();
3552 Location l = (Location) oob_stack.Pop ();
3554 current_block = prev_block;
3557 Foreach f = new Foreach ((Expression) $3, v, (Expression) $7, (Statement) $10, l);
3558 foreach_block.AddStatement (f);
3567 | continue_statement
3577 $$ = new Break (lexer.Location);
3582 : CONTINUE SEMICOLON
3584 $$ = new Continue (lexer.Location);
3589 : GOTO IDENTIFIER SEMICOLON
3591 $$ = new Goto (current_block, (string) $2, lexer.Location);
3593 | GOTO CASE constant_expression SEMICOLON
3595 $$ = new GotoCase ((Expression) $3, lexer.Location);
3597 | GOTO DEFAULT SEMICOLON
3599 $$ = new GotoDefault (lexer.Location);
3604 : RETURN opt_expression SEMICOLON
3606 $$ = new Return ((Expression) $2, lexer.Location);
3611 : THROW opt_expression SEMICOLON
3613 $$ = new Throw ((Expression) $2, lexer.Location);
3618 : YIELD expression SEMICOLON
3620 if (iterator_container == null){
3621 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
3624 iterator_container.SetYields ();
3625 $$ = new Yield ((Expression) $2, lexer.Location);
3628 | YIELD BREAK SEMICOLON
3630 if (iterator_container == null){
3631 Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
3634 iterator_container.SetYields ();
3635 $$ = new YieldBreak (lexer.Location);
3646 : TRY block catch_clauses
3649 ArrayList s = new ArrayList (4);
3651 foreach (Catch cc in (ArrayList) $3) {
3658 // Now s contains the list of specific catch clauses
3659 // and g contains the general one.
3661 $$ = new Try ((Block) $2, s, g, null, lexer.Location);
3663 | TRY block opt_catch_clauses FINALLY block
3666 ArrayList s = new ArrayList (4);
3667 ArrayList catch_list = (ArrayList) $3;
3669 if (catch_list != null){
3670 foreach (Catch cc in catch_list) {
3678 $$ = new Try ((Block) $2, s, g, (Block) $5, lexer.Location);
3682 Report.Error (1524, lexer.Location, "Expected catch or finally");
3687 : /* empty */ { $$ = null; }
3694 ArrayList l = new ArrayList (4);
3699 | catch_clauses catch_clause
3701 ArrayList l = (ArrayList) $1;
3709 : /* empty */ { $$ = null; }
3714 : CATCH opt_catch_args
3716 Expression type = null;
3720 DictionaryEntry cc = (DictionaryEntry) $2;
3721 type = (Expression) cc.Key;
3722 id = (string) cc.Value;
3725 ArrayList one = new ArrayList (4);
3726 Location loc = lexer.Location;
3728 one.Add (new VariableDeclaration (id, null, loc));
3731 current_block = new Block (current_block);
3732 Block b = declare_local_variables (type, one, loc);
3737 Expression type = null;
3741 DictionaryEntry cc = (DictionaryEntry) $2;
3742 type = (Expression) cc.Key;
3743 id = (string) cc.Value;
3747 // FIXME: I can change this for an assignment.
3749 while (current_block != (Block) $1)
3750 current_block = current_block.Parent;
3755 $$ = new Catch (type, id , (Block) $4, lexer.Location);
3760 : /* empty */ { $$ = null; }
3765 : OPEN_PARENS type opt_identifier CLOSE_PARENS
3767 $$ = new DictionaryEntry ($2, $3);
3774 $$ = new Checked ((Block) $2);
3781 $$ = new Unchecked ((Block) $2);
3788 if (!RootContext.Unsafe){
3789 Report.Error (227, lexer.Location,
3790 "Unsafe code can only be used if --unsafe is used");
3793 $$ = new Unsafe ((Block) $3);
3799 type fixed_pointer_declarators
3802 Block assign_block = new Block (current_block, Block.Flags.Implicit);
3803 ArrayList list = (ArrayList) $4;
3804 Expression type = (Expression) $3;
3805 Location l = lexer.Location;
3806 int top = list.Count;
3808 for (int i = 0; i < top; i++){
3809 Pair p = (Pair) list [i];
3812 v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
3819 current_block.AddStatement (assign_block);
3820 current_block = assign_block;
3821 oob_stack.Push (assign_block);
3826 Location l = (Location) oob_stack.Pop ();
3827 Block assign_block = (Block) oob_stack.Pop ();
3829 ArrayList list = (ArrayList) $4;
3830 int top = list.Count;
3832 $$ = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l);
3836 fixed_pointer_declarators
3837 : fixed_pointer_declarator {
3838 ArrayList declarators = new ArrayList (4);
3839 declarators.Add ($1);
3842 | fixed_pointer_declarators COMMA fixed_pointer_declarator
3844 ArrayList declarators = (ArrayList) $1;
3845 declarators.Add ($3);
3850 fixed_pointer_declarator
3851 : IDENTIFIER ASSIGN expression
3853 $$ = new Pair ($1, $3);
3858 : LOCK OPEN_PARENS expression CLOSE_PARENS
3864 $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
3869 : USING OPEN_PARENS resource_acquisition CLOSE_PARENS
3871 Block assign_block = new Block (current_block);
3872 current_block = assign_block;
3874 oob_stack.Push (lexer.Location);
3876 if ($3 is DictionaryEntry){
3877 DictionaryEntry de = (DictionaryEntry) $3;
3878 Location l = lexer.Location;
3880 Expression type = (Expression) de.Key;
3881 ArrayList var_declarators = (ArrayList) de.Value;
3883 ArrayList vars = new ArrayList (4);
3885 foreach (VariableDeclaration decl in var_declarators){
3887 LocalInfo vi = current_block.AddVariable (
3888 type, decl.identifier,
3889 current_local_parameters, decl.Location);
3895 if (decl.expression_or_array_initializer is Expression){
3896 expr = (Expression) decl.expression_or_array_initializer;
3898 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3900 expr = new ArrayCreation (type, "", init, decl.Location);
3903 LocalVariableReference var;
3905 // Get a writable reference to this read-only variable.
3906 var = new LocalVariableReference (assign_block, decl.identifier, l, vi, false);
3908 // This is so that it is not a warning on using variables
3911 vars.Add (new DictionaryEntry (var, expr));
3913 // Assign a = new Assign (var, expr, decl.Location);
3914 // assign_block.AddStatement (new StatementExpression (a, lexer.Location));
3916 $3 = new DictionaryEntry (type, vars);
3921 Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
3922 current_block.AddStatement (u);
3923 while (current_block.Implicit)
3924 current_block = current_block.Parent;
3926 current_block = current_block.Parent;
3930 resource_acquisition
3931 : local_variable_declaration
3938 // A class used to pass around variable declarations and constants
3940 public class VariableDeclaration {
3941 public string identifier;
3942 public object expression_or_array_initializer;
3943 public Location Location;
3944 public Attributes OptAttributes;
3946 public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs)
3948 this.identifier = id;
3949 this.expression_or_array_initializer = eoai;
3951 this.OptAttributes = opt_attrs;
3954 public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3960 // A class used to hold info about an indexer declarator
3963 public class IndexerDeclaration {
3964 public Expression type;
3965 public string interface_type;
3966 public Parameters param_list;
3968 public IndexerDeclaration (Expression type, string interface_type, Parameters param_list)
3971 this.interface_type = interface_type;
3972 this.param_list = param_list;
3977 // A class used to hold info about an operator declarator
3980 public class OperatorDeclaration {
3981 public Operator.OpType optype;
3982 public Expression ret_type, arg1type, arg2type;
3983 public string arg1name, arg2name;
3984 public Location location;
3986 public OperatorDeclaration (Operator.OpType op, Expression ret_type,
3987 Expression arg1type, string arg1name,
3988 Expression arg2type, string arg2name, Location location)
3991 this.ret_type = ret_type;
3992 this.arg1type = arg1type;
3993 this.arg1name = arg1name;
3994 this.arg2type = arg2type;
3995 this.arg2name = arg2name;
3996 this.location = location;
4001 void Error_ExpectingTypeName (Location l, Expression expr)
4003 if (expr is Invocation){
4004 Report.Error (1002, l, "; expected");
4006 Report.Error (-1, l, "Invalid Type definition");
4011 // Given the @class_name name, it creates a fully qualified name
4012 // based on the containing declaration space
4015 MakeName (string class_name)
4017 string ns = current_namespace.FullName;
4018 string container_name = current_container.Name;
4020 if (container_name == ""){
4022 return ns + "." + class_name;
4026 return container_name + "." + class_name;
4030 // Used to report back to the user the result of a declaration
4031 // in the current declaration space
4034 CheckDef (DeclSpace.AdditionResult result, string name, Location l)
4036 if (result == DeclSpace.AdditionResult.Success)
4040 case DeclSpace.AdditionResult.NameExists:
4041 Report.Error (102, l, "The container `" + current_container.Name +
4042 "' already contains a definition for `"+
4048 // This is handled only for static Constructors, because
4049 // in reality we handle these by the semantic analysis later
4051 case DeclSpace.AdditionResult.MethodExists:
4053 111, l, "Class `"+current_container.Name+
4054 "' already defines a member called '" +
4055 name + "' with the same parameter types (more than one default constructor)");
4058 case DeclSpace.AdditionResult.EnclosingClash:
4059 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
4062 case DeclSpace.AdditionResult.NotAConstructor:
4063 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
4066 case DeclSpace.AdditionResult.Error:
4067 // Error has already been reported.
4073 CheckDef (bool result, string name, Location l)
4077 CheckDef (DeclSpace.AdditionResult.NameExists, name, l);
4080 Expression DecomposeQI (string name, Location loc)
4084 if (name.IndexOf ('.') == -1){
4085 return new SimpleName (name, loc);
4087 int pos = name.LastIndexOf (".");
4088 string left = name.Substring (0, pos);
4089 string right = name.Substring (pos + 1);
4091 o = DecomposeQI (left, loc);
4093 return new MemberAccess (o, right, loc);
4097 Block declare_local_variables (Expression type, ArrayList variable_declarators, Location loc)
4099 Block implicit_block;
4100 ArrayList inits = null;
4103 // We use the `Used' property to check whether statements
4104 // have been added to the current block. If so, we need
4105 // to create another block to contain the new declaration
4106 // otherwise, as an optimization, we use the same block to
4107 // add the declaration.
4109 // FIXME: A further optimization is to check if the statements
4110 // that were added were added as part of the initialization
4111 // below. In which case, no other statements have been executed
4112 // and we might be able to reduce the number of blocks for
4113 // situations like this:
4115 // int j = 1; int k = j + 1;
4117 if (current_block.Used) {
4118 implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
4119 implicit_block.AddChildVariableNames (current_block);
4121 implicit_block = current_block;
4123 foreach (VariableDeclaration decl in variable_declarators){
4125 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
4126 if (decl.expression_or_array_initializer != null){
4128 inits = new ArrayList (4);
4135 return implicit_block;
4137 foreach (VariableDeclaration decl in inits){
4141 if (decl.expression_or_array_initializer is Expression){
4142 expr = (Expression) decl.expression_or_array_initializer;
4145 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
4147 expr = new ArrayCreation (type, "", init, decl.Location);
4150 LocalVariableReference var;
4151 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
4153 assign = new Assign (var, expr, decl.Location);
4155 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
4158 return implicit_block;
4161 Block declare_local_constant (Expression type, VariableDeclaration decl)
4163 Block implicit_block;
4165 if (current_block.Used)
4166 implicit_block = new Block (current_block, Block.Flags.Implicit);
4168 implicit_block = current_block;
4170 if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
4171 current_local_parameters, decl.Location))){
4174 return implicit_block;
4177 void CheckAttributeTarget (string a)
4181 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
4185 Location l = lexer.Location;
4186 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
4192 void CheckUnaryOperator (Operator.OpType op)
4196 case Operator.OpType.LogicalNot:
4197 case Operator.OpType.OnesComplement:
4198 case Operator.OpType.Increment:
4199 case Operator.OpType.Decrement:
4200 case Operator.OpType.True:
4201 case Operator.OpType.False:
4202 case Operator.OpType.Addition:
4203 case Operator.OpType.Subtraction:
4208 Location l = lexer.Location;
4209 Report.Error (1019, l, "Overloadable unary operator expected");
4215 void CheckBinaryOperator (Operator.OpType op)
4219 case Operator.OpType.Addition:
4220 case Operator.OpType.Subtraction:
4221 case Operator.OpType.Multiply:
4222 case Operator.OpType.Division:
4223 case Operator.OpType.Modulus:
4224 case Operator.OpType.BitwiseAnd:
4225 case Operator.OpType.BitwiseOr:
4226 case Operator.OpType.ExclusiveOr:
4227 case Operator.OpType.LeftShift:
4228 case Operator.OpType.RightShift:
4229 case Operator.OpType.Equality:
4230 case Operator.OpType.Inequality:
4231 case Operator.OpType.GreaterThan:
4232 case Operator.OpType.LessThan:
4233 case Operator.OpType.GreaterThanOrEqual:
4234 case Operator.OpType.LessThanOrEqual:
4238 Location l = lexer.Location;
4239 Report.Error (1020, l, "Overloadable binary operator expected");
4245 void syntax_error (Location l, string msg)
4247 Report.Error (1003, l, "Syntax error, " + msg);
4250 void output (string s)
4252 Console.WriteLine (s);
4255 void note (string s)
4257 // Used to put annotations
4262 public Tokenizer Lexer {
4268 public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines)
4270 current_namespace = new NamespaceEntry (null, file, null, Location.Null);
4271 this.name = file.Name;
4273 current_container = RootContext.Tree.Types;
4274 current_container.NamespaceEntry = current_namespace;
4275 oob_stack = new Stack ();
4276 switch_stack = new Stack ();
4278 lexer = new Tokenizer (reader, file, defines);
4281 public void parse ()
4284 if (yacc_verbose_flag)
4285 yyparse (lexer, new yydebug.yyDebugSimple ());
4288 Tokenizer tokenizer = lexer as Tokenizer;
4289 tokenizer.cleanup ();
4290 } catch (Exception e){
4291 // Please do not remove this, it is used during debugging
4294 Console.WriteLine (e);
4295 Report.Error (-25, lexer.Location, "Parsing error");
4296 if (Driver.parser_verbose)
4297 Console.WriteLine (e);
4301 void CheckToken (int error, int yyToken, string msg)
4303 if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD){
4304 Report.Error (error, lexer.Location, String.Format ("{0}: `{1}' is a keyword", msg, yyName [yyToken].ToLower ()));
4307 Report.Error (error, lexer.Location, msg);
4310 void CheckIdentifierToken (int yyToken)
4312 CheckToken (1041, yyToken, "Identifier expected");