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)
11 // Ravi Pratap (ravi@ximian.com)
13 // Licensed under the terms of the GNU GPL
15 // (C) 2001 Ximian, Inc (http://www.ximian.com)
18 // (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM
19 // And come to think of it, it is not that great, it duplicates a lot of code
20 // for something which is not really needed. We still have piles of typecasts
21 // anwyays (due to the nature of the stack being a collection of Objects).
23 // (2) Figure out why error productions dont work. `type-declaration' is a
24 // great spot to put an `error' because you can reproduce it with this input:
27 // (3) Move Modifier checking from each object into the parser itself, that will
28 // get rid of the global "error" symbol that we use now to report errors.
29 // We still need to pass a pointer to the tree.ErrorHandler, but that is a
37 using System.Collections;
43 public class CSharpParser : GenericParser {
44 Namespace current_namespace;
45 TypeContainer current_container;
48 // Current block is used to add statements as we find
55 // Current interface is used by the various declaration
56 // productions in the interface declaration to "add"
57 // the interfaces as we find them.
59 Interface current_interface;
62 // This is used by the unary_expression code to resolve
63 // a name against a parameter.
65 Parameters current_local_parameters;
68 // Using during property parsing to describe the implicit
69 // value parameter that is passed to the "set" and "get"accesor
70 // methods (properties and indexers).
72 string implicit_value_parameter_type;
73 Parameters indexer_parameters;
76 // Used to determine if we are parsing the get/set pair
77 // of an indexer or a property
82 // An out-of-band stack.
88 %token NONE /* This token is never returned by our lexer */
89 %token ERROR // This is used not by the parser, but by the tokenizer.
93 *These are the C# keywords
176 /* C# keywords which are not really keywords */
180 /* C# single character operators/punctuation. */
181 %token OPEN_BRACE "{"
182 %token CLOSE_BRACE "}"
183 %token OPEN_BRACKET "["
184 %token CLOSE_BRACKET "]"
185 %token OPEN_PARENS "("
186 %token CLOSE_PARENS ")"
199 %token BITWISE_AND "&"
200 %token BITWISE_OR "|"
207 /* C# multi-character operators. */
210 %token OP_SHIFT_LEFT "<<"
211 %token OP_SHIFT_RIGHT ">>"
218 %token OP_MULT_ASSIGN "*="
219 %token OP_DIV_ASSIGN "/="
220 %token OP_MOD_ASSIGN "%="
221 %token OP_ADD_ASSIGN "+="
222 %token OP_SUB_ASSIGN "-="
223 %token OP_SHIFT_LEFT_ASSIGN "<<="
224 %token OP_SHIFT_RIGHT_ASSIGN ">>="
225 %token OP_AND_ASSIGN "&="
226 %token OP_XOR_ASSIGN "^="
227 %token OP_OR_ASSIGN "|="
231 %token LITERAL_INTEGER "int literal"
232 %token LITERAL_FLOAT "float literal"
233 %token LITERAL_DOUBLE "double literal"
234 %token LITERAL_DECIMAL "decimal literal"
235 %token LITERAL_CHARACTER "character literal"
236 %token LITERAL_STRING "string literal"
240 /* Add precedence rules to solve dangling else s/r conflict */
249 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
251 %left STAR DIV PERCENT
252 %right BANG CARRET UMINUS
253 %nonassoc OP_INC OP_DEC
255 %left OPEN_BRACKET OPEN_BRACE
259 %start compilation_unit
263 : outer_declarations opt_EOF
264 | outer_declarations attribute_sections opt_EOF
265 | attribute_sections opt_EOF
275 | outer_declarations outer_declaration
280 | namespace_member_declaration
285 | using_directives using_directive
289 : using_alias_directive
290 | using_namespace_directive
293 using_alias_directive
294 : USING IDENTIFIER ASSIGN
295 namespace_or_type_name SEMICOLON
297 current_namespace.UsingAlias ((string) $2, (string) $4, lexer.Location);
301 using_namespace_directive
302 : USING namespace_name SEMICOLON
304 current_namespace.Using ((string) $2);
309 // Strictly speaking, namespaces don't have attributes but
310 // we parse global attributes along with namespace declarations and then
313 namespace_declaration
314 : opt_attributes NAMESPACE qualified_identifier
316 Attributes attrs = (Attributes) $1;
319 foreach (AttributeSection asec in attrs.AttributeSections)
320 if (asec.Target == "assembly")
321 RootContext.AddGlobalAttribute (
322 current_container, asec, lexer.Location);
325 current_namespace = RootContext.Tree.RecordNamespace (current_namespace, name, (string) $3);
327 namespace_body opt_semicolon
329 current_namespace = current_namespace.Parent;
345 | qualified_identifier DOT IDENTIFIER {
346 $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
351 : namespace_or_type_name
357 opt_namespace_member_declarations
368 opt_namespace_member_declarations
370 | namespace_member_declarations
373 namespace_member_declarations
374 : namespace_member_declaration
375 | namespace_member_declarations namespace_member_declaration
378 namespace_member_declaration
385 Class c = (Class) $1;
386 mod_flags = c.ModFlags;
388 } else if ($1 is Struct){
389 Struct s = (Struct) $1;
390 mod_flags = s.ModFlags;
395 if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
397 1527, lexer.Location,
398 "Namespace elements cant be explicitly " +
399 "declared private or protected in `" + name + "'");
402 | namespace_declaration
408 | interface_declaration
410 | delegate_declaration
412 // Enable this when we have handled all errors, because this acts as a generic fallback
415 // Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
425 | attribute_sections { $$ = $1; }
431 AttributeSection sect = (AttributeSection) $1;
433 if (sect.Target == "assembly")
434 RootContext.AddGlobalAttribute (current_container, sect, lexer.Location);
436 $$ = new Attributes ((AttributeSection) $1, lexer.Location);
438 | attribute_sections attribute_section
440 Attributes attrs = null;
441 AttributeSection sect = (AttributeSection) $2;
443 if (sect.Target == "assembly")
444 RootContext.AddGlobalAttribute (current_container, sect, lexer.Location);
447 attrs = (Attributes) $1;
448 attrs.AddAttribute (sect);
456 : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET
458 string target = null;
461 target = (string) $2;
463 $$ = new AttributeSection (target, (ArrayList) $3);
465 | OPEN_BRACKET attribute_list CLOSE_BRACKET
467 $$ = new AttributeSection (null, (ArrayList) $2);
471 attribute_target_specifier
472 : attribute_target COLON
481 CheckAttributeTarget ((string) $1);
484 | EVENT { $$ = "event"; }
485 | RETURN { $$ = "return"; }
491 ArrayList attrs = new ArrayList ();
497 | attribute_list COMMA attribute
499 ArrayList attrs = (ArrayList) $1;
511 opt_attribute_arguments
513 $$ = new Attribute ((string) $1, (ArrayList) $3, (Location) $2);
518 : type_name { /* reserved attribute name or identifier: 17.4 */ }
521 opt_attribute_arguments
522 : /* empty */ { $$ = null; }
523 | OPEN_PARENS attribute_arguments CLOSE_PARENS
531 : opt_positional_argument_list
536 ArrayList args = new ArrayList ();
542 | positional_argument_list COMMA named_argument_list
544 ArrayList args = new ArrayList ();
550 | named_argument_list
552 ArrayList args = new ArrayList ();
561 opt_positional_argument_list
562 : /* empty */ { $$ = null; }
563 | positional_argument_list
566 positional_argument_list
569 ArrayList args = new ArrayList ();
570 args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
574 | positional_argument_list COMMA expression
576 ArrayList args = (ArrayList) $1;
577 args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
586 ArrayList args = new ArrayList ();
591 | named_argument_list COMMA named_argument
593 ArrayList args = (ArrayList) $1;
601 : IDENTIFIER ASSIGN expression
603 $$ = new DictionaryEntry (
605 new Argument ((Expression) $3, Argument.AType.Expression));
611 : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
614 opt_class_member_declarations
616 | class_member_declarations
619 class_member_declarations
620 : class_member_declaration
621 | class_member_declarations
622 class_member_declaration
625 class_member_declaration
626 : constant_declaration // done
627 | field_declaration // done
628 | method_declaration // done
629 | property_declaration // done
630 | event_declaration // done
631 | indexer_declaration // done
632 | operator_declaration // done
633 | constructor_declaration // done
634 | destructor_declaration // done
644 string full_struct_name = MakeName ((string) $4);
646 new_struct = new Struct (current_container, full_struct_name, (int) $2,
647 (Attributes) $1, lexer.Location);
648 current_container = new_struct;
649 current_container.Namespace = current_namespace;
650 RootContext.Tree.RecordDecl (full_struct_name, new_struct);
656 Struct new_struct = (Struct) current_container;
659 new_struct.Bases = (ArrayList) $6;
661 current_container = current_container.Parent;
662 CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
668 : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
671 opt_struct_member_declarations
673 | struct_member_declarations
676 struct_member_declarations
677 : struct_member_declaration
678 | struct_member_declarations struct_member_declaration
681 struct_member_declaration
682 : constant_declaration
685 | property_declaration
687 | indexer_declaration
688 | operator_declaration
689 | constructor_declaration
693 * This is only included so we can flag error 575:
694 * destructors only allowed on class types
696 | destructor_declaration
707 foreach (VariableDeclaration constant in (ArrayList) $5){
708 Location l = constant.Location;
710 Const c = new Const (
711 (string) $4, (string) constant.identifier,
712 (Expression) constant.expression_or_array_initializer, (int) $2,
715 CheckDef (current_container.AddConstant (c), c.Name, l);
721 : constant_declarator
723 ArrayList constants = new ArrayList ();
727 | constant_declarators COMMA constant_declarator
729 ArrayList constants = (ArrayList) $1;
736 : IDENTIFIER ASSIGN constant_expression
738 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
749 string type = (string) $3;
752 foreach (VariableDeclaration var in (ArrayList) $4){
753 Location l = var.Location;
755 Field field = new Field (type, mod, var.identifier,
756 var.expression_or_array_initializer,
759 CheckDef (current_container.AddField (field), field.Name, l);
765 : variable_declarator
767 ArrayList decl = new ArrayList ();
771 | variable_declarators COMMA variable_declarator
773 ArrayList decls = (ArrayList) $1;
780 : IDENTIFIER ASSIGN variable_initializer
782 $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
786 $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
799 | STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
801 $$ = new StackAlloc ((string) $2, (Expression) $4, lexer.Location);
809 Method method = (Method) $1;
810 Block b = (Block) $2;
811 const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT);
814 if ((method.ModFlags & extern_abstract) == 0){
816 501, lexer.Location, current_container.MakeName (method.Name) +
817 "must declare a body because it is not marked abstract or extern");
820 if ((method.ModFlags & Modifiers.EXTERN) != 0){
822 179, lexer.Location, current_container.MakeName (method.Name) +
823 " is declared extern, but has a body");
827 method.Block = (Block) $2;
828 CheckDef (current_container.AddMethod (method), method.Name, method.Location);
830 current_local_parameters = null;
844 1585, lexer.Location, "Member modifier `" +
845 Modifiers.Name (i) + "' must precede member type and name");
858 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
860 Method method = new Method ((string) $3, (int) $2, (string) $4,
861 (Parameters) $6, (Attributes) $1, lexer.Location);
863 current_local_parameters = (Parameters) $6;
871 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
873 Method method = new Method ("System.Void", (int) $2, (string) $4,
874 (Parameters) $6, (Attributes) $1, lexer.Location);
876 current_local_parameters = (Parameters) $6;
883 | SEMICOLON { $$ = null; }
886 opt_formal_parameter_list
887 : /* empty */ { $$ = Parameters.GetEmptyReadOnlyParameters (); }
888 | formal_parameter_list
891 formal_parameter_list
894 ArrayList pars_list = (ArrayList) $1;
896 Parameter [] pars = new Parameter [pars_list.Count];
897 pars_list.CopyTo (pars);
899 $$ = new Parameters (pars, null, lexer.Location);
901 | fixed_parameters COMMA parameter_array
903 ArrayList pars_list = (ArrayList) $1;
905 Parameter [] pars = new Parameter [pars_list.Count];
906 pars_list.CopyTo (pars);
908 $$ = new Parameters (pars, (Parameter) $3, lexer.Location);
912 $$ = new Parameters (null, (Parameter) $1, lexer.Location);
919 ArrayList pars = new ArrayList ();
924 | fixed_parameters COMMA fixed_parameter
926 ArrayList pars = (ArrayList) $1;
935 opt_parameter_modifier
939 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
943 opt_parameter_modifier
944 : /* empty */ { $$ = Parameter.Modifier.NONE; }
949 : REF { $$ = Parameter.Modifier.REF; }
950 | OUT { $$ = Parameter.Modifier.OUT; }
954 : opt_attributes PARAMS type IDENTIFIER
956 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
957 note ("type must be a single-dimension array type");
962 : qualified_identifier
971 implicit_value_parameter_type = (string) $3;
973 lexer.PropertyParsing = true;
977 accessor_declarations
979 lexer.PropertyParsing = false;
984 Pair pair = (Pair) $7;
985 Accessor get_block = (Accessor) pair.First;
986 Accessor set_block = (Accessor) pair.Second;
988 Location loc = (Location) $6;
989 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block,
990 (Attributes) $1, loc);
992 CheckDef (current_container.AddProperty (prop), prop.Name, loc);
993 implicit_value_parameter_type = null;
997 accessor_declarations
998 : get_accessor_declaration opt_set_accessor_declaration
1000 $$ = new Pair ($1, $2);
1002 | set_accessor_declaration opt_get_accessor_declaration
1004 $$ = new Pair ($2, $1);
1008 opt_get_accessor_declaration
1009 : /* empty */ { $$ = null; }
1010 | get_accessor_declaration
1013 opt_set_accessor_declaration
1014 : /* empty */ { $$ = null; }
1015 | set_accessor_declaration
1018 get_accessor_declaration
1019 : opt_attributes GET
1021 // If this is not the case, then current_local_parameters has already
1022 // been set in indexer_declaration
1023 if (parsing_indexer == false)
1024 current_local_parameters = null;
1026 current_local_parameters = indexer_parameters;
1027 lexer.PropertyParsing = false;
1031 $$ = new Accessor ((Block) $4, (Attributes) $1);
1032 current_local_parameters = null;
1033 lexer.PropertyParsing = true;
1037 set_accessor_declaration
1038 : opt_attributes SET
1041 Parameter implicit_value_parameter = new Parameter (
1042 implicit_value_parameter_type, "value",
1043 Parameter.Modifier.NONE, null);
1045 if (parsing_indexer == false) {
1046 args = new Parameter [1];
1047 args [0] = implicit_value_parameter;
1048 current_local_parameters = new Parameters (args, null, lexer.Location);
1050 Parameter [] fpars = indexer_parameters.FixedParameters;
1053 int count = fpars.Length;
1055 args = new Parameter [count + 1];
1056 fpars.CopyTo (args, 0);
1057 args [count] = implicit_value_parameter;
1060 current_local_parameters = new Parameters (
1061 args, indexer_parameters.ArrayParameter, lexer.Location);
1064 lexer.PropertyParsing = false;
1068 $$ = new Accessor ((Block) $4, (Attributes) $1);
1069 current_local_parameters = null;
1070 lexer.PropertyParsing = true;
1076 | SEMICOLON { $$ = null; }
1079 interface_declaration
1082 INTERFACE IDENTIFIER
1084 Interface new_interface;
1085 string full_interface_name = MakeName ((string) $4);
1087 new_interface = new Interface (current_container, full_interface_name, (int) $2,
1088 (Attributes) $1, lexer.Location);
1089 if (current_interface != null) {
1090 Location l = lexer.Location;
1091 Report.Error (-2, l, "Internal compiler error: interface inside interface");
1093 current_interface = new_interface;
1094 new_interface.Namespace = current_namespace;
1095 RootContext.Tree.RecordDecl (full_interface_name, new_interface);
1098 interface_body opt_semicolon
1100 Interface new_interface = (Interface) current_interface;
1103 new_interface.Bases = (ArrayList) $6;
1105 current_interface = null;
1106 CheckDef (current_container.AddInterface (new_interface),
1107 new_interface.Name, new_interface.Location);
1112 : /* empty */ { $$ = null; }
1117 : COLON interface_type_list { $$ = $2; }
1123 ArrayList interfaces = new ArrayList ();
1125 interfaces.Add ($1);
1128 | interface_type_list COMMA interface_type
1130 ArrayList interfaces = (ArrayList) $1;
1131 interfaces.Add ($3);
1138 opt_interface_member_declarations
1142 opt_interface_member_declarations
1144 | interface_member_declarations
1147 interface_member_declarations
1148 : interface_member_declaration
1149 | interface_member_declarations interface_member_declaration
1152 interface_member_declaration
1153 : interface_method_declaration
1155 InterfaceMethod m = (InterfaceMethod) $1;
1157 CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
1159 | interface_property_declaration
1161 InterfaceProperty p = (InterfaceProperty) $1;
1163 CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
1165 | interface_event_declaration
1167 InterfaceEvent e = (InterfaceEvent) $1;
1169 CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
1171 | interface_indexer_declaration
1173 InterfaceIndexer i = (InterfaceIndexer) $1;
1175 CheckDef (current_interface.AddIndexer (i), "indexer", i.Location);
1180 : /* empty */ { $$ = false; }
1181 | NEW { $$ = true; }
1184 interface_method_declaration
1185 : opt_attributes opt_new type IDENTIFIER
1186 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1189 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2,
1190 (Parameters) $6, (Attributes) $1, lexer.Location);
1192 | opt_attributes opt_new VOID IDENTIFIER
1193 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1196 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6,
1197 (Attributes) $1, lexer.Location);
1201 interface_property_declaration
1206 { lexer.PropertyParsing = true; }
1208 { lexer.PropertyParsing = false; }
1213 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2,
1214 (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1,
1220 : opt_attributes GET SEMICOLON { $$ = 1; }
1221 | opt_attributes SET SEMICOLON { $$ = 2; }
1222 | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
1224 | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
1228 interface_event_declaration
1229 : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
1231 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);
1235 interface_indexer_declaration
1236 : opt_attributes opt_new type THIS
1237 OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
1239 { lexer.PropertyParsing = true; }
1241 { lexer.PropertyParsing = false; }
1244 int a_flags = (int) $10;
1246 bool do_get = (a_flags & 1) == 1;
1247 bool do_set = (a_flags & 2) == 2;
1249 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set,
1250 (bool) $2, (Attributes) $1, lexer.Location);
1254 operator_declaration
1255 : opt_attributes opt_modifiers operator_declarator operator_body
1257 OperatorDeclaration decl = (OperatorDeclaration) $3;
1259 Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
1260 decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
1262 // Note again, checking is done in semantic analysis
1263 current_container.AddOperator (op);
1265 current_local_parameters = null;
1271 | SEMICOLON { $$ = null; }
1274 : type OPERATOR overloadable_operator
1275 OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1277 Operator.OpType op = (Operator.OpType) $3;
1278 CheckUnaryOperator (op);
1280 if (op == Operator.OpType.Addition)
1281 op = Operator.OpType.UnaryPlus;
1283 if (op == Operator.OpType.Subtraction)
1284 op = Operator.OpType.UnaryNegation;
1286 Parameter [] pars = new Parameter [1];
1288 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1290 current_local_parameters = new Parameters (pars, null, lexer.Location);
1292 $$ = new OperatorDeclaration (op, (string) $1, (string) $5, (string) $6,
1293 null, null, lexer.Location);
1295 | type OPERATOR overloadable_operator
1297 type IDENTIFIER COMMA
1301 CheckBinaryOperator ((Operator.OpType) $3);
1303 Parameter [] pars = new Parameter [2];
1305 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1306 pars [1] = new Parameter ((string) $8, (string) $9, Parameter.Modifier.NONE, null);
1308 current_local_parameters = new Parameters (pars, null, lexer.Location);
1310 $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
1311 (string) $8, (string) $9, lexer.Location);
1313 | conversion_operator_declarator
1316 overloadable_operator
1318 : BANG { $$ = Operator.OpType.LogicalNot; }
1319 | TILDE { $$ = Operator.OpType.OnesComplement; }
1320 | OP_INC { $$ = Operator.OpType.Increment; }
1321 | OP_DEC { $$ = Operator.OpType.Decrement; }
1322 | TRUE { $$ = Operator.OpType.True; }
1323 | FALSE { $$ = Operator.OpType.False; }
1324 // Unary and binary:
1325 | PLUS { $$ = Operator.OpType.Addition; }
1326 | MINUS { $$ = Operator.OpType.Subtraction; }
1328 | STAR { $$ = Operator.OpType.Multiply; }
1329 | DIV { $$ = Operator.OpType.Division; }
1330 | PERCENT { $$ = Operator.OpType.Modulus; }
1331 | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
1332 | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
1333 | CARRET { $$ = Operator.OpType.ExclusiveOr; }
1334 | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
1335 | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
1336 | OP_EQ { $$ = Operator.OpType.Equality; }
1337 | OP_NE { $$ = Operator.OpType.Inequality; }
1338 | OP_GT { $$ = Operator.OpType.GreaterThan; }
1339 | OP_LT { $$ = Operator.OpType.LessThan; }
1340 | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
1341 | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
1344 conversion_operator_declarator
1345 : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1347 Parameter [] pars = new Parameter [1];
1349 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1351 current_local_parameters = new Parameters (pars, null, lexer.Location);
1353 $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
1354 null, null, lexer.Location);
1356 | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
1358 Parameter [] pars = new Parameter [1];
1360 pars [0] = new Parameter ((string) $5, (string) $6, Parameter.Modifier.NONE, null);
1362 current_local_parameters = new Parameters (pars, null, lexer.Location);
1364 $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
1365 null, null, lexer.Location);
1369 syntax_error (lexer.Location, "'operator' expected");
1373 syntax_error (lexer.Location, "'operator' expected");
1377 constructor_declaration
1380 constructor_declarator
1383 Constructor c = (Constructor) $3;
1384 c.Block = (Block) $4;
1385 c.ModFlags = (int) $2;
1386 c.OptAttributes = (Attributes) $1;
1388 if ((c.ModFlags & Modifiers.STATIC) != 0){
1389 if ((c.ModFlags & Modifiers.Accessibility) != 0) {
1392 "Access modifiers are not allowed on static constructors");
1395 if (c.Initializer != null){
1398 "Static constructors can not have an explicit this or base " +
1399 "constructor invocations");
1402 if (!c.Parameters.Empty){
1404 132, c.Location, "Static constructors should not have parameters");
1408 CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
1410 current_local_parameters = null;
1414 constructor_declarator
1416 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
1418 oob_stack.Push (lexer.Location);
1420 current_local_parameters = (Parameters) $3;
1422 opt_constructor_initializer
1424 Location l = (Location) oob_stack.Pop ();
1425 $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $6, l);
1431 | SEMICOLON { $$ = null; }
1434 opt_constructor_initializer
1435 : /* empty */ { $$ = null; }
1436 | constructor_initializer
1439 constructor_initializer
1440 : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
1442 $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
1444 | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
1446 $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
1450 destructor_declaration
1451 : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
1453 if ((string) $3 != current_container.Basename){
1454 Report.Error (574, lexer.Location, "Name of destructor must match name of class");
1455 } else if (!(current_container is Class)){
1456 Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
1458 Location l = lexer.Location;
1461 if (!RootContext.StdLib && current_container.Name == "System.Object")
1462 m = Modifiers.PROTECTED | Modifiers.VIRTUAL;
1464 m = Modifiers.PROTECTED | Modifiers.OVERRIDE;
1466 Method d = new Method (
1467 "System.Void", m, "Finalize",
1468 new Parameters (null, null, l), (Attributes) $1, l);
1470 d.Block = (Block) $6;
1471 CheckDef (current_container.AddMethod (d), d.Name, d.Location);
1479 EVENT type variable_declarators SEMICOLON
1481 foreach (VariableDeclaration var in (ArrayList) $5) {
1483 Event e = new Event ((string) $4, var.identifier,
1484 var.expression_or_array_initializer,
1485 (int) $2, null, null, (Attributes) $1, lexer.Location);
1487 CheckDef (current_container.AddEvent (e), e.Name, e.Location);
1493 EVENT type member_name
1496 implicit_value_parameter_type = (string) $4;
1497 lexer.EventParsing = true;
1498 oob_stack.Push (lexer.Location);
1500 event_accessor_declarations
1502 lexer.EventParsing = false;
1506 Location loc = (Location) oob_stack.Pop ();
1508 Pair pair = (Pair) $8;
1509 Accessor add_accessor = null;
1510 Accessor rem_accessor = null;
1512 if (pair.First != null)
1513 add_accessor = (Accessor) pair.First;
1514 if (pair.Second != null)
1515 rem_accessor = (Accessor) pair.Second;
1517 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_accessor, rem_accessor,
1518 (Attributes) $1, loc);
1520 CheckDef (current_container.AddEvent (e), e.Name, loc);
1521 implicit_value_parameter_type = null;
1525 event_accessor_declarations
1526 : add_accessor_declaration remove_accessor_declaration
1528 $$ = new Pair ($1, $2);
1530 | remove_accessor_declaration add_accessor_declaration
1532 $$ = new Pair ($2, $1);
1536 add_accessor_declaration
1537 : opt_attributes ADD
1539 Parameter [] args = new Parameter [1];
1540 Parameter implicit_value_parameter = new Parameter (
1541 implicit_value_parameter_type, "value",
1542 Parameter.Modifier.NONE, null);
1544 args [0] = implicit_value_parameter;
1546 current_local_parameters = new Parameters (args, null, lexer.Location);
1547 lexer.EventParsing = false;
1551 $$ = new Accessor ((Block) $4, (Attributes) $1);
1552 lexer.EventParsing = true;
1556 remove_accessor_declaration
1557 : opt_attributes REMOVE
1559 Parameter [] args = new Parameter [1];
1560 Parameter implicit_value_parameter = new Parameter (
1561 implicit_value_parameter_type, "value",
1562 Parameter.Modifier.NONE, null);
1564 args [0] = implicit_value_parameter;
1566 current_local_parameters = new Parameters (args, null, lexer.Location);
1567 lexer.EventParsing = false;
1571 $$ = new Accessor ((Block) $4, (Attributes) $1);
1572 lexer.EventParsing = true;
1577 : opt_attributes opt_modifiers indexer_declarator
1580 IndexerDeclaration decl = (IndexerDeclaration) $3;
1582 implicit_value_parameter_type = decl.type;
1584 lexer.PropertyParsing = true;
1585 parsing_indexer = true;
1587 indexer_parameters = decl.param_list;
1588 oob_stack.Push (lexer.Location);
1590 accessor_declarations
1592 lexer.PropertyParsing = false;
1593 parsing_indexer = false;
1597 // The signature is computed from the signature of the indexer. Look
1598 // at section 3.6 on the spec
1599 Location loc = (Location) oob_stack.Pop ();
1601 IndexerDeclaration decl = (IndexerDeclaration) $3;
1602 Pair pair = (Pair) $6;
1603 Accessor get_block = (Accessor) pair.First;
1604 Accessor set_block = (Accessor) pair.Second;
1606 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
1607 get_block, set_block, (Attributes) $1, loc);
1609 // Note that there is no equivalent of CheckDef for this case
1610 // We shall handle this in semantic analysis
1612 current_container.AddIndexer (indexer);
1614 current_local_parameters = null;
1615 implicit_value_parameter_type = null;
1616 indexer_parameters = null;
1621 : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1623 Parameters pars = (Parameters) $4;
1625 if (pars.FixedParameters == null && pars.ArrayParameter == null){
1626 Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1629 $$ = new IndexerDeclaration ((string) $1, null, pars);
1631 | type qualified_identifier DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
1633 Parameters pars = (Parameters) $6;
1635 if (pars.FixedParameters == null && pars.ArrayParameter == null){
1636 Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
1638 $$ = new IndexerDeclaration ((string) $1, (string) $2, pars);
1650 Location enum_location = lexer.Location;
1652 string full_name = MakeName ((string) $4);
1653 Enum e = new Enum (current_container, (string) $5, (int) $2, full_name,
1654 (Attributes) $1, enum_location);
1656 foreach (VariableDeclaration ev in (ArrayList) $6) {
1657 Location loc = (Location) ev.Location;
1659 CheckDef (e.AddEnumMember (ev.identifier,
1660 (Expression) ev.expression_or_array_initializer,
1661 loc, ev.OptAttributes),
1662 ev.identifier, loc);
1665 e.Namespace = current_namespace;
1667 CheckDef (current_container.AddEnum (e), full_name, enum_location);
1668 RootContext.Tree.RecordDecl (full_name, e);
1674 : /* empty */ { $$ = "System.Int32"; }
1675 | COLON type { $$ = $2; }
1679 : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
1685 opt_enum_member_declarations
1686 : /* empty */ { $$ = new ArrayList (); }
1687 | enum_member_declarations opt_comma { $$ = $1; }
1690 enum_member_declarations
1691 : enum_member_declaration
1693 ArrayList l = new ArrayList ();
1698 | enum_member_declarations COMMA enum_member_declaration
1700 ArrayList l = (ArrayList) $1;
1708 enum_member_declaration
1709 : opt_attributes IDENTIFIER
1711 $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
1713 | opt_attributes IDENTIFIER
1715 $$ = lexer.Location;
1719 $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
1723 delegate_declaration
1727 IDENTIFIER OPEN_PARENS
1728 opt_formal_parameter_list
1732 Location l = lexer.Location;
1733 Delegate del = new Delegate (current_container, (string) $4, (int) $2,
1734 MakeName ((string) $5), (Parameters) $7,
1735 (Attributes) $1, l);
1737 del.Namespace = current_namespace;
1738 CheckDef (current_container.AddDelegate (del), del.Name, l);
1743 IDENTIFIER OPEN_PARENS
1744 opt_formal_parameter_list
1748 Location l = lexer.Location;
1749 Delegate del = new Delegate (
1751 "System.Void", (int) $2, MakeName ((string) $5), (Parameters) $7,
1752 (Attributes) $1, l);
1754 del.Namespace = current_namespace;
1755 CheckDef (current_container.AddDelegate (del), del.Name, l);
1760 : namespace_or_type_name
1763 namespace_or_type_name
1764 : qualified_identifier
1768 * Before you think of adding a return_type, notice that we have been
1769 * using two rules in the places where it matters (one rule using type
1770 * and another identical one that uses VOID as the return type). This
1771 * gets rid of a shift/reduce couple
1774 : type_name { /* class_type */
1776 This does interfaces, delegates, struct_types, class_types,
1777 parent classes, and more! 4.2
1791 // Note that here only unmanaged types are allowed but we
1792 // can't perform checks during this phase - we do it during
1793 // semantic analysis.
1795 $$ = (string) $1 + "*";
1799 $$ = "System.Void*";
1806 $$ = new SimpleName ((string) $1, lexer.Location);
1808 | non_expression_type rank_specifier
1810 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1812 | non_expression_type STAR
1814 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1816 | expression rank_specifiers
1818 $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
1822 $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
1829 ArrayList types = new ArrayList ();
1834 | type_list COMMA type
1836 ArrayList types = (ArrayList) $1;
1844 * replaces all the productions for isolating the various
1845 * simple types, but we need this to reuse it easily in local_variable_type
1848 : OBJECT { $$ = "System.Object"; }
1849 | STRING { $$ = "System.String"; }
1850 | BOOL { $$ = "System.Boolean"; }
1851 | DECIMAL { $$ = "System.Decimal"; }
1852 | FLOAT { $$ = "System.Single"; }
1853 | DOUBLE { $$ = "System.Double"; }
1858 : SBYTE { $$ = "System.SByte"; }
1859 | BYTE { $$ = "System.Byte"; }
1860 | SHORT { $$ = "System.Int16"; }
1861 | USHORT { $$ = "System.UInt16"; }
1862 | INT { $$ = "System.Int32"; }
1863 | UINT { $$ = "System.UInt32"; }
1864 | LONG { $$ = "System.Int64"; }
1865 | ULONG { $$ = "System.UInt64"; }
1866 | CHAR { $$ = "System.Char"; }
1867 | VOID { $$ = "System.Void"; }
1875 : type rank_specifiers
1877 $$ = (string) $1 + (string) $2;
1882 // Expressions, section 7.5
1890 | qualified_identifier
1892 string name = (string) $1;
1895 $$ = DecomposeQI (name, lexer.Location);
1897 | parenthesized_expression
1899 | invocation_expression
1903 | post_increment_expression
1904 | post_decrement_expression
1908 | checked_expression
1909 | unchecked_expression
1910 | pointer_member_access
1911 // TODO: pointer_element_access
1912 // TODO: sizeof-expression
1919 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
1920 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
1921 | NULL { $$ = NullLiteral.Null; }
1925 : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }
1926 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
1927 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
1932 object v = lexer.Value;
1935 // FIXME: Possible optimization would be to
1936 // compute the *Literal objects directly in the scanner
1939 $$ = new IntLiteral ((Int32) v);
1941 $$ = new UIntLiteral ((UInt32) v);
1943 $$ = new LongLiteral ((Int64) v);
1944 else if (v is ulong)
1945 $$ = new ULongLiteral ((UInt64) v);
1947 Console.WriteLine ("OOPS. Unexpected result from scanner");
1952 : TRUE { $$ = new BoolLiteral (true); }
1953 | FALSE { $$ = new BoolLiteral (false); }
1956 parenthesized_expression
1957 : OPEN_PARENS expression CLOSE_PARENS
1962 : primary_expression DOT IDENTIFIER
1964 $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
1966 | predefined_type DOT IDENTIFIER
1968 $$ = new MemberAccess (new SimpleName ((string) $1, lexer.Location), (string) $3, lexer.Location);
1976 invocation_expression
1977 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
1980 Location l = lexer.Location;
1981 Report.Error (1, l, "THIS IS CRAZY");
1983 $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
1988 : /* empty */ { $$ = null; }
1995 ArrayList list = new ArrayList ();
1999 | argument_list COMMA argument
2001 ArrayList list = (ArrayList) $1;
2010 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
2012 | REF variable_reference
2014 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
2016 | OUT variable_reference
2018 $$ = new Argument ((Expression) $2, Argument.AType.Out);
2023 : expression { note ("section 5.4"); $$ = $1; }
2027 : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
2029 $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
2031 | primary_expression rank_specifiers
2033 // So the super-trick is that primary_expression
2034 // can only be either a SimpleName or a MemberAccess.
2035 // The MemberAccess case arises when you have a fully qualified type-name like :
2037 // SimpleName is when you have
2040 Expression expr = (Expression) $1;
2041 if (!(expr is SimpleName || expr is MemberAccess)) {
2042 Location l = lexer.Location;
2043 Report.Error (-1, l, "Invalid Type definition");
2044 $$ = "System.Object";
2048 // So we extract the string corresponding to the SimpleName
2051 $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
2058 ArrayList list = new ArrayList ();
2062 | expression_list COMMA expression
2064 ArrayList list = (ArrayList) $1;
2073 $$ = new This (lexer.Location);
2078 : BASE DOT IDENTIFIER
2080 $$ = new BaseAccess ((string) $3, lexer.Location);
2082 | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
2084 $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
2088 post_increment_expression
2089 : primary_expression OP_INC
2091 $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
2092 (Expression) $1, lexer.Location);
2096 post_decrement_expression
2097 : primary_expression OP_DEC
2099 $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
2100 (Expression) $1, lexer.Location);
2105 : object_or_delegate_creation_expression
2106 | array_creation_expression
2109 object_or_delegate_creation_expression
2110 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
2112 $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
2116 array_creation_expression
2117 : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
2119 opt_array_initializer
2121 $$ = new ArrayCreation ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
2123 | NEW type rank_specifiers array_initializer
2125 $$ = new ArrayCreation ((string) $2, (string) $3, (ArrayList) $4, lexer.Location);
2129 Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
2149 | rank_specifiers rank_specifier
2151 $$ = (string) $2 + (string) $1;
2156 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
2158 $$ = "[" + (string) $2 + "]";
2178 | dim_separators COMMA
2180 $$ = (string) $1 + ",";
2184 opt_array_initializer
2196 : OPEN_BRACE CLOSE_BRACE
2198 ArrayList list = new ArrayList ();
2201 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
2203 $$ = (ArrayList) $2;
2207 variable_initializer_list
2208 : variable_initializer
2210 ArrayList list = new ArrayList ();
2214 | variable_initializer_list COMMA variable_initializer
2216 ArrayList list = (ArrayList) $1;
2223 : TYPEOF OPEN_PARENS type CLOSE_PARENS
2225 $$ = new TypeOf ((string) $3, lexer.Location);
2230 : SIZEOF OPEN_PARENS type CLOSE_PARENS {
2231 $$ = new SizeOf ((string) $3, lexer.Location);
2233 note ("Verify type is unmanaged");
2234 note ("if (5.8) builtin, yield constant expression");
2239 : CHECKED OPEN_PARENS expression CLOSE_PARENS
2241 $$ = new CheckedExpr ((Expression) $3);
2245 unchecked_expression
2246 : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
2248 $$ = new UnCheckedExpr ((Expression) $3);
2252 pointer_member_access
2253 : primary_expression OP_PTR IDENTIFIER
2257 deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lexer.Location);
2258 $$ = new MemberAccess (deref, (string) $3, lexer.Location);
2262 : primary_expression
2263 | BANG prefixed_unary_expression
2265 $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
2267 | TILDE prefixed_unary_expression
2269 $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
2271 | OPEN_PARENS expression CLOSE_PARENS unary_expression
2273 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2275 | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
2277 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
2282 // The idea to split this out is from Rhys' grammar
2283 // to solve the problem with casts.
2285 prefixed_unary_expression
2287 | PLUS prefixed_unary_expression
2289 $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
2291 | MINUS prefixed_unary_expression
2293 $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
2295 | OP_INC prefixed_unary_expression
2297 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2298 (Expression) $2, lexer.Location);
2300 | OP_DEC prefixed_unary_expression
2302 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2303 (Expression) $2, lexer.Location);
2305 | STAR prefixed_unary_expression
2307 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
2309 | BITWISE_AND prefixed_unary_expression
2311 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
2315 pre_increment_expression
2316 : OP_INC prefixed_unary_expression
2318 $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
2319 (Expression) $2, lexer.Location);
2323 pre_decrement_expression
2324 : OP_DEC prefixed_unary_expression
2326 $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
2327 (Expression) $2, lexer.Location);
2331 multiplicative_expression
2332 : prefixed_unary_expression
2333 | multiplicative_expression STAR prefixed_unary_expression
2335 $$ = new Binary (Binary.Operator.Multiply,
2336 (Expression) $1, (Expression) $3, lexer.Location);
2338 | multiplicative_expression DIV prefixed_unary_expression
2340 $$ = new Binary (Binary.Operator.Division,
2341 (Expression) $1, (Expression) $3, lexer.Location);
2343 | multiplicative_expression PERCENT prefixed_unary_expression
2345 $$ = new Binary (Binary.Operator.Modulus,
2346 (Expression) $1, (Expression) $3, lexer.Location);
2351 : multiplicative_expression
2352 | additive_expression PLUS multiplicative_expression
2354 $$ = new Binary (Binary.Operator.Addition,
2355 (Expression) $1, (Expression) $3, lexer.Location);
2357 | additive_expression MINUS multiplicative_expression
2359 $$ = new Binary (Binary.Operator.Subtraction,
2360 (Expression) $1, (Expression) $3, lexer.Location);
2365 : additive_expression
2366 | shift_expression OP_SHIFT_LEFT additive_expression
2368 $$ = new Binary (Binary.Operator.LeftShift,
2369 (Expression) $1, (Expression) $3, lexer.Location);
2371 | shift_expression OP_SHIFT_RIGHT additive_expression
2373 $$ = new Binary (Binary.Operator.RightShift,
2374 (Expression) $1, (Expression) $3, lexer.Location);
2378 relational_expression
2380 | relational_expression OP_LT shift_expression
2382 $$ = new Binary (Binary.Operator.LessThan,
2383 (Expression) $1, (Expression) $3, lexer.Location);
2385 | relational_expression OP_GT shift_expression
2387 $$ = new Binary (Binary.Operator.GreaterThan,
2388 (Expression) $1, (Expression) $3, lexer.Location);
2390 | relational_expression OP_LE shift_expression
2392 $$ = new Binary (Binary.Operator.LessThanOrEqual,
2393 (Expression) $1, (Expression) $3, lexer.Location);
2395 | relational_expression OP_GE shift_expression
2397 $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
2398 (Expression) $1, (Expression) $3, lexer.Location);
2400 | relational_expression IS type
2402 $$ = new Is ((Expression) $1, (string) $3, lexer.Location);
2404 | relational_expression AS type
2406 $$ = new As ((Expression) $1, (string) $3, lexer.Location);
2411 : relational_expression
2412 | equality_expression OP_EQ relational_expression
2414 $$ = new Binary (Binary.Operator.Equality,
2415 (Expression) $1, (Expression) $3, lexer.Location);
2417 | equality_expression OP_NE relational_expression
2419 $$ = new Binary (Binary.Operator.Inequality,
2420 (Expression) $1, (Expression) $3, lexer.Location);
2425 : equality_expression
2426 | and_expression BITWISE_AND equality_expression
2428 $$ = new Binary (Binary.Operator.BitwiseAnd,
2429 (Expression) $1, (Expression) $3, lexer.Location);
2433 exclusive_or_expression
2435 | exclusive_or_expression CARRET and_expression
2437 $$ = new Binary (Binary.Operator.ExclusiveOr,
2438 (Expression) $1, (Expression) $3, lexer.Location);
2442 inclusive_or_expression
2443 : exclusive_or_expression
2444 | inclusive_or_expression BITWISE_OR exclusive_or_expression
2446 $$ = new Binary (Binary.Operator.BitwiseOr,
2447 (Expression) $1, (Expression) $3, lexer.Location);
2451 conditional_and_expression
2452 : inclusive_or_expression
2453 | conditional_and_expression OP_AND inclusive_or_expression
2455 $$ = new Binary (Binary.Operator.LogicalAnd,
2456 (Expression) $1, (Expression) $3, lexer.Location);
2460 conditional_or_expression
2461 : conditional_and_expression
2462 | conditional_or_expression OP_OR conditional_and_expression
2464 $$ = new Binary (Binary.Operator.LogicalOr,
2465 (Expression) $1, (Expression) $3, lexer.Location);
2469 conditional_expression
2470 : conditional_or_expression
2471 | conditional_or_expression INTERR expression COLON expression
2473 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
2477 assignment_expression
2478 : prefixed_unary_expression ASSIGN expression
2480 $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
2482 | prefixed_unary_expression OP_MULT_ASSIGN expression
2484 Location l = lexer.Location;
2486 $$ = new CompoundAssign (
2487 Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
2489 | prefixed_unary_expression OP_DIV_ASSIGN expression
2491 Location l = lexer.Location;
2493 $$ = new CompoundAssign (
2494 Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
2496 | prefixed_unary_expression OP_MOD_ASSIGN expression
2498 Location l = lexer.Location;
2500 $$ = new CompoundAssign (
2501 Binary.Operator.Modulus, (Expression) $1, (Expression) $3, l);
2503 | prefixed_unary_expression OP_ADD_ASSIGN expression
2505 Location l = lexer.Location;
2507 $$ = new CompoundAssign (
2508 Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
2510 | prefixed_unary_expression OP_SUB_ASSIGN expression
2512 Location l = lexer.Location;
2514 $$ = new CompoundAssign (
2515 Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
2517 | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
2519 Location l = lexer.Location;
2521 $$ = new CompoundAssign (
2522 Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, l);
2524 | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
2526 Location l = lexer.Location;
2528 $$ = new CompoundAssign (
2529 Binary.Operator.RightShift, (Expression) $1, (Expression) $3, l);
2531 | prefixed_unary_expression OP_AND_ASSIGN expression
2533 Location l = lexer.Location;
2535 $$ = new CompoundAssign (
2536 Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3, l);
2538 | prefixed_unary_expression OP_OR_ASSIGN expression
2540 Location l = lexer.Location;
2542 $$ = new CompoundAssign (
2543 Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3, l);
2545 | prefixed_unary_expression OP_XOR_ASSIGN expression
2547 Location l = lexer.Location;
2549 $$ = new CompoundAssign (
2550 Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3, l);
2555 : conditional_expression
2556 | assignment_expression
2578 name = MakeName ((string) $4);
2580 new_class = new Class (current_container, name, (int) $2,
2581 (Attributes) $1, lexer.Location);
2582 current_container = new_class;
2583 current_container.Namespace = current_namespace;
2584 RootContext.Tree.RecordDecl (name, new_class);
2590 Class new_class = (Class) current_container;
2593 new_class.Bases = (ArrayList) $6;
2595 current_container = current_container.Parent;
2596 CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
2603 : /* empty */ { $$ = (int) 0; }
2609 | modifiers modifier
2614 if ((m1 & m2) != 0) {
2615 Location l = lexer.Location;
2616 Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
2618 $$ = (int) (m1 | m2);
2623 : NEW { $$ = Modifiers.NEW; }
2624 | PUBLIC { $$ = Modifiers.PUBLIC; }
2625 | PROTECTED { $$ = Modifiers.PROTECTED; }
2626 | INTERNAL { $$ = Modifiers.INTERNAL; }
2627 | PRIVATE { $$ = Modifiers.PRIVATE; }
2628 | ABSTRACT { $$ = Modifiers.ABSTRACT; }
2629 | SEALED { $$ = Modifiers.SEALED; }
2630 | STATIC { $$ = Modifiers.STATIC; }
2631 | READONLY { $$ = Modifiers.READONLY; }
2632 | VIRTUAL { $$ = Modifiers.VIRTUAL; }
2633 | OVERRIDE { $$ = Modifiers.OVERRIDE; }
2634 | EXTERN { $$ = Modifiers.EXTERN; }
2635 | VOLATILE { $$ = Modifiers.VOLATILE; }
2636 | UNSAFE { $$ = Modifiers.UNSAFE; }
2640 : /* empty */ { $$ = null; }
2641 | class_base { $$ = $1; }
2645 : COLON type_list { $$ = $2; }
2653 // A block is "contained" on the following places:
2655 // property_declaration as part of the accessor body (get/set)
2656 // operator_declaration
2657 // constructor_declaration
2658 // destructor_declaration
2659 // event_declaration as part of add_accessor_declaration or remove_accessor_declaration
2664 current_block = new Block (current_block, lexer.Location, Location.Null);
2666 opt_statement_list CLOSE_BRACE
2668 while (current_block.Implicit)
2669 current_block = current_block.Parent;
2671 current_block.SetEndLocation (lexer.Location);
2672 current_block = current_block.Parent;
2683 | statement_list statement
2687 : declaration_statement
2689 if ((Block) $1 != current_block){
2690 current_block.AddStatement ((Statement) $1);
2691 current_block = (Block) $1;
2694 | embedded_statement
2696 Statement s = (Statement) $1;
2699 current_block.AddStatement ((Statement) $1);
2707 | expression_statement
2708 | selection_statement
2709 | iteration_statement
2713 | unchecked_statement
2723 $$ = new EmptyStatement ();
2730 LabeledStatement labeled = new LabeledStatement ((string) $1);
2732 if (!current_block.AddLabel ((string) $1, labeled)){
2733 Location l = lexer.Location;
2734 Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
2736 current_block.AddStatement (labeled);
2741 declaration_statement
2742 : local_variable_declaration SEMICOLON
2744 DictionaryEntry de = (DictionaryEntry) $1;
2746 $$ = declare_local_variables ((string) de.Key, (ArrayList) de.Value, lexer.Location);
2749 | local_constant_declaration SEMICOLON
2751 DictionaryEntry de = (DictionaryEntry) $1;
2753 $$ = declare_local_constant ((string) de.Key, (VariableDeclaration) de.Value);
2758 * The following is from Rhys' grammar:
2759 * > Types in local variable declarations must be recognized as
2760 * > expressions to prevent reduce/reduce errors in the grammar.
2761 * > The expressions are converted into types during semantic analysis.
2764 : primary_expression opt_rank_specifier
2766 // FIXME: Do something smart here regarding the composition of the type.
2768 // Ok, the above "primary_expression" is there to get rid of
2769 // both reduce/reduce and shift/reduces in the grammar, it should
2770 // really just be "type_name". If you use type_name, a reduce/reduce
2771 // creeps up. If you use qualified_identifier (which is all we need
2772 // really) two shift/reduces appear.
2775 // So the super-trick is that primary_expression
2776 // can only be either a SimpleName or a MemberAccess.
2777 // The MemberAccess case arises when you have a fully qualified type-name like :
2779 // SimpleName is when you have
2782 Expression expr = (Expression) $1;
2783 if (!(expr is SimpleName || expr is MemberAccess)) {
2784 Location l = lexer.Location;
2785 Report.Error (-1, l, "Invalid Type definition");
2786 $$ = "System.Object";
2790 // So we extract the string corresponding to the SimpleName
2793 $$ = GetQualifiedIdentifier (expr) + (string) $2;
2795 | builtin_types opt_rank_specifier
2797 $$ = (string) $1 + (string) $2;
2801 local_variable_pointer_type
2802 : primary_expression STAR
2804 Expression expr = (Expression) $1;
2805 if (!(expr is SimpleName || expr is MemberAccess)) {
2806 Location l = lexer.Location;
2807 Report.Error (-1, l, "Invalid Type definition");
2808 $$ = "System.Object";
2811 $$ = GetQualifiedIdentifier (expr) + "*";
2813 | builtin_types STAR
2815 $$ = (string) $1 + "*";
2819 $$ = "System.Void*";
2821 | local_variable_pointer_type STAR
2823 $$ = (string) $1 + "*";
2827 local_variable_declaration
2828 : local_variable_type variable_declarators
2830 $$ = new DictionaryEntry ($1, $2);
2832 | local_variable_pointer_type opt_rank_specifier variable_declarators
2834 $$ = new DictionaryEntry ((string) $1 + (string) $2, $3);
2838 local_constant_declaration
2839 : CONST local_variable_type constant_declarator
2841 $$ = new DictionaryEntry ($2, $3);
2845 expression_statement
2846 : statement_expression SEMICOLON
2853 // We have to do the wrapping here and not in the case above,
2854 // because statement_expression is used for example in for_statement
2856 statement_expression
2857 : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2858 | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2859 | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2860 | post_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2861 | post_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2862 | pre_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2863 | pre_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
2865 Report.Error (1002, lexer.Location, "Expecting `;'");
2869 object_creation_expression
2870 : object_or_delegate_creation_expression
2871 { note ("complain if this is a delegate maybe?"); }
2880 : if_statement_open if_statement_rest
2889 oob_stack.Push (lexer.Location);
2894 : boolean_expression CLOSE_PARENS
2897 Location l = (Location) oob_stack.Pop ();
2899 $$ = new If ((Expression) $1, (Statement) $3, l);
2901 if (RootContext.WarningLevel >= 3){
2902 if ($3 is EmptyStatement)
2903 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
2907 | boolean_expression CLOSE_PARENS
2908 embedded_statement ELSE embedded_statement
2910 Location l = (Location) oob_stack.Pop ();
2912 $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l);
2917 : SWITCH OPEN_PARENS
2919 oob_stack.Push (lexer.Location);
2921 expression CLOSE_PARENS
2924 $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
2940 Report.Error (1522, lexer.Location, "Empty switch block");
2948 ArrayList sections = new ArrayList ();
2953 | switch_sections switch_section
2955 ArrayList sections = (ArrayList) $1;
2965 current_block = new Block (current_block);
2969 while (current_block.Implicit)
2970 current_block = current_block.Parent;
2971 $$ = new SwitchSection ((ArrayList) $1, current_block);
2972 current_block = current_block.Parent;
2979 ArrayList labels = new ArrayList ();
2984 | switch_labels switch_label
2986 ArrayList labels = (ArrayList) ($1);
2994 : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
2995 | DEFAULT COLON { $$ = new SwitchLabel (null, lexer.Location); }
2998 1523, lexer.Location,
2999 "The keyword case or default must precede code in switch block");
3013 oob_stack.Push (lexer.Location);
3015 boolean_expression CLOSE_PARENS embedded_statement
3017 Location l = (Location) oob_stack.Pop ();
3018 $$ = new While ((Expression) $4, (Statement) $6, l);
3020 if (RootContext.WarningLevel >= 3){
3021 if ($6 is EmptyStatement)
3022 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3028 : DO embedded_statement
3029 WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
3031 $$ = new Do ((Statement) $2, (Expression) $5, lexer.Location);
3037 opt_for_initializer SEMICOLON
3039 Block assign_block = new Block (current_block);
3040 current_block = assign_block;
3042 if ($3 is DictionaryEntry){
3043 DictionaryEntry de = (DictionaryEntry) $3;
3045 string type = (string) de.Key;
3046 ArrayList var_declarators = (ArrayList) de.Value;
3048 foreach (VariableDeclaration decl in var_declarators){
3052 vi = current_block.AddVariable (
3053 type, decl.identifier, current_local_parameters, decl.Location);
3055 Report.Error (128, decl.Location,
3056 "A local variable `" + decl.identifier +
3057 "' is already defined in this scope");
3059 Location l = lexer.Location;
3061 if (decl.expression_or_array_initializer is Expression){
3062 expr = (Expression) decl.expression_or_array_initializer;
3066 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3068 string base_type = type.Substring (0, type.IndexOf ("["));
3069 string rank = type.Substring (type.IndexOf ("["));
3071 expr = new ArrayCreation (base_type, rank, init, decl.Location);
3074 LocalVariableReference var;
3075 var = new LocalVariableReference (
3076 assign_block, decl.identifier, l);
3078 Assign a = new Assign (var, expr, decl.Location);
3080 assign_block.AddStatement (new StatementExpression (a, lexer.Location));
3086 oob_stack.Push (lexer.Location);
3088 opt_for_condition SEMICOLON
3089 opt_for_iterator CLOSE_PARENS
3092 Location l = (Location) oob_stack.Pop ();
3094 For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
3096 if (RootContext.WarningLevel >= 3){
3097 if ($10 is EmptyStatement)
3098 Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
3101 current_block.AddStatement (f);
3102 while (current_block.Implicit)
3103 current_block = current_block.Parent;
3105 current_block = current_block.Parent;
3110 : /* empty */ { $$ = new EmptyStatement (); }
3115 : local_variable_declaration
3116 | statement_expression_list
3120 : /* empty */ { $$ = null; }
3121 | boolean_expression
3125 : /* empty */ { $$ = new EmptyStatement (); }
3130 : statement_expression_list
3133 statement_expression_list
3134 : statement_expression
3136 // CHANGE: was `null'
3137 Block b = new Block (current_block, true);
3139 b.AddStatement ((Statement) $1);
3142 | statement_expression_list COMMA statement_expression
3144 Block b = (Block) $1;
3146 b.AddStatement ((Statement) $3);
3152 : FOREACH OPEN_PARENS type IDENTIFIER IN
3154 oob_stack.Push (lexer.Location);
3156 expression CLOSE_PARENS
3158 oob_stack.Push (current_block);
3160 Block foreach_block = new Block (current_block, true);
3161 LocalVariableReference v;
3162 Location l = lexer.Location;
3165 vi = foreach_block.AddVariable ((string) $3, (string) $4, current_local_parameters, l);
3169 128, l, "A local variable `" + (string) $4 + "' is already "+
3170 "defined in this scope");
3173 v = new LocalVariableReference (foreach_block, (string) $4, l);
3174 current_block = foreach_block;
3177 oob_stack.Push (current_block);
3181 Block foreach_block = (Block) oob_stack.Pop ();
3182 LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
3183 Block prev_block = (Block) oob_stack.Pop ();
3184 Location l = (Location) oob_stack.Pop ();
3186 current_block = prev_block;
3188 Foreach f = new Foreach ((string) $3, v, (Expression) $7, (Statement) $10, l);
3189 foreach_block.AddStatement (f);
3197 | continue_statement
3206 $$ = new Break (lexer.Location);
3211 : CONTINUE SEMICOLON
3213 $$ = new Continue (lexer.Location);
3218 : GOTO IDENTIFIER SEMICOLON
3220 $$ = new Goto (current_block, (string) $2, lexer.Location);
3222 | GOTO CASE constant_expression SEMICOLON
3224 $$ = new GotoCase ((Expression) $3, lexer.Location);
3226 | GOTO DEFAULT SEMICOLON
3228 $$ = new GotoDefault (lexer.Location);
3233 : RETURN opt_expression SEMICOLON
3235 $$ = new Return ((Expression) $2, lexer.Location);
3240 : THROW opt_expression SEMICOLON
3242 $$ = new Throw ((Expression) $2, lexer.Location);
3252 : TRY block catch_clauses
3255 ArrayList s = new ArrayList ();
3257 foreach (Catch cc in (ArrayList) $3) {
3258 if (cc.Type == null)
3264 // Now s contains the list of specific catch clauses
3265 // and g contains the general one.
3267 $$ = new Try ((Block) $2, s, g, null);
3269 | TRY block opt_catch_clauses FINALLY block
3272 ArrayList s = new ArrayList ();
3273 ArrayList catch_list = (ArrayList) $3;
3275 if (catch_list != null){
3276 foreach (Catch cc in catch_list) {
3277 if (cc.Type == null)
3284 $$ = new Try ((Block) $2, s, g, (Block) $5);
3288 Report.Error (1524, lexer.Location, "Expected catch or finally");
3293 : /* empty */ { $$ = null; }
3300 ArrayList l = new ArrayList ();
3305 | catch_clauses catch_clause
3307 ArrayList l = (ArrayList) $1;
3315 : /* empty */ { $$ = null; }
3320 : CATCH opt_catch_args
3322 string type = null, id = null;
3325 DictionaryEntry cc = (DictionaryEntry) $2;
3326 type = (string) cc.Key;
3327 id = (string) cc.Value;
3330 ArrayList one = new ArrayList ();
3331 Location loc = lexer.Location;
3333 one.Add (new VariableDeclaration (id, null, loc));
3336 current_block = new Block (current_block);
3337 Block b = declare_local_variables (type, one, loc);
3344 string type = null, id = null;
3347 DictionaryEntry cc = (DictionaryEntry) $2;
3348 type = (string) cc.Key;
3349 id = (string) cc.Value;
3352 while (current_block != (Block) $1)
3353 current_block = current_block.Parent;
3358 $$ = new Catch (type, id , (Block) $4, lexer.Location);
3363 : /* empty */ { $$ = null; }
3368 : OPEN_PARENS type opt_identifier CLOSE_PARENS
3370 $$ = new DictionaryEntry ($2, $3);
3377 $$ = new Checked ((Block) $2);
3384 $$ = new Unchecked ((Block) $2);
3391 if (!RootContext.Unsafe){
3392 Report.Error (227, lexer.Location,
3393 "Unsafe code can only be used if --unsafe is used");
3396 $$ = new Unsafe ((Block) $3);
3402 pointer_type fixed_pointer_declarators
3405 Block assign_block = new Block (current_block, true);
3406 ArrayList list = (ArrayList) $4;
3407 string type = (string) $3;
3408 Location l = lexer.Location;
3409 int top = list.Count;
3411 for (int i = 0; i < top; i++){
3412 Pair p = (Pair) list [i];
3415 v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
3418 128, l, "A local variable `" + (string) p.First + "' is already "+
3419 "defined in this scope");
3425 current_block.AddStatement (assign_block);
3426 current_block = assign_block;
3427 oob_stack.Push (assign_block);
3432 Location l = (Location) oob_stack.Pop ();
3433 Block assign_block = (Block) oob_stack.Pop ();
3435 ArrayList list = (ArrayList) $4;
3436 int top = list.Count;
3438 $$ = new Fixed ((string) $3, (ArrayList) $4, (Statement) $7, l);
3442 fixed_pointer_declarators
3443 : fixed_pointer_declarator {
3444 ArrayList declarators = new ArrayList ();
3445 declarators.Add ($1);
3448 | fixed_pointer_declarators COMMA fixed_pointer_declarator
3450 ArrayList declarators = (ArrayList) $1;
3451 declarators.Add ($3);
3456 fixed_pointer_declarator
3457 : IDENTIFIER ASSIGN expression
3459 $$ = new Pair ($1, $3);
3464 : LOCK OPEN_PARENS expression CLOSE_PARENS
3470 $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
3475 : USING OPEN_PARENS resource_acquisition CLOSE_PARENS
3477 Block assign_block = new Block (current_block);
3478 current_block = assign_block;
3480 oob_stack.Push (lexer.Location);
3482 if ($3 is DictionaryEntry){
3483 DictionaryEntry de = (DictionaryEntry) $3;
3484 Location l = lexer.Location;
3486 string type = (string) de.Key;
3487 ArrayList var_declarators = (ArrayList) de.Value;
3489 foreach (VariableDeclaration decl in var_declarators){
3490 if (current_block.AddVariable (
3491 type, decl.identifier,
3492 current_local_parameters, decl.Location) == null){
3493 Report.Error (128, decl.Location,
3494 "A local variable `" + decl.identifier + "' is already" +
3495 "defined in this scope");
3499 ArrayList vars = new ArrayList ();
3501 foreach (VariableDeclaration decl in var_declarators){
3504 if (decl.expression_or_array_initializer is Expression){
3505 expr = (Expression) decl.expression_or_array_initializer;
3509 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3511 string base_type = type.Substring (0, type.IndexOf ("["));
3512 string rank = type.Substring (type.IndexOf ("["));
3514 expr = new ArrayCreation (base_type, rank, init, decl.Location);
3517 LocalVariableReference var;
3520 var = new LocalVariableReference (assign_block, decl.identifier, l);
3521 vi = var.VariableInfo;
3524 // This is so that it is not a warning on using variables
3527 vars.Add (new DictionaryEntry (var, expr));
3529 // Assign a = new Assign (var, expr, decl.Location);
3530 // assign_block.AddStatement (new StatementExpression (a, lexer.Location));
3532 $3 = new DictionaryEntry (type, vars);
3537 Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
3538 current_block.AddStatement (u);
3539 while (current_block.Implicit)
3540 current_block = current_block.Parent;
3542 current_block = current_block.Parent;
3546 resource_acquisition
3547 : local_variable_declaration
3554 // A class used to pass around variable declarations and constants
3556 public class VariableDeclaration {
3557 public string identifier;
3558 public object expression_or_array_initializer;
3559 public Location Location;
3560 public Attributes OptAttributes;
3562 public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs)
3564 this.identifier = id;
3565 this.expression_or_array_initializer = eoai;
3567 this.OptAttributes = opt_attrs;
3570 public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
3576 // A class used to hold info about an indexer declarator
3579 public class IndexerDeclaration {
3581 public string interface_type;
3582 public Parameters param_list;
3584 public IndexerDeclaration (string type, string interface_type, Parameters param_list)
3587 this.interface_type = interface_type;
3588 this.param_list = param_list;
3593 // A class used to hold info about an operator declarator
3596 public class OperatorDeclaration {
3597 public Operator.OpType optype;
3598 public string ret_type;
3599 public string arg1type;
3600 public string arg1name;
3601 public string arg2type;
3602 public string arg2name;
3603 public Location location;
3605 public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
3606 string arg2type, string arg2name, Location location)
3609 this.ret_type = ret_type;
3610 this.arg1type = arg1type;
3611 this.arg1name = arg1name;
3612 this.arg2type = arg2type;
3613 this.arg2name = arg2name;
3614 this.location = location;
3620 // Given the @class_name name, it creates a fully qualified name
3621 // based on the containing declaration space
3624 MakeName (string class_name)
3626 string ns = current_namespace.Name;
3627 string container_name = current_container.Name;
3629 if (container_name == ""){
3631 return ns + "." + class_name;
3635 return container_name + "." + class_name;
3639 // Used to report back to the user the result of a declaration
3640 // in the current declaration space
3643 CheckDef (AdditionResult result, string name, Location l)
3645 if (result == AdditionResult.Success)
3649 case AdditionResult.NameExists:
3650 Report.Error (102, l, "The container `" + current_container.Name +
3651 "' already contains a definition for `"+
3657 // This is handled only for static Constructors, because
3658 // in reality we handle these by the semantic analysis later
3660 case AdditionResult.MethodExists:
3662 111, l, "Class `"+current_container.Name+
3663 "' already defines a member called '" +
3664 name + "' with the same parameter types (more than one default constructor)");
3667 case AdditionResult.EnclosingClash:
3668 Report.Error (542, l, "Member names cannot be the same as their enclosing type");
3671 case AdditionResult.NotAConstructor:
3672 Report.Error (1520, l, "Class, struct, or interface method must have a return type");
3678 CheckDef (bool result, string name, Location l)
3682 CheckDef (AdditionResult.NameExists, name, l);
3686 // This routine should be removed soon. I am in the process of making
3687 // changes to never keep anything but SimpleNames during parsing, as
3688 // that breaks some kinds of code (documented in the ChangeLog).
3691 SimpleLookup (string name, Location loc)
3694 // we need to check against current_block not being null
3695 // as `expression' is allowed in argument_lists, which
3696 // do not exist inside a block.
3699 if (current_local_parameters != null){
3701 Parameter par = current_local_parameters.GetParameterByName (name, out idx);
3703 return new ParameterReference (current_local_parameters, idx, name);
3709 Expression DecomposeQI (string name, Location loc)
3713 if (name.IndexOf ('.') == -1){
3714 o = SimpleLookup (name, loc);
3716 return new SimpleName (name, loc);
3719 int pos = name.LastIndexOf (".");
3720 string left = name.Substring (0, pos);
3721 string right = name.Substring (pos + 1);
3723 o = DecomposeQI (left, loc);
3724 return new MemberAccess (o, right, loc);
3729 // This method is used to get at the complete string representation of
3730 // a fully-qualified type name, hiding inside a MemberAccess ;-)
3731 // This is necessary because local_variable_type admits primary_expression
3732 // as the type of the variable. So we do some extra checking
3734 string GetQualifiedIdentifier (Expression expr)
3736 if (expr is SimpleName)
3737 return ((SimpleName)expr).Name;
3738 else if (expr is MemberAccess)
3739 return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
3741 throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
3745 Block declare_local_variables (string type, ArrayList variable_declarators, Location loc)
3747 Block implicit_block;
3748 ArrayList inits = null;
3751 // We use the `Used' property to check whether statements
3752 // have been added to the current block. If so, we need
3753 // to create another block to contain the new declaration
3754 // otherwise, as an optimization, we use the same block to
3755 // add the declaration.
3757 // FIXME: A further optimization is to check if the statements
3758 // that were added were added as part of the initialization
3759 // below. In which case, no other statements have been executed
3760 // and we might be able to reduce the number of blocks for
3761 // situations like this:
3763 // int j = 1; int k = j + 1;
3765 if (current_block.Used)
3766 implicit_block = new Block (current_block, true, loc, Location.Null);
3768 implicit_block = current_block;
3770 foreach (VariableDeclaration decl in variable_declarators){
3772 if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
3773 if (decl.expression_or_array_initializer != null){
3775 inits = new ArrayList ();
3779 Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3780 "' is already defined in this scope");
3785 return implicit_block;
3787 foreach (VariableDeclaration decl in inits){
3791 if (decl.expression_or_array_initializer is Expression){
3792 expr = (Expression) decl.expression_or_array_initializer;
3795 ArrayList init = (ArrayList) decl.expression_or_array_initializer;
3797 string base_type = type.Substring (0, type.IndexOf ("["));
3798 string rank = type.Substring (type.IndexOf ("["));
3800 expr = new ArrayCreation (base_type, rank, init, decl.Location);
3804 LocalVariableReference var;
3805 var = new LocalVariableReference (implicit_block, decl.identifier, loc);
3807 assign = new Assign (var, expr, decl.Location);
3809 implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
3812 return implicit_block;
3815 Block declare_local_constant (string type, VariableDeclaration decl)
3817 Block implicit_block;
3819 if (current_block.Used)
3820 implicit_block = new Block (current_block, true);
3822 implicit_block = current_block;
3824 if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
3825 current_local_parameters, decl.Location))){
3826 Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
3827 "' is already defined in this scope");
3830 return implicit_block;
3833 void CheckAttributeTarget (string a)
3837 case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
3841 Location l = lexer.Location;
3842 Report.Error (658, l, "`" + a + "' is an invalid attribute target");
3848 void CheckUnaryOperator (Operator.OpType op)
3852 case Operator.OpType.LogicalNot:
3853 case Operator.OpType.OnesComplement:
3854 case Operator.OpType.Increment:
3855 case Operator.OpType.Decrement:
3856 case Operator.OpType.True:
3857 case Operator.OpType.False:
3858 case Operator.OpType.Addition:
3859 case Operator.OpType.Subtraction:
3864 Location l = lexer.Location;
3865 Report.Error (1019, l, "Overloadable unary operator expected");
3871 void CheckBinaryOperator (Operator.OpType op)
3875 case Operator.OpType.Addition:
3876 case Operator.OpType.Subtraction:
3877 case Operator.OpType.Multiply:
3878 case Operator.OpType.Division:
3879 case Operator.OpType.Modulus:
3880 case Operator.OpType.BitwiseAnd:
3881 case Operator.OpType.BitwiseOr:
3882 case Operator.OpType.ExclusiveOr:
3883 case Operator.OpType.LeftShift:
3884 case Operator.OpType.RightShift:
3885 case Operator.OpType.Equality:
3886 case Operator.OpType.Inequality:
3887 case Operator.OpType.GreaterThan:
3888 case Operator.OpType.LessThan:
3889 case Operator.OpType.GreaterThanOrEqual:
3890 case Operator.OpType.LessThanOrEqual:
3894 Location l = lexer.Location;
3895 Report.Error (1020, l, "Overloadable binary operator expected");
3901 void syntax_error (Location l, string msg)
3903 Report.Error (1003, l, "Syntax error, " + msg);
3906 void output (string s)
3908 Console.WriteLine (s);
3911 void note (string s)
3913 // Used to put annotations
3918 public Tokenizer Lexer {
3924 public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
3926 current_namespace = new Namespace (null, "");
3929 current_container = RootContext.Tree.Types;
3930 current_container.Namespace = current_namespace;
3931 oob_stack = new Stack ();
3933 lexer = new Tokenizer (input, name, defines);
3936 public override void parse ()
3939 if (yacc_verbose_flag)
3940 yyparse (lexer, new yydebug.yyDebugSimple ());
3943 } catch (Exception e){
3944 // Please do not remove this, it is used during debugging
3947 Console.WriteLine (lexer.location + " : Parsing error ");
3948 Console.WriteLine (e);