3 // cs-parser.jay: The Parser for the C# compiler
\r
5 // Author: Miguel de Icaza (miguel@gnu.org)
\r
7 // Licensed under the terms of the GNU GPL
\r
9 // (C) 2001 Ximian, Inc (http://www.ximian.com)
\r
12 // (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM
\r
13 // And come to think of it, it is not that great, it duplicates a lot of code
\r
14 // for something which is not really needed. We still have piles of typecasts
\r
15 // anwyays (due to the nature of the stack being a collection of Objects).
\r
17 // (2) Figure out why error productions dont work. `type-declaration' is a
\r
18 // great spot to put an `error' because you can reproduce it with this input:
\r
21 // (3) Move Modifier checking from each object into the parser itself, that will
\r
22 // get rid of the global "error" symbol that we use now to report errors.
\r
23 // We still need to pass a pointer to the tree.ErrorHandler, but that is a
\r
32 using System.Collections;
\r
37 public class CSharpParser {
\r
38 static int global_errors;
\r
40 Namespace current_namespace;
\r
41 TypeContainer current_container;
\r
44 // Current block is used to add statements as we find
\r
48 Block current_block;
\r
51 // Current interface is used by the various declaration
\r
52 // productions in the interface declaration to "add"
\r
53 // the interfaces as we find them.
\r
55 Interface current_interface;
\r
58 // This is used by the unary_expression code to resolve
\r
59 // a name against a parameter.
\r
61 Parameters current_local_parameters;
\r
64 // Using during property parsing to describe the implicit
\r
65 // value parameter that is passed to the "set" accesor
\r
68 Parameter [] implicit_value_parameters;
\r
71 // Used to determine if we are parsing the get/set pair
\r
72 // of an indexer or a property
\r
74 bool parsing_indexer;
\r
77 // Used to record all types defined
\r
82 // Name of the file we are parsing
\r
85 // Input stream to parse from.
\r
86 public System.IO.Stream input;
\r
91 %token NONE /* This token is never returned by our lexer */
\r
92 %token ERROR // This is used not by the parser, but by the tokenizer.
\r
96 *These are the C# keywords
\r
176 /* C# keywords which are not really keywords */
\r
180 /* C# single character operators/punctuation. */
\r
181 %token OPEN_BRACE "{"
\r
182 %token CLOSE_BRACE "}"
\r
183 %token OPEN_BRACKET "["
\r
184 %token CLOSE_BRACKET "]"
\r
185 %token OPEN_PARENS "("
\r
186 %token CLOSE_PARENS ")"
\r
190 %token SEMICOLON ";"
\r
199 %token BITWISE_AND "&"
\r
200 %token BITWISE_OR "|"
\r
207 /* C# multi-character operators. */
\r
210 %token OP_SHIFT_LEFT "<<"
\r
211 %token OP_SHIFT_RIGHT ">>"
\r
218 %token OP_MULT_ASSIGN "*="
\r
219 %token OP_DIV_ASSIGN "/="
\r
220 %token OP_MOD_ASSIGN "%="
\r
221 %token OP_ADD_ASSIGN "+="
\r
222 %token OP_SUB_ASSIGN "-="
\r
223 %token OP_SHIFT_LEFT_ASSIGN "<<="
\r
224 %token OP_SHIFT_RIGHT_ASSIGN ">>="
\r
225 %token OP_AND_ASSIGN "&="
\r
226 %token OP_XOR_ASSIGN "^="
\r
227 %token OP_OR_ASSIGN "|="
\r
231 %token LITERAL_INTEGER "int literal"
\r
232 %token LITERAL_FLOAT "float literal"
\r
233 %token LITERAL_DOUBLE "double literal"
\r
234 %token LITERAL_DECIMAL "decimal literal"
\r
235 %token LITERAL_CHARACTER "character literal"
\r
236 %token LITERAL_STRING "string literal"
\r
240 /* Add precedence rules to solve dangling else s/r conflict */
\r
249 %left OP_SHIFT_LEFT OP_SHIFT_RIGHT
\r
251 %left STAR DIV PERCENT
\r
252 %right BANG CARRET UMINUS
\r
253 %nonassoc OP_INC OP_DEC
\r
255 %left OPEN_BRACKET OPEN_BRACE
\r
259 %start compilation_unit
\r
260 /*%start namespace_declaration */
\r
264 : opt_using_directives opt_attributes opt_namespace_member_declarations
\r
267 // At some point check that using only comes *before* any namespaces
\r
273 | using_directives using_directive
\r
277 : using_alias_directive
\r
278 | using_namespace_directive
\r
281 using_alias_directive
\r
282 : USING IDENTIFIER ASSIGN
\r
283 namespace_or_type_name SEMICOLON {
\r
287 using_namespace_directive
\r
288 : USING namespace_name SEMICOLON
\r
290 current_namespace.Using ((string) $2);
\r
294 namespace_declarations
\r
295 : namespace_declaration
\r
296 | namespace_declarations namespace_declaration
\r
298 namespace_declaration
\r
299 : NAMESPACE qualified_identifier
\r
301 current_namespace = new Namespace (current_namespace, (string) $2);
\r
303 namespace_body opt_semicolon
\r
305 current_namespace = current_namespace.Parent;
\r
319 qualified_identifier
\r
321 | qualified_identifier DOT IDENTIFIER {
\r
322 $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
\r
327 : namespace_or_type_name
\r
332 opt_using_directives
\r
333 opt_namespace_member_declarations
\r
338 opt_using_directives
\r
343 opt_namespace_member_declarations
\r
345 | namespace_member_declarations
\r
348 namespace_member_declarations
\r
349 : namespace_member_declaration
\r
350 | namespace_member_declarations namespace_member_declaration
\r
353 namespace_member_declaration
\r
360 Class c = (Class) $1;
\r
361 mod_flags = c.ModFlags;
\r
363 } else if ($1 is Struct){
\r
364 Struct s = (Struct) $1;
\r
365 mod_flags = s.ModFlags;
\r
371 // We remove this error until we can
\r
372 //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
\r
373 // error (1527, "Namespace elements cant be explicitly " +
\r
374 // "declared private or protected in `" + name + "'");
\r
377 | namespace_declaration
\r
381 : class_declaration
\r
382 | struct_declaration
\r
383 | interface_declaration
\r
384 | enum_declaration
\r
385 | delegate_declaration // finishme
\r
393 | attribute_section opt_attributes
\r
398 opt_attribute_target_specifier attribute_list
\r
399 /* FIXME: opt_comma */
\r
403 opt_attribute_target_specifier
\r
405 | attribute_target_specifier
\r
408 attribute_target_specifier
\r
409 : attribute_target COLON
\r
414 // if (Collection.Contains ($$))... FIXME
\r
415 note ("Allows: assembly, field, method, module, param, property, type");
\r
423 | attribute_list COMMA attribute
\r
428 | opt_attribute_arguments
\r
432 : type_name { /* reserved attribute name or identifier: 17.4 */ }
\r
435 opt_attribute_arguments
\r
437 | OPEN_PARENS attribute_arguments CLOSE_PARENS
\r
440 attribute_arguments
\r
442 | attribute_arguments COMMA expression
\r
446 opt_dimension_separators
\r
448 | dimension_separators
\r
451 dimension_separators
\r
453 | dimension_separators COMMA
\r
457 : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
\r
460 opt_class_member_declarations
\r
462 | class_member_declarations
\r
465 class_member_declarations
\r
466 : class_member_declaration
\r
467 | class_member_declarations
\r
468 class_member_declaration
\r
471 class_member_declaration
\r
472 : constant_declaration // done
\r
473 | field_declaration // done
\r
474 | method_declaration // done
\r
475 | property_declaration // done
\r
476 | event_declaration // done
\r
477 | indexer_declaration // done
\r
478 | operator_declaration // finishme
\r
479 | constructor_declaration // done
\r
480 | destructor_declaration // done
\r
490 string full_struct_name = MakeName ((string) $4);
\r
492 new_struct = new Struct (rc, current_container, full_struct_name, (int) $2);
\r
493 current_container = new_struct;
\r
494 current_container.Namespace = current_namespace;
\r
495 tree.RecordStruct (full_struct_name, new_struct);
\r
497 opt_struct_interfaces
\r
501 Struct new_struct = (Struct) current_container;
\r
503 current_container = current_container.Parent;
\r
504 CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
\r
509 opt_struct_interfaces
\r
511 | struct_interfaces
\r
516 | struct_interfaces struct_interface
\r
524 : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
\r
527 opt_struct_member_declarations
\r
529 | struct_member_declarations
\r
532 struct_member_declarations
\r
533 : struct_member_declaration
\r
534 | struct_member_declarations struct_member_declaration
\r
537 struct_member_declaration
\r
538 : constant_declaration
\r
539 | field_declaration
\r
540 | method_declaration
\r
541 | property_declaration
\r
542 | event_declaration
\r
543 | indexer_declaration
\r
544 | operator_declaration
\r
545 | constructor_declaration
\r
549 constant_declaration
\r
554 constant_declarators
\r
557 Modifiers.Check (Constant.AllowedModifiers, (int) $2, Modifiers.PRIVATE);
\r
559 foreach (DictionaryEntry constant in (ArrayList) $5){
\r
560 Constant c = new Constant (
\r
561 (string) $4, (string) constant.Key,
\r
562 (Expression) constant.Value, (int) $2);
\r
564 CheckDef (current_container.AddConstant (c), c.Name);
\r
569 constant_declarators
\r
570 : constant_declarator
\r
572 ArrayList constants = new ArrayList ();
\r
573 constants.Add ($1);
\r
576 | constant_declarators COMMA constant_declarator
\r
578 ArrayList constants = (ArrayList) $1;
\r
580 constants.Add ($3);
\r
584 constant_declarator
\r
585 : IDENTIFIER ASSIGN constant_expression {
\r
586 $$ = new DictionaryEntry ($1, $3);
\r
594 variable_declarators
\r
597 string type = (string) $3;
\r
598 int mod = (int) $2;
\r
600 foreach (VariableDeclaration var in (ArrayList) $4){
\r
601 Field field = new Field (type, mod, var.identifier,
\r
602 var.expression_or_array_initializer);
\r
604 CheckDef (current_container.AddField (field), field.Name);
\r
610 variable_declarators
\r
611 : variable_declarator
\r
613 ArrayList decl = new ArrayList ();
\r
617 | variable_declarators COMMA variable_declarator
\r
619 ArrayList decls = (ArrayList) $1;
\r
625 variable_declarator
\r
626 : IDENTIFIER ASSIGN variable_initializer
\r
628 $$ = new VariableDeclaration ((string) $1, $3);
\r
632 $$ = new VariableDeclaration ((string) $1, null);
\r
636 variable_initializer
\r
639 ArrayList list = new ArrayList ();
\r
643 | array_initializer
\r
653 Method method = (Method) $1;
\r
655 method.Block = (Block) $2;
\r
656 CheckDef (current_container.AddMethod (method), method.Name);
\r
658 current_local_parameters = null;
\r
667 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
669 Method method = new Method ((string) $3, (int) $2, (string) $4, (Parameters) $6);
\r
671 current_local_parameters = (Parameters) $6;
\r
679 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
681 Method method = new Method ("System.Void", (int) $2, (string) $4, (Parameters) $6);
\r
683 current_local_parameters = (Parameters) $6;
\r
690 | SEMICOLON { $$ = null; }
\r
693 opt_formal_parameter_list
\r
694 : /* empty */ { $$ = new Parameters (null, null); }
\r
695 | formal_parameter_list
\r
698 formal_parameter_list
\r
699 : fixed_parameters
\r
701 ArrayList pars_list = (ArrayList) $1;
\r
703 Parameter [] pars = new Parameter [pars_list.Count];
\r
704 pars_list.CopyTo (pars);
\r
706 $$ = new Parameters (pars, null);
\r
708 | fixed_parameters COMMA parameter_array
\r
710 ArrayList pars_list = (ArrayList) $1;
\r
712 Parameter [] pars = new Parameter [pars_list.Count];
\r
713 pars_list.CopyTo (pars);
\r
715 $$ = new Parameters (pars, (Parameter) $3);
\r
719 $$ = new Parameters (null, (Parameter) $1);
\r
726 ArrayList pars = new ArrayList ();
\r
731 | fixed_parameters COMMA fixed_parameter
\r
733 ArrayList pars = (ArrayList) $1;
\r
742 opt_parameter_modifier
\r
746 $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2);
\r
750 opt_parameter_modifier
\r
751 : /* empty */ { $$ = Parameter.Modifier.NONE; }
\r
752 | parameter_modifier
\r
756 : REF { $$ = Parameter.Modifier.REF; }
\r
757 | OUT { $$ = Parameter.Modifier.OUT; }
\r
761 : opt_attributes PARAMS type IDENTIFIER
\r
763 $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS);
\r
764 note ("type must be a single-dimension array type");
\r
769 : IDENTIFIER { $$ = $1.ToString (); }
\r
770 | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
\r
773 property_declaration
\r
779 Parameter implicit_value_parameter;
\r
780 implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE);
\r
782 lexer.properties = true;
\r
784 implicit_value_parameters = new Parameter [1];
\r
785 implicit_value_parameters [0] = implicit_value_parameter;
\r
787 accessor_declarations
\r
789 lexer.properties = false;
\r
794 DictionaryEntry pair = (DictionaryEntry) $7;
\r
795 Block get_block = null;
\r
796 Block set_block = null;
\r
798 if (pair.Key != null)
\r
799 get_block = (Block) pair.Key;
\r
800 if (pair.Value != null)
\r
801 set_block = (Block) pair.Value;
\r
803 prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block);
\r
805 CheckDef (current_container.AddProperty (prop), prop.Name);
\r
806 implicit_value_parameters = null;
\r
810 accessor_declarations
\r
811 : get_accessor_declaration opt_set_accessor_declaration
\r
813 $$ = new DictionaryEntry ($1, $2);
\r
815 | set_accessor_declaration opt_get_accessor_declaration
\r
817 $$ = new DictionaryEntry ($2, $1);
\r
821 opt_get_accessor_declaration
\r
822 : /* empty */ { $$ = null; }
\r
823 | get_accessor_declaration
\r
826 opt_set_accessor_declaration
\r
827 : /* empty */ { $$ = null; }
\r
828 | set_accessor_declaration
\r
831 get_accessor_declaration
\r
832 : opt_attributes GET
\r
834 // If this is not the case, then current_local_parameters has already
\r
835 // been set in indexer_declaration
\r
836 if (parsing_indexer == false)
\r
837 current_local_parameters = new Parameters (implicit_value_parameters, null);
\r
844 current_local_parameters = null;
\r
848 set_accessor_declaration
\r
849 : opt_attributes SET
\r
851 if (parsing_indexer == false)
\r
852 current_local_parameters = new Parameters (implicit_value_parameters, null);
\r
857 current_local_parameters = null;
\r
863 | SEMICOLON { $$ = new Block (null); }
\r
866 interface_declaration
\r
869 INTERFACE IDENTIFIER
\r
871 Interface new_interface;
\r
872 string full_interface_name = MakeName ((string) $4);
\r
874 new_interface = new Interface (current_container, full_interface_name, (int) $2);
\r
875 if (current_interface != null)
\r
876 error (-2, "Internal compiler error: interface inside interface");
\r
877 current_interface = new_interface;
\r
878 tree.RecordInterface (full_interface_name, new_interface);
\r
883 Interface new_interface = (Interface) current_interface;
\r
886 new_interface.Bases = (ArrayList) $6;
\r
888 current_interface = null;
\r
889 CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
\r
894 : /* empty */ { $$ = null; }
\r
899 : COLON interface_type_list { $$ = $2; }
\r
902 interface_type_list
\r
905 ArrayList interfaces = new ArrayList ();
\r
907 interfaces.Add ($1);
\r
910 | interface_type_list COMMA interface_type
\r
912 ArrayList interfaces = (ArrayList) $1;
\r
913 interfaces.Add ($3);
\r
920 opt_interface_member_declarations
\r
924 opt_interface_member_declarations
\r
926 | interface_member_declarations
\r
929 interface_member_declarations
\r
930 : interface_member_declaration
\r
931 | interface_member_declarations interface_member_declaration
\r
934 interface_member_declaration
\r
935 : interface_method_declaration
\r
937 InterfaceMethod m = (InterfaceMethod) $1;
\r
939 CheckDef (current_interface.AddMethod (m), m.Name);
\r
941 | interface_property_declaration
\r
943 InterfaceProperty p = (InterfaceProperty) $1;
\r
945 CheckDef (current_interface.AddProperty (p), p.Name);
\r
947 | interface_event_declaration
\r
949 InterfaceEvent e = (InterfaceEvent) $1;
\r
951 CheckDef (current_interface.AddEvent (e), e.Name);
\r
953 | interface_indexer_declaration
\r
955 InterfaceIndexer i = (InterfaceIndexer) $1;
\r
957 CheckDef (current_interface.AddIndexer (i), "indexer");
\r
962 : /* empty */ { $$ = false; }
\r
963 | NEW { $$ = true; }
\r
966 interface_method_declaration
\r
967 : opt_attributes opt_new type IDENTIFIER
\r
968 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
971 $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6);
\r
973 | opt_attributes opt_new VOID IDENTIFIER
\r
974 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
977 $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6);
\r
981 interface_property_declaration
\r
986 { lexer.properties = true; }
\r
987 interface_accesors
\r
988 { lexer.properties = false; }
\r
993 $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2,
\r
994 (gs & 1) == 1, (gs & 2) == 2);
\r
999 : opt_attributes GET SEMICOLON { $$ = 1; }
\r
1000 | opt_attributes SET SEMICOLON { $$ = 2; }
\r
1001 | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
\r
1003 | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
\r
1007 interface_event_declaration
\r
1008 : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
\r
1010 $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2);
\r
1014 interface_indexer_declaration
\r
1015 : opt_attributes opt_new type THIS
\r
1016 OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1018 { lexer.properties = true; }
\r
1019 interface_accesors
\r
1020 { lexer.properties = false; }
\r
1023 int a_flags = (int) $10;
\r
1025 bool do_get = (a_flags & 1) == 1;
\r
1026 bool do_set = (a_flags & 2) == 2;
\r
1028 $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2);
\r
1032 operator_declaration
\r
1033 : opt_attributes opt_modifiers operator_declarator block
\r
1035 // FIXME: validate that opt_modifiers is exactly: PUBLIC and STATIC
\r
1039 operator_declarator
\r
1040 : type OPERATOR overloadable_operator
\r
1041 OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1043 // FIXME: since reduce/reduce on this
\r
1044 // rule, validate overloadable_operator is unary
\r
1046 | type OPERATOR overloadable_operator
\r
1048 type IDENTIFIER COMMA
\r
1052 // FIXME: because of the reduce/reduce on PLUS and MINUS
\r
1053 // validate overloadable_operator is binary
\r
1055 | conversion_operator_declarator
\r
1058 overloadable_operator
\r
1059 // Unary operators:
\r
1066 // Unary and binary:
\r
1086 conversion_operator_declarator
\r
1087 : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1088 | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
\r
1091 constructor_declaration
\r
1094 constructor_declarator
\r
1097 Constructor c = (Constructor) $3;
\r
1098 c.Block = (Block) $4;
\r
1099 c.ModFlags = (int) $2;
\r
1101 if ((c.ModFlags & Modifiers.STATIC) != 0){
\r
1102 if ((c.ModFlags & Modifiers.Accessibility) != 0){
\r
1103 error (515, "Access modifiers are not allowed on static constructors");
\r
1106 CheckDef (current_container.AddConstructor (c), c.Name);
\r
1108 current_local_parameters = null;
\r
1112 constructor_declarator
\r
1114 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
\r
1115 opt_constructor_initializer
\r
1117 ConstructorInitializer i = null;
\r
1120 i = new ConstructorBaseInitializer (null);
\r
1122 i = (ConstructorInitializer) $5;
\r
1124 $$ = new Constructor ((string) $1, (Parameters) $3, i);
\r
1126 current_local_parameters = (Parameters) $3;
\r
1130 opt_constructor_initializer
\r
1131 : /* empty */ { $$ = null; }
\r
1132 | constructor_initializer
\r
1135 constructor_initializer
\r
1136 : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1138 $$ = new ConstructorBaseInitializer ((ArrayList) $4);
\r
1140 | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1142 $$ = new ConstructorThisInitializer ((ArrayList) $4);
\r
1146 destructor_declaration
\r
1147 : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
\r
1149 Method d = new Method ("System.Void", 0, "Finalize", new Parameters (null, null));
\r
1151 d.Block = (Block) $6;
\r
1152 CheckDef (current_container.AddMethod (d), d.Name);
\r
1159 EVENT type variable_declarators SEMICOLON
\r
1161 foreach (VariableDeclaration var in (ArrayList) $5) {
\r
1163 // FIXME : Is this right ?
\r
1164 Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
\r
1165 (int) $2, null, null);
\r
1167 CheckDef (current_container.AddEvent (e), e.Name);
\r
1173 EVENT type member_name
\r
1174 OPEN_BRACE event_accessor_declarations CLOSE_BRACE
\r
1176 DictionaryEntry pair = (DictionaryEntry) $7;
\r
1177 Block add_block = null;
\r
1178 Block rem_block = null;
\r
1180 if (pair.Key != null)
\r
1181 add_block = (Block) pair.Key;
\r
1182 if (pair.Value != null)
\r
1183 rem_block = (Block) pair.Value;
\r
1185 Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block);
\r
1187 CheckDef (current_container.AddEvent (e), e.Name);
\r
1191 event_accessor_declarations
\r
1192 : add_accessor_declaration remove_accessor_declaration
\r
1194 $$ = new DictionaryEntry ($1, $2);
\r
1196 | remove_accessor_declaration add_accessor_declaration
\r
1198 $$ = new DictionaryEntry ($2, $2);
\r
1202 add_accessor_declaration
\r
1203 : opt_attributes ADD block
\r
1209 remove_accessor_declaration
\r
1210 : opt_attributes REMOVE block
\r
1216 indexer_declaration
\r
1217 : opt_attributes opt_modifiers indexer_declarator
\r
1220 IndexerDeclaration decl = (IndexerDeclaration) $3;
\r
1222 lexer.properties = true;
\r
1223 parsing_indexer = true;
\r
1225 current_local_parameters = decl.param_list;
\r
1227 accessor_declarations
\r
1229 lexer.properties = false;
\r
1230 parsing_indexer = false;
\r
1234 // The signature is computed from the signature of the indexer. Look
\r
1235 // at section 3.6 on the spec
\r
1238 IndexerDeclaration decl = (IndexerDeclaration) $3;
\r
1239 DictionaryEntry pair = (DictionaryEntry) $6;
\r
1240 Block get_block = null;
\r
1241 Block set_block = null;
\r
1243 if (pair.Key != null)
\r
1244 get_block = (Block) pair.Key;
\r
1245 if (pair.Value != null)
\r
1246 set_block = (Block) pair.Value;
\r
1248 indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
\r
1249 get_block, set_block);
\r
1251 // Note that there is no equivalent of CheckDef for this case
\r
1252 // We shall handle this in semantic analysis
\r
1254 current_local_parameters = null;
\r
1258 indexer_declarator
\r
1259 : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1261 $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);
\r
1263 | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
\r
1265 $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);
\r
1277 string name = (string) $4;
\r
1278 Enum e = new Enum ((string) $5, (int) $2, name);
\r
1280 foreach (VariableDeclaration ev in (ArrayList) $6){
\r
1284 (Expression) ev.expression_or_array_initializer),
\r
1288 CheckDef (current_container.AddEnum (e), name);
\r
1293 : /* empty */ { $$ = "System.Int32"; }
\r
1294 | COLON integral_type { $$ = $2; }
\r
1298 : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
\r
1304 opt_enum_member_declarations
\r
1305 : /* empty */ { $$ = new ArrayList (); }
\r
1306 | enum_member_declarations opt_comma { $$ = $1; }
\r
1309 enum_member_declarations
\r
1310 : enum_member_declaration
\r
1312 ArrayList l = new ArrayList ();
\r
1317 | enum_member_declarations COMMA enum_member_declaration
\r
1319 ArrayList l = (ArrayList) $1;
\r
1327 enum_member_declaration
\r
1328 : opt_attributes IDENTIFIER
\r
1330 $$ = new VariableDeclaration ((string) $2, null);
\r
1332 | opt_attributes IDENTIFIER ASSIGN expression
\r
1334 $$ = new VariableDeclaration ((string) $2, $4);
\r
1338 delegate_declaration
\r
1342 IDENTIFIER OPEN_PARENS
\r
1343 formal_parameter_list
\r
1346 { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }
\r
1351 IDENTIFIER OPEN_PARENS
\r
1352 formal_parameter_list
\r
1355 { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }
\r
1359 : namespace_or_type_name
\r
1362 namespace_or_type_name
\r
1363 : qualified_identifier
\r
1367 * Before you think of adding a return_type, notice that we have been
\r
1368 * using two rules in the places where it matters (one rule using type
\r
1369 * and another identical one that uses VOID as the return type). This
\r
1370 * gets rid of a shift/reduce couple
\r
1373 : type_name { /* class_type */
\r
1375 This does interfaces, delegates, struct_types, class_types,
\r
1376 parent classes, and more! 4.2
\r
1387 ArrayList types = new ArrayList ();
\r
1392 | type_list COMMA type
\r
1394 ArrayList types = (ArrayList) $1;
\r
1402 * replaces all the productions for isolating the various
\r
1403 * simple types, but we need this to reuse it easily in local_variable_type
\r
1406 : OBJECT { $$ = "System.Object"; }
\r
1407 | STRING { $$ = "System.String"; }
\r
1408 | BOOL { $$ = "System.Boolean"; }
\r
1409 | DECIMAL { $$ = "System.Decimal"; }
\r
1410 | FLOAT { $$ = "System.Single"; }
\r
1411 | DOUBLE { $$ = "System.Double"; }
\r
1416 : SBYTE { $$ = "System.SByte"; }
\r
1417 | BYTE { $$ = "System.Byte"; }
\r
1418 | SHORT { $$ = "System.Int16"; }
\r
1419 | USHORT { $$ = "System.UInt16"; }
\r
1420 | INT { $$ = "System.Int32"; }
\r
1421 | UINT { $$ = "System.UInt32"; }
\r
1422 | LONG { $$ = "System.Int64"; }
\r
1423 | ULONG { $$ = "System.UInt64"; }
\r
1424 | CHAR { $$ = "System.Char"; }
\r
1432 : type rank_specifiers
\r
1434 $$ = (string) $1 + " " + (string) $2;
\r
1435 // FIXME: We need to create a type for the nested thing.
\r
1440 // Expressions, section 7.5
\r
1442 primary_expression
\r
1445 // 7.5.1: Literals
\r
1449 | qualified_identifier
\r
1451 string name = (string) $1;
\r
1454 if (name.IndexOf ('.') == -1){
\r
1456 // we need to check against current_block not being null
\r
1457 // as `expression' is allowed in argument_lists, which
\r
1458 // do not exist inside a block.
\r
1460 if (current_block != null){
\r
1461 if (current_block.IsVariableDefined (name))
\r
1462 $$ = new LocalVariableReference (current_block, name);
\r
1464 if (($$ == null) && (current_local_parameters != null)){
\r
1465 Parameter par = current_local_parameters.GetParameterByName (name);
\r
1467 $$ = new ParameterReference (current_local_parameters, name);
\r
1471 $$ = new SimpleName (name);
\r
1473 | parenthesized_expression
\r
1475 | invocation_expression
\r
1479 | post_increment_expression
\r
1480 | post_decrement_expression
\r
1482 | typeof_expression
\r
1483 | sizeof_expression
\r
1484 | checked_expression
\r
1485 | unchecked_expression
\r
1492 | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
\r
1493 | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
\r
1494 | NULL { $$ = new NullLiteral (); }
\r
1498 : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }
\r
1499 | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
\r
1500 | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
\r
1504 : LITERAL_INTEGER { $$ = new IntLiteral ((Int32) lexer.Value); }
\r
1508 : TRUE { $$ = new BoolLiteral (true); }
\r
1509 | FALSE { $$ = new BoolLiteral (false); }
\r
1512 parenthesized_expression
\r
1513 : OPEN_PARENS expression CLOSE_PARENS
\r
1518 : primary_expression DOT IDENTIFIER
\r
1520 $$ = new MemberAccess ((Expression) $1, (string) $3);
\r
1522 | predefined_type DOT IDENTIFIER
\r
1524 $$ = new BuiltinTypeAccess ((string) $1, (string) $3);
\r
1532 invocation_expression
\r
1533 : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1536 // if $1 is MethodGroup
\r
1537 // $$ = new Call ($1, $3);
\r
1539 // $$ = new DelegateCall ($1, $3);
\r
1541 error (1, "THIS IS CRAZY");
\r
1543 $$ = new Invocation ((Expression) $1, (ArrayList) $3);
\r
1548 : /* empty */ { $$ = null; }
\r
1555 ArrayList list = new ArrayList ();
\r
1559 | argument_list COMMA argument
\r
1561 ArrayList list = (ArrayList) $1;
\r
1570 $$ = new Argument ((Expression) $1, Argument.AType.Expression);
\r
1572 | REF variable_reference
\r
1574 $$ = new Argument ((Expression) $2, Argument.AType.Ref);
\r
1576 | OUT variable_reference
\r
1578 $$ = new Argument ((Expression) $2, Argument.AType.Out);
\r
1582 variable_reference
\r
1583 : expression { note ("section 5.4"); $$ = $1; }
\r
1587 : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1594 ArrayList list = new ArrayList ();
\r
1598 | expression_list COMMA expression
\r
1600 ArrayList list = (ArrayList) $1;
\r
1614 : BASE DOT IDENTIFIER
\r
1616 | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1620 post_increment_expression
\r
1621 : primary_expression OP_INC
\r
1623 $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1);
\r
1627 post_decrement_expression
\r
1628 : primary_expression OP_DEC
\r
1630 $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1);
\r
1635 : object_or_delegate_creation_expression
\r
1636 | array_creation_expression
\r
1639 object_or_delegate_creation_expression
\r
1640 : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
\r
1642 $$ = new New ((string) $2, (ArrayList) $4);
\r
1646 array_creation_expression
\r
1647 : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
\r
1648 opt_rank_specifier
\r
1649 opt_array_initializer
\r
1651 $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7);
\r
1655 opt_rank_specifier
\r
1671 | rank_specifier rank_specifiers
\r
1673 $$ = (string) $1 + (string) $2;
\r
1678 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
1680 $$ = "[" + (string) $2 + "]";
\r
1684 opt_dim_separators
\r
1700 | dim_separators COMMA
\r
1702 $$ =(string) $1 + ",";
\r
1706 opt_array_initializer
\r
1711 | array_initializer
\r
1718 : OPEN_BRACE CLOSE_BRACE
\r
1720 ArrayList list = new ArrayList ();
\r
1723 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
\r
1725 $$ = (ArrayList) $2;
\r
1729 variable_initializer_list
\r
1730 : variable_initializer
\r
1732 ArrayList list = new ArrayList ();
\r
1736 | variable_initializer_list COMMA variable_initializer
\r
1738 ArrayList list = (ArrayList) $1;
\r
1745 : TYPEOF OPEN_PARENS type CLOSE_PARENS
\r
1747 $$ = new TypeOf ((string) $3);
\r
1752 : SIZEOF OPEN_PARENS type CLOSE_PARENS {
\r
1753 $$ = new SizeOf ((string) $3);
\r
1755 note ("Verify type is unmanaged");
\r
1756 note ("if (5.8) builtin, yield constant expression");
\r
1760 checked_expression
\r
1761 : CHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1764 unchecked_expression
\r
1765 : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
\r
1769 : primary_expression
\r
1770 | PLUS unary_expression {
\r
1771 $$ = new Unary (Unary.Operator.Plus, (Expression) $2);
\r
1773 | MINUS unary_expression
\r
1775 $$ = new Unary (Unary.Operator.Minus, (Expression) $2);
\r
1777 | BANG unary_expression
\r
1779 $$ = new Unary (Unary.Operator.Negate, (Expression) $2);
\r
1781 | TILDE unary_expression
\r
1783 $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2);
\r
1785 | STAR unary_expression
\r
1787 $$ = new Unary (Unary.Operator.Indirection, (Expression) $2);
\r
1789 | BITWISE_AND unary_expression
\r
1791 $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);
\r
1793 | OP_INC unary_expression
\r
1795 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1797 | OP_DEC unary_expression
\r
1799 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1801 | cast_expression
\r
1803 we can not do cast expressions at this level,
\r
1804 as there is an ambiguity. Check "Cast Expressions" 7.6.8
\r
1805 for the recipe to handle this.
\r
1809 pre_increment_expression
\r
1810 : OP_INC unary_expression
\r
1812 $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);
\r
1816 pre_decrement_expression
\r
1817 : OP_DEC unary_expression
\r
1819 $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);
\r
1825 * FIXME: This is actually wrong, it should be `type' but that
\r
1826 * introduces a lot of {shift,reduce}/reduces
\r
1828 * This is really really wrong. We need to track down
\r
1829 * the source of problems with QIs because expressions like:
\r
1830 * foreach (string s in (string []) object) wont be parsed.
\r
1832 : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression
\r
1834 $$ = new Cast ((string) $2, (Expression) $4);
\r
1836 | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
\r
1838 $$ = new Cast ((string) $2, (Expression) $4);
\r
1842 multiplicative_expression
\r
1843 : unary_expression
\r
1844 | multiplicative_expression STAR unary_expression
\r
1846 $$ = new Binary (Binary.Operator.Multiply,
\r
1847 (Expression) $1, (Expression) $3);
\r
1849 | multiplicative_expression DIV unary_expression
\r
1851 $$ = new Binary (Binary.Operator.Divide,
\r
1852 (Expression) $1, (Expression) $3);
\r
1854 | multiplicative_expression PERCENT unary_expression
\r
1856 $$ = new Binary (Binary.Operator.Modulo,
\r
1857 (Expression) $1, (Expression) $3);
\r
1861 additive_expression
\r
1862 : multiplicative_expression
\r
1863 | additive_expression PLUS multiplicative_expression
\r
1865 $$ = new Binary (Binary.Operator.Add,
\r
1866 (Expression) $1, (Expression) $3);
\r
1868 | additive_expression MINUS multiplicative_expression
\r
1870 $$ = new Binary (Binary.Operator.Substract,
\r
1871 (Expression) $1, (Expression) $3);
\r
1876 : additive_expression
\r
1877 | shift_expression OP_SHIFT_LEFT additive_expression
\r
1879 $$ = new Binary (Binary.Operator.ShiftLeft,
\r
1880 (Expression) $1, (Expression) $3);
\r
1882 | shift_expression OP_SHIFT_RIGHT additive_expression
\r
1884 $$ = new Binary (Binary.Operator.ShiftRight,
\r
1885 (Expression) $1, (Expression) $3);
\r
1889 relational_expression
\r
1890 : shift_expression
\r
1891 | relational_expression OP_LT shift_expression
\r
1893 $$ = new Binary (Binary.Operator.LessThan,
\r
1894 (Expression) $1, (Expression) $3);
\r
1896 | relational_expression OP_GT shift_expression
\r
1898 $$ = new Binary (Binary.Operator.GreatherThan,
\r
1899 (Expression) $1, (Expression) $3);
\r
1901 | relational_expression OP_LE shift_expression
\r
1903 $$ = new Binary (Binary.Operator.LessOrEqual,
\r
1904 (Expression) $1, (Expression) $3);
\r
1906 | relational_expression OP_GE shift_expression
\r
1908 $$ = new Binary (Binary.Operator.GreatherOrEqual,
\r
1909 (Expression) $1, (Expression) $3);
\r
1911 | relational_expression IS type
\r
1913 $$ = new Probe (Probe.Operator.Is,
\r
1914 (Expression) $1, (string) $3);
\r
1916 | relational_expression AS type
\r
1918 $$ = new Probe (Probe.Operator.As,
\r
1919 (Expression) $1, (string) $3);
\r
1923 equality_expression
\r
1924 : relational_expression
\r
1925 | equality_expression OP_EQ relational_expression
\r
1927 $$ = new Binary (Binary.Operator.Equal,
\r
1928 (Expression) $1, (Expression) $3);
\r
1930 | equality_expression OP_NE relational_expression
\r
1932 $$ = new Binary (Binary.Operator.NotEqual,
\r
1933 (Expression) $1, (Expression) $3);
\r
1938 : equality_expression
\r
1939 | and_expression BITWISE_AND equality_expression
\r
1941 $$ = new Binary (Binary.Operator.BitwiseAnd,
\r
1942 (Expression) $1, (Expression) $3);
\r
1946 exclusive_or_expression
\r
1948 | exclusive_or_expression CARRET and_expression
\r
1950 $$ = new Binary (Binary.Operator.ExclusiveOr,
\r
1951 (Expression) $1, (Expression) $3);
\r
1955 inclusive_or_expression
\r
1956 : exclusive_or_expression
\r
1957 | inclusive_or_expression BITWISE_OR exclusive_or_expression
\r
1959 $$ = new Binary (Binary.Operator.BitwiseOr,
\r
1960 (Expression) $1, (Expression) $3);
\r
1964 conditional_and_expression
\r
1965 : inclusive_or_expression
\r
1966 | conditional_and_expression OP_AND inclusive_or_expression
\r
1968 $$ = new Binary (Binary.Operator.LogicalAnd,
\r
1969 (Expression) $1, (Expression) $3);
\r
1973 conditional_or_expression
\r
1974 : conditional_and_expression
\r
1975 | conditional_or_expression OP_OR conditional_and_expression
\r
1977 $$ = new Binary (Binary.Operator.LogicalOr,
\r
1978 (Expression) $1, (Expression) $3);
\r
1982 conditional_expression
\r
1983 : conditional_or_expression
\r
1984 | conditional_or_expression INTERR expression COLON expression
\r
1986 $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);
\r
1990 assignment_expression
\r
1991 : unary_expression ASSIGN expression
\r
1993 $$ = new Assign ((Expression) $1, (Expression) $3);
\r
1995 | unary_expression OP_MULT_ASSIGN expression
\r
1997 $$ = new Assign ((Expression) $1,
\r
1998 new Binary (Binary.Operator.Multiply,
\r
2000 (Expression) $3));
\r
2002 | unary_expression OP_DIV_ASSIGN expression
\r
2004 $$ = new Assign ((Expression) $1,
\r
2005 new Binary (Binary.Operator.Divide,
\r
2007 (Expression) $3));
\r
2009 | unary_expression OP_MOD_ASSIGN expression
\r
2011 $$ = new Assign ((Expression) $1,
\r
2012 new Binary (Binary.Operator.Modulo,
\r
2014 (Expression) $3));
\r
2016 | unary_expression OP_ADD_ASSIGN expression
\r
2018 $$ = new Assign ((Expression) $1,
\r
2019 new Binary (Binary.Operator.Add,
\r
2021 (Expression) $3));
\r
2023 | unary_expression OP_SUB_ASSIGN expression
\r
2025 $$ = new Assign ((Expression) $1,
\r
2026 new Binary (Binary.Operator.Substract,
\r
2028 (Expression) $3));
\r
2030 | unary_expression OP_SHIFT_LEFT_ASSIGN expression
\r
2032 $$ = new Assign ((Expression) $1,
\r
2033 new Binary (Binary.Operator.ShiftLeft,
\r
2035 (Expression) $3));
\r
2037 | unary_expression OP_SHIFT_RIGHT_ASSIGN expression
\r
2039 $$ = new Assign ((Expression) $1,
\r
2040 new Binary (Binary.Operator.ShiftRight,
\r
2042 (Expression) $3));
\r
2044 | unary_expression OP_AND_ASSIGN expression
\r
2046 $$ = new Assign ((Expression) $1,
\r
2047 new Binary (Binary.Operator.BitwiseAnd,
\r
2049 (Expression) $3));
\r
2051 | unary_expression OP_OR_ASSIGN expression
\r
2053 $$ = new Assign ((Expression) $1,
\r
2054 new Binary (Binary.Operator.BitwiseOr,
\r
2056 (Expression) $3));
\r
2058 | unary_expression OP_XOR_ASSIGN expression
\r
2060 $$ = new Assign ((Expression) $1,
\r
2061 new Binary (Binary.Operator.ExclusiveOr,
\r
2063 (Expression) $3));
\r
2068 : conditional_expression
\r
2069 | assignment_expression
\r
2072 constant_expression
\r
2076 boolean_expression
\r
2077 : expression { CheckBoolean ((Expression) $1); $$ = $1; }
\r
2089 string full_class_name = MakeName ((string) $4);
\r
2091 new_class = new Class (rc, current_container, full_class_name, (int) $2);
\r
2092 current_container = new_class;
\r
2093 current_container.Namespace = current_namespace;
\r
2094 tree.RecordClass (full_class_name, new_class);
\r
2100 Class new_class = (Class) current_container;
\r
2103 new_class.Bases = (ArrayList) $6;
\r
2105 current_container = current_container.Parent;
\r
2106 CheckDef (current_container.AddClass (new_class), new_class.Name);
\r
2113 : /* empty */ { $$ = (int) 0; }
\r
2119 | modifiers modifier {
\r
2120 int m1 = (int) $1;
\r
2121 int m2 = (int) $2;
\r
2123 if ((m1 & m2) != 0)
\r
2124 error (1002, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
\r
2126 $$ = (int) (m1 | m2);
\r
2131 : NEW { $$ = Modifiers.NEW; }
\r
2132 | PUBLIC { $$ = Modifiers.PUBLIC; }
\r
2133 | PROTECTED { $$ = Modifiers.PROTECTED; }
\r
2134 | INTERNAL { $$ = Modifiers.INTERNAL; }
\r
2135 | PRIVATE { $$ = Modifiers.PRIVATE; }
\r
2136 | ABSTRACT { $$ = Modifiers.ABSTRACT; }
\r
2137 | SEALED { $$ = Modifiers.SEALED; }
\r
2138 | STATIC { $$ = Modifiers.STATIC; }
\r
2139 | READONLY { $$ = Modifiers.READONLY; }
\r
2140 | VIRTUAL { $$ = Modifiers.VIRTUAL; }
\r
2141 | OVERRIDE { $$ = Modifiers.OVERRIDE; }
\r
2142 | EXTERN { $$ = Modifiers.EXTERN; }
\r
2146 : /* empty */ { $$ = null; }
\r
2147 | class_base { $$ = $1; }
\r
2151 : COLON type_list { $$ = $2; }
\r
2155 // Statements (8.2)
\r
2159 // A block is "contained" on the following places:
\r
2161 // property_declaration as part of the accessor body (get/set)
\r
2162 // operator_declaration
\r
2163 // constructor_declaration
\r
2164 // destructor_declaration
\r
2165 // event_declaration as part of add_accessor_declaration or remove_accessor_declaration
\r
2170 current_block = new Block (current_block);
\r
2172 opt_statement_list CLOSE_BRACE
\r
2174 while (current_block.Implicit)
\r
2175 current_block = current_block.Parent;
\r
2176 $$ = current_block;
\r
2177 current_block = current_block.Parent;
\r
2181 opt_statement_list
\r
2188 | statement_list statement
\r
2192 : declaration_statement
\r
2194 if ((Block) $1 != current_block){
\r
2195 current_block.AddStatement ((Statement) $1);
\r
2196 current_block = (Block) $1;
\r
2199 | embedded_statement
\r
2201 current_block.AddStatement ((Statement) $1);
\r
2203 | labeled_statement
\r
2205 current_block.AddStatement ((Statement) $1);
\r
2209 embedded_statement
\r
2212 | expression_statement
\r
2213 | selection_statement
\r
2214 | iteration_statement
\r
2217 | checked_statement
\r
2218 | unchecked_statement
\r
2226 $$ = new EmptyStatement ();
\r
2231 : IDENTIFIER COLON statement
\r
2233 string lab = (String) $1;
\r
2236 block = new Block (current_block, lab);
\r
2237 block.AddStatement ((Statement) $3);
\r
2240 if (!current_block.AddLabel (lab, block)){
\r
2241 error (140, "The label '" + lab + "' is a duplicate");
\r
2247 declaration_statement
\r
2248 : local_variable_declaration SEMICOLON // done
\r
2249 | local_constant_declaration SEMICOLON // finishme
\r
2253 * The following is from Rhys' grammar:
\r
2254 * > Types in local variable declarations must be recognized as
\r
2255 * > expressions to prevent reduce/reduce errors in the grammar.
\r
2256 * > The expressions are converted into types during semantic analysis.
\r
2258 local_variable_type
\r
2259 : primary_expression type_suffixes
\r
2261 // FIXME: Do something smart here regarding the composition of the type.
\r
2264 // Ok, the above "primary_expression" is there to get rid of
\r
2265 // both reduce/reduce and shift/reduces in the grammar, it should
\r
2266 // really just be "type_name". If you use type_name, a reduce/reduce
\r
2267 // creeps up. If you use qualified_identifier (which is all we need
\r
2268 // really) two shift/reduces appear.
\r
2270 // So, instead we do a super trick: we just allow ($1) to be a
\r
2271 // SimpleName Expression.
\r
2273 if (((Expression) $1) is SimpleName)
\r
2274 $$ = ((SimpleName) $1).Name;
\r
2276 error (-1, "Invalid Type definition");
\r
2277 $$ = "System.Object";
\r
2280 | builtin_types type_suffixes
\r
2282 // FIXME: Do something smart with the type here.
\r
2285 | VOID type_suffixes
\r
2287 // FIXME: this is a string that represents the type
\r
2288 // Figure out something to make this work.
\r
2289 $$ = "VOID SOMETHING TYPE FIXME";
\r
2295 | type_suffix_list
\r
2300 | type_suffix_list type_suffix
\r
2304 : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
\r
2305 /* FIXME: | MULTIPLY */
\r
2308 local_variable_declaration
\r
2309 : local_variable_type variable_declarators
\r
2311 $$ = declare_local_variables ((string) $1, (ArrayList) $2);
\r
2315 local_constant_declaration
\r
2316 : CONST type constant_declarator
\r
2320 expression_statement
\r
2321 : statement_expression SEMICOLON
\r
2328 // We have to do the wrapping here and not in the case above,
\r
2329 // because statement_expression is used for example in for_statement
\r
2331 statement_expression
\r
2332 : invocation_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2333 | object_creation_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2334 | assignment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2335 | post_increment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2336 | post_decrement_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2337 | pre_increment_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2338 | pre_decrement_expression { $$ = new StatementExpression ((Expression) $1); }
\r
2341 object_creation_expression
\r
2342 : object_or_delegate_creation_expression
\r
2343 { note ("complain if this is a delegate maybe?"); }
\r
2346 selection_statement
\r
2348 | switch_statement
\r
2352 : IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2353 embedded_statement
\r
2355 $$ = new If ((Expression) $3, (Statement) $5);
\r
2357 | IF OPEN_PARENS boolean_expression CLOSE_PARENS
\r
2358 embedded_statement ELSE embedded_statement
\r
2360 $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
\r
2365 : SWITCH OPEN_PARENS expression CLOSE_PARENS
\r
2368 $$ = new Switch ((Expression) $3, (ArrayList) $5);
\r
2374 opt_switch_sections
\r
2381 opt_switch_sections
\r
2382 : /* empty */ { $$ = new ArrayList (); }
\r
2389 ArrayList sections = new ArrayList ();
\r
2391 sections.Add ($1);
\r
2394 | switch_sections switch_section
\r
2396 ArrayList sections = (ArrayList) $1;
\r
2398 sections.Add ($2);
\r
2406 current_block = new Block (current_block);
\r
2410 while (current_block.Implicit)
\r
2411 current_block = current_block.Parent;
\r
2412 $$ = new SwitchSection ((ArrayList) $1, current_block);
\r
2413 current_block = current_block.Parent;
\r
2420 ArrayList labels = new ArrayList ();
\r
2425 | switch_labels switch_label
\r
2427 ArrayList labels = (ArrayList) ($1);
\r
2435 : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2); }
\r
2436 | DEFAULT COLON { $$ = new SwitchLabel (null); }
\r
2439 iteration_statement
\r
2443 | foreach_statement
\r
2447 : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
\r
2449 $$ = new While ((Expression) $3, (Statement) $5);
\r
2454 : DO embedded_statement
\r
2455 WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
\r
2457 $$ = new Do ((Statement) $2, (Expression) $5);
\r
2462 : FOR OPEN_PARENS
\r
2463 opt_for_initializer SEMICOLON
\r
2464 opt_for_condition SEMICOLON
\r
2465 opt_for_iterator CLOSE_PARENS
\r
2466 embedded_statement
\r
2468 $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
\r
2472 opt_for_initializer
\r
2473 : /* empty */ { $$ = new EmptyStatement (); }
\r
2474 | for_initializer
\r
2478 : local_variable_declaration
\r
2479 | statement_expression_list
\r
2483 : /* empty */ { $$ = new BoolLiteral (true); }
\r
2484 | boolean_expression
\r
2488 : /* empty */ { $$ = new EmptyStatement (); }
\r
2493 : statement_expression_list
\r
2496 statement_expression_list
\r
2497 : statement_expression
\r
2499 Block b = new Block (null, true);
\r
2501 b.AddStatement ((Statement) $1);
\r
2504 | statement_expression_list COMMA statement_expression
\r
2506 Block b = (Block) $1;
\r
2508 b.AddStatement ((Statement) $3);
\r
2514 : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS
\r
2515 embedded_statement
\r
2517 string temp_id = current_block.MakeInternalID ();
\r
2518 Expression assign_e, ma;
\r
2519 Statement getcurrent;
\r
2520 Block foreach_block, child_block;
\r
2522 foreach_block = new Block (current_block, true);
\r
2524 foreach_block.AddVariable ("System.IEnumerator", temp_id);
\r
2525 foreach_block.AddVariable ((string) $3, (string) $4);
\r
2526 assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id),
\r
2528 new MemberAccess ((Expression) $6, "GetEnumerator"), null));
\r
2529 current_block.AddStatement (new StatementExpression (assign_e));
\r
2530 ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");
\r
2531 child_block = new Block (current_block);
\r
2533 getcurrent = new StatementExpression (
\r
2535 new LocalVariableReference (foreach_block, (string) $4),
\r
2538 new MemberAccess (
\r
2539 new LocalVariableReference (foreach_block, temp_id), "Current"))));
\r
2541 child_block.AddStatement (getcurrent);
\r
2542 child_block.AddStatement ((Statement) $8);
\r
2543 foreach_block.AddStatement (new While (ma, (Statement) child_block));
\r
2545 $$ = foreach_block;
\r
2551 | continue_statement
\r
2553 | return_statement
\r
2560 $$ = new Break ();
\r
2564 continue_statement
\r
2565 : CONTINUE SEMICOLON
\r
2567 $$ = new Continue ();
\r
2572 : GOTO IDENTIFIER SEMICOLON
\r
2574 $$ = new Goto ((string) $2);
\r
2576 | GOTO CASE constant_expression SEMICOLON
\r
2577 | GOTO DEFAULT SEMICOLON
\r
2581 : RETURN opt_expression SEMICOLON
\r
2583 $$ = new Return ((Expression) $2);
\r
2588 : THROW opt_expression SEMICOLON
\r
2590 $$ = new Throw ((Expression) $2);
\r
2600 : TRY block catch_clauses
\r
2602 DictionaryEntry cc = (DictionaryEntry) $3;
\r
2603 ArrayList s = null;
\r
2605 if (cc.Key != null)
\r
2606 s = (ArrayList) cc.Key;
\r
2608 $$ = new Try ((Block) $2, s, (Catch) cc.Value, null);
\r
2610 | TRY block FINALLY block
\r
2612 $$ = new Try ((Block) $2, null, null, (Block) $4);
\r
2614 | TRY block catch_clauses FINALLY block
\r
2616 DictionaryEntry cc = (DictionaryEntry) $3;
\r
2617 ArrayList s = null;
\r
2619 if (cc.Key != null)
\r
2620 s = (ArrayList) cc.Key;
\r
2622 $$ = new Try ((Block) $2, s, (Catch) cc.Value, (Block) $5);
\r
2627 : specific_catch_clauses opt_general_catch_clause
\r
2629 DictionaryEntry pair = new DictionaryEntry ();
\r
2636 | opt_specific_catch_clauses general_catch_clause
\r
2638 DictionaryEntry pair = new DictionaryEntry ();
\r
2646 opt_general_catch_clause
\r
2647 : /* empty */ { $$ = null; }
\r
2648 | general_catch_clause
\r
2651 opt_specific_catch_clauses
\r
2652 : /* emtpy */ { $$ = null; }
\r
2653 | specific_catch_clauses
\r
2656 specific_catch_clauses
\r
2657 : specific_catch_clause
\r
2659 ArrayList l = new ArrayList ();
\r
2664 | specific_catch_clauses specific_catch_clause
\r
2666 ArrayList l = (ArrayList) $1;
\r
2673 specific_catch_clause
\r
2674 : CATCH OPEN_PARENS type opt_identifier CLOSE_PARENS block
\r
2681 $$ = new Catch ((string) $3, id, (Block) $6);
\r
2686 : /* empty */ { $$ = null; }
\r
2690 general_catch_clause
\r
2693 $$ = new Catch (null, null, (Block) $2);
\r
2700 $$ = new Checked ((Block) $2);
\r
2704 unchecked_statement
\r
2707 $$ = new Unchecked ((Block) $2);
\r
2712 : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
\r
2714 $$ = new Lock ((Expression) $3, (Statement) $5);
\r
2719 : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
\r
2723 resource_acquisition
\r
2724 : local_variable_declaration
\r
2732 // A class used to pass around variable declarations and constants
\r
2734 public class VariableDeclaration {
\r
2735 public string identifier;
\r
2736 public object expression_or_array_initializer;
\r
2738 public VariableDeclaration (string id, object eoai){
\r
2739 this.identifier = id;
\r
2740 this.expression_or_array_initializer = eoai;
\r
2745 // A class used to hold info about an indexer declarator
\r
2748 public class IndexerDeclaration {
\r
2749 public string type;
\r
2750 public string interface_type;
\r
2751 public Parameters param_list;
\r
2753 public IndexerDeclaration (string type, string interface_type, Parameters param_list)
\r
2756 this.interface_type = interface_type;
\r
2757 this.param_list = param_list;
\r
2763 // Given the @class_name name, it creates a fully qualified name
\r
2764 // based on the containing declaration space
\r
2767 MakeName (string class_name)
\r
2769 string ns = current_namespace.Name;
\r
2770 string container_name = current_container.Name;
\r
2772 if (container_name == ""){
\r
2774 return ns + "." + class_name;
\r
2776 return class_name;
\r
2778 return container_name + "." + class_name;
\r
2782 // Used to report back to the user the result of a declaration
\r
2783 // in the current declaration space
\r
2786 CheckDef (DeclSpace.AdditionResult result, string name)
\r
2788 if (result == DeclSpace.AdditionResult.Success)
\r
2792 case DeclSpace.AdditionResult.NameExists:
\r
2793 error (102, "The namespace `" + current_container.Name +
\r
2794 "' already contains a definition for `"+
\r
2799 NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
\r
2801 case DeclSpace.AdditionResult.MethodDuplicated:
\r
2802 error (111, "Class `"+current_container.Name+
\r
2803 "' already defines a member called '" +
\r
2804 name + "' with the same parameter types");
\r
2807 case DeclSpace.AdditionResult.EnclosingClash:
\r
2808 error (542, "Member names cannot be the same as their enclosing type");
\r
2811 case DeclSpace.AdditionResult.NotAConstructor:
\r
2812 error (1520, "Class, struct, or interface method must have a return type");
\r
2818 CheckDef (bool result, string name)
\r
2822 CheckDef (DeclSpace.AdditionResult.NameExists, name);
\r
2825 Block declare_local_variables (string type, ArrayList variable_declarators)
\r
2827 Block implicit_block;
\r
2828 ArrayList inits = null;
\r
2831 // We use the `Used' property to check whether statements
\r
2832 // have been added to the current block. If so, we need
\r
2833 // to create another block to contain the new declaration
\r
2834 // otherwise, as an optimization, we use the same block to
\r
2835 // add the declaration.
\r
2837 // FIXME: A further optimization is to check if the statements
\r
2838 // that were added were added as part of the initialization
\r
2839 // below. In which case, no other statements have been executed
\r
2840 // and we might be able to reduce the number of blocks for
\r
2841 // situations like this:
\r
2843 // int j = 1; int k = j + 1;
\r
2845 if (current_block.Used)
\r
2846 implicit_block = new Block (current_block, true);
\r
2848 implicit_block = new Block (current_block, true);
\r
2850 foreach (VariableDeclaration decl in variable_declarators){
\r
2851 if (implicit_block.AddVariable (type, decl.identifier)){
\r
2852 if (decl.expression_or_array_initializer != null){
\r
2853 if (inits == null)
\r
2854 inits = new ArrayList ();
\r
2858 error (128, "A local variable `" + decl.identifier +
\r
2859 "' is already defined in this scope");
\r
2863 if (inits == null)
\r
2864 return implicit_block;
\r
2866 foreach (VariableDeclaration decl in inits){
\r
2867 if (decl.expression_or_array_initializer is Expression){
\r
2868 Expression expr = (Expression) decl.expression_or_array_initializer;
\r
2871 assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr);
\r
2872 implicit_block.AddStatement (new StatementExpression (assign));
\r
2877 return implicit_block;
\r
2880 void CheckConstant (Expression expr)
\r
2885 void CheckBoolean (Expression expr)
\r
2890 static public void error (int code, string desc)
\r
2892 Console.WriteLine ("Error CS"+code+": "+desc);
\r
2896 void output (string s)
\r
2898 Console.WriteLine (s);
\r
2901 void note (string s)
\r
2903 // Used to put annotations
\r
2908 public CSharpParser(RootContext rc, string name, System.IO.Stream input)
\r
2910 current_namespace = new Namespace (null, "");
\r
2912 this.tree = rc.Tree;
\r
2914 this.input = input;
\r
2915 current_container = tree.Types;
\r
2916 current_container.Namespace = current_namespace;
\r
2918 lexer = new Tokenizer (input, name);
\r
2921 public int parse ()
\r
2923 StringBuilder value = new StringBuilder ();
\r
2925 global_errors = 0;
\r
2927 if (yacc_verbose_flag)
\r
2928 yyparse (lexer, new yydebug.yyDebugSimple ());
\r
2931 } catch (Exception e){
\r
2932 Console.WriteLine ("Fatal error: "+name);
\r
2933 Console.WriteLine (e);
\r
2934 Console.WriteLine (lexer.location);
\r
2938 return global_errors;
\r
2941 bool yacc_verbose_flag = false;
\r
2943 public bool yacc_verbose {
\r
2945 yacc_verbose_flag = value;
\r
2949 return yacc_verbose_flag;
\r