-%{\r
-//\r
-// cs-parser.jay: The Parser for the C# compiler\r
-//\r
-// Author: Miguel de Icaza (miguel@gnu.org)\r
-//\r
-// Licensed under the terms of the GNU GPL\r
-//\r
-// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
-//\r
-// TODO:\r
-// (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM\r
-// And come to think of it, it is not that great, it duplicates a lot of code\r
-// for something which is not really needed. We still have piles of typecasts\r
-// anwyays (due to the nature of the stack being a collection of Objects).\r
-//\r
-// (2) Figure out why error productions dont work. `type-declaration' is a\r
-// great spot to put an `error' because you can reproduce it with this input:\r
-// "public X { }"\r
-//\r
-// (3) Move Modifier checking from each object into the parser itself, that will\r
-// get rid of the global "error" symbol that we use now to report errors. \r
-// We still need to pass a pointer to the tree.ErrorHandler, but that is a \r
-// separate problem\r
-//\r
-using System.Text;\r
-using CSC;\r
-using System;\r
-\r
-namespace CSC\r
-{\r
- using System.Collections;\r
- using CSC;\r
- using CIR;\r
-\r
- /// <summary>\r
- /// The C# Parser\r
- /// </summary>\r
- public class CSharpParser {\r
- static int global_errors;\r
-\r
- Namespace current_namespace;\r
- TypeContainer current_container;\r
- \r
- // <summary>\r
- // Current block is used to add statements as we find\r
- // them. \r
- // </summary>\r
-\r
- Block current_block;\r
-\r
- // <summary>\r
- // Current interface is used by the various declaration\r
- // productions in the interface declaration to "add"\r
- // the interfaces as we find them.\r
- // </summary>\r
- Interface current_interface;\r
-\r
- // <summary>\r
- // This is used by the unary_expression code to resolve\r
- // a name against a parameter. \r
- // </summary>\r
- Parameters current_local_parameters;\r
-\r
- // <summary>\r
- // Using during property parsing to describe the implicit\r
- // value parameter that is passed to the "set" accesor\r
- // method\r
- // </summary>\r
- ParameterCollection implicit_value_parameters;\r
-\r
- // <summary>\r
- // Used to record all types defined\r
- // </summary>\r
- CIR.Tree tree;\r
-\r
- // Name of the file we are parsing\r
- public string name;\r
-\r
- // Input stream to parse from.\r
- public System.IO.Stream input;\r
-\r
-%}\r
-\r
-%token EOF\r
-%token NONE /* This token is never returned by our lexer */\r
-%token ERROR // This is used not by the parser, but by the tokenizer.\r
- // do not remove.\r
-\r
-/*\r
- *These are the C# keywords\r
- */\r
-%token ABSTRACT \r
-%token AS\r
-%token ADD\r
-%token BASE \r
-%token BOOL \r
-%token BREAK \r
-%token BYTE \r
-%token CASE \r
-%token CATCH \r
-%token CHAR \r
-%token CHECKED \r
-%token CLASS \r
-%token CONST \r
-%token CONTINUE \r
-%token DECIMAL \r
-%token DEFAULT \r
-%token DELEGATE \r
-%token DO \r
-%token DOUBLE \r
-%token ELSE \r
-%token ENUM \r
-%token EVENT \r
-%token EXPLICIT \r
-%token EXTERN \r
-%token FALSE \r
-%token FINALLY \r
-%token FIXED \r
-%token FLOAT \r
-%token FOR \r
-%token FOREACH \r
-%token GOTO \r
-%token IF \r
-%token IMPLICIT \r
-%token IN \r
-%token INT \r
-%token INTERFACE\r
-%token INTERNAL \r
-%token IS \r
-%token LOCK \r
-%token LONG \r
-%token NAMESPACE\r
-%token NEW \r
-%token NULL \r
-%token OBJECT \r
-%token OPERATOR \r
-%token OUT \r
-%token OVERRIDE \r
-%token PARAMS \r
-%token PRIVATE \r
-%token PROTECTED\r
-%token PUBLIC \r
-%token READONLY \r
-%token REF \r
-%token RETURN \r
-%token REMOVE\r
-%token SBYTE \r
-%token SEALED \r
-%token SHORT \r
-%token SIZEOF \r
-%token STATIC \r
-%token STRING \r
-%token STRUCT \r
-%token SWITCH \r
-%token THIS \r
-%token THROW \r
-%token TRUE \r
-%token TRY \r
-%token TYPEOF \r
-%token UINT \r
-%token ULONG \r
-%token UNCHECKED\r
-%token UNSAFE \r
-%token USHORT \r
-%token USING \r
-%token VIRTUAL \r
-%token VOID \r
-%token WHILE \r
-\r
-/* C# keywords which are not really keywords */\r
-%token GET "get"\r
-%token SET "set"\r
-\r
-/* C# single character operators/punctuation. */\r
-%token OPEN_BRACE "{"\r
-%token CLOSE_BRACE "}"\r
-%token OPEN_BRACKET "["\r
-%token CLOSE_BRACKET "]"\r
-%token OPEN_PARENS "("\r
-%token CLOSE_PARENS ")"\r
-%token DOT "."\r
-%token COMMA ","\r
-%token COLON ":"\r
-%token SEMICOLON ";"\r
-%token TILDE "~"\r
-\r
-%token PLUS "+"\r
-%token MINUS "-"\r
-%token BANG "!"\r
-%token ASSIGN "="\r
-%token OP_LT "<"\r
-%token OP_GT ">"\r
-%token BITWISE_AND "&"\r
-%token BITWISE_OR "|"\r
-%token STAR "*"\r
-%token PERCENT "%"\r
-%token DIV "/"\r
-%token CARRET "^"\r
-%token INTERR "?"\r
-\r
-/* C# multi-character operators. */\r
-%token OP_INC "++"\r
-%token OP_DEC "--"\r
-%token OP_SHIFT_LEFT "<<"\r
-%token OP_SHIFT_RIGHT ">>"\r
-%token OP_LE "<="\r
-%token OP_GE ">="\r
-%token OP_EQ "=="\r
-%token OP_NE "!="\r
-%token OP_AND "&&"\r
-%token OP_OR "||"\r
-%token OP_MULT_ASSIGN "*="\r
-%token OP_DIV_ASSIGN "/="\r
-%token OP_MOD_ASSIGN "%="\r
-%token OP_ADD_ASSIGN "+="\r
-%token OP_SUB_ASSIGN "-="\r
-%token OP_SHIFT_LEFT_ASSIGN "<<="\r
-%token OP_SHIFT_RIGHT_ASSIGN ">>="\r
-%token OP_AND_ASSIGN "&="\r
-%token OP_XOR_ASSIGN "^="\r
-%token OP_OR_ASSIGN "|="\r
-%token OP_PTR "->"\r
-\r
-/* Numbers */\r
-%token LITERAL_INTEGER "int literal"\r
-%token LITERAL_FLOAT "float literal"\r
-%token LITERAL_DOUBLE "double literal"\r
-%token LITERAL_DECIMAL "decimal literal"\r
-%token LITERAL_CHARACTER "character literal"\r
-%token LITERAL_STRING "string literal"\r
-\r
-%token IDENTIFIER\r
-\r
-/* Add precedence rules to solve dangling else s/r conflict */\r
-%nonassoc LOWPREC\r
-%nonassoc IF\r
-%nonassoc ELSE\r
-%right ASSIGN\r
-%left OP_OR\r
-%left OP_AND\r
-%left BITWISE_OR\r
-%left BITWISE_AND\r
-%left OP_SHIFT_LEFT OP_SHIFT_RIGHT\r
-%left PLUS MINUS\r
-%left STAR DIV PERCENT\r
-%right BANG CARRET UMINUS\r
-%nonassoc OP_INC OP_DEC\r
-%left OPEN_PARENS\r
-%left OPEN_BRACKET OPEN_BRACE\r
-%left DOT\r
-%nonassoc HIGHPREC\r
-\r
-%start compilation_unit\r
-/*%start namespace_declaration */\r
-%%\r
-\r
-compilation_unit\r
- : opt_using_directives opt_attributes opt_namespace_member_declarations \r
- EOF\r
- {\r
- // At some point check that using only comes *before* any namespaces\r
- }\r
- ;\r
-\r
-using_directives\r
- : using_directive \r
- | using_directives using_directive \r
- ;\r
-\r
-using_directive\r
- : using_alias_directive\r
- | using_namespace_directive\r
- ;\r
-\r
-using_alias_directive\r
- : USING IDENTIFIER ASSIGN \r
- namespace_or_type_name SEMICOLON {\r
- }\r
- ;\r
-\r
-using_namespace_directive\r
- : USING namespace_name SEMICOLON \r
- {\r
- current_namespace.Using ((string) $2);\r
- }\r
- ;\r
-\r
-namespace_declarations\r
- : namespace_declaration\r
- | namespace_declarations namespace_declaration\r
-\r
-namespace_declaration\r
- : NAMESPACE qualified_identifier \r
- {\r
- current_namespace = new Namespace (current_namespace, (string) $2); \r
- } \r
- namespace_body opt_semicolon\r
- { \r
- current_namespace = current_namespace.Parent;\r
- }\r
- ;\r
-\r
-opt_semicolon\r
- : /* empty */\r
- | SEMICOLON\r
- ;\r
-\r
-opt_comma\r
- : /* empty */\r
- | COMMA\r
- ;\r
-\r
-qualified_identifier\r
- : IDENTIFIER\r
- | qualified_identifier DOT IDENTIFIER { \r
- $$ = (($1).ToString ()) + "." + ($3.ToString ()); }\r
- ;\r
-\r
-\r
-namespace_name\r
- : namespace_or_type_name\r
- ;\r
-\r
-namespace_body\r
- : OPEN_BRACE\r
- opt_using_directives\r
- opt_namespace_member_declarations\r
- CLOSE_BRACE {\r
- }\r
- ;\r
-\r
-opt_using_directives\r
- : /* empty */\r
- | using_directives\r
- ;\r
-\r
-opt_namespace_member_declarations\r
- : /* empty */\r
- | namespace_member_declarations\r
- ;\r
-\r
-namespace_member_declarations\r
- : namespace_member_declaration\r
- | namespace_member_declarations namespace_member_declaration\r
- ;\r
-\r
-namespace_member_declaration\r
- : type_declaration\r
- {\r
- int mod_flags = 0;\r
- string name = "";\r
-\r
- if ($1 is Class){\r
- Class c = (Class) $1;\r
- mod_flags = c.ModFlags;\r
- name = c.Name;\r
- } else if ($1 is Struct){\r
- Struct s = (Struct) $1;\r
- mod_flags = s.ModFlags;\r
- name = s.Name;\r
- } else\r
- break;\r
-\r
- //\r
- // We remove this error until we can \r
- //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){\r
- // error (1527, "Namespace elements cant be explicitly " +\r
- // "declared private or protected in `" + name + "'");\r
- //}\r
- }\r
- | namespace_declaration\r
- ;\r
-\r
-type_declaration\r
- : class_declaration \r
- | struct_declaration \r
- | interface_declaration \r
- | enum_declaration \r
- | delegate_declaration // finishme\r
- ;\r
-\r
-//\r
-// Attributes 17.2\r
-//\r
-opt_attributes\r
- : /* empty */\r
- | attribute_section opt_attributes\r
- ;\r
-\r
-attribute_section\r
- : OPEN_BRACKET\r
- opt_attribute_target_specifier attribute_list \r
- /* FIXME: opt_comma */ \r
- CLOSE_BRACKET \r
- ;\r
-\r
-opt_attribute_target_specifier\r
- : /* empty */\r
- | attribute_target_specifier\r
- ;\r
-\r
-attribute_target_specifier\r
- : attribute_target COLON\r
- ;\r
-\r
-attribute_target\r
- : IDENTIFIER { \r
- // if (Collection.Contains ($$))... FIXME\r
- note ("Allows: assembly, field, method, module, param, property, type"); \r
- }\r
- | EVENT\r
- | RETURN \r
- ;\r
-\r
-attribute_list\r
- : attribute\r
- | attribute_list COMMA attribute\r
- ;\r
-\r
-attribute\r
- : attribute_name\r
- | opt_attribute_arguments\r
- ;\r
-\r
-attribute_name\r
- : type_name { /* reserved attribute name or identifier: 17.4 */ }\r
- ;\r
-\r
-opt_attribute_arguments\r
- : /* empty */\r
- | OPEN_PARENS attribute_arguments CLOSE_PARENS\r
- ;\r
-\r
-attribute_arguments\r
- : expression\r
- | attribute_arguments COMMA expression\r
- ;\r
-\r
-\r
-opt_dimension_separators\r
- : /* empty */\r
- | dimension_separators\r
- ;\r
-\r
-dimension_separators\r
- : COMMA \r
- | dimension_separators COMMA \r
- ;\r
-\r
-class_body\r
- : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE\r
- ;\r
-\r
-opt_class_member_declarations\r
- : /* empty */\r
- | class_member_declarations\r
- ;\r
-\r
-class_member_declarations\r
- : class_member_declaration\r
- | class_member_declarations \r
- class_member_declaration\r
- ;\r
-\r
-class_member_declaration\r
- : constant_declaration // done\r
- | field_declaration // done\r
- | method_declaration // done\r
- | property_declaration // done\r
- | event_declaration // finishme\r
- | indexer_declaration // finishme\r
- | operator_declaration // finishme\r
- | constructor_declaration // done\r
- | destructor_declaration // done\r
- | type_declaration\r
- ;\r
-\r
-struct_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- STRUCT IDENTIFIER\r
- { \r
- Struct new_struct;\r
- string full_struct_name = MakeName ((string) $4);\r
-\r
- new_struct = new Struct (current_container, full_struct_name, (int) $2);\r
- current_container = new_struct;\r
- current_container.Namespace = current_namespace;\r
- tree.RecordStruct (full_struct_name, new_struct);\r
- }\r
- opt_struct_interfaces\r
- struct_body\r
- opt_semicolon\r
- {\r
- Struct new_struct = (Struct) current_container;\r
-\r
- current_container = current_container.Parent;\r
- CheckDef (current_container.AddStruct (new_struct), new_struct.Name);\r
- $$ = new_struct;\r
- }\r
- ;\r
-\r
-opt_struct_interfaces\r
- : /* empty */\r
- | struct_interfaces\r
- ;\r
-\r
-struct_interfaces\r
- : struct_interface\r
- | struct_interfaces struct_interface\r
- ; \r
-\r
-struct_interface\r
- : COLON type_list\r
- ;\r
-\r
-struct_body\r
- : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE\r
- ;\r
-\r
-opt_struct_member_declarations\r
- : /* empty */\r
- | struct_member_declarations\r
- ;\r
-\r
-struct_member_declarations\r
- : struct_member_declaration\r
- | struct_member_declarations struct_member_declaration\r
- ;\r
-\r
-struct_member_declaration\r
- : constant_declaration\r
- | field_declaration\r
- | method_declaration\r
- | property_declaration\r
- | event_declaration\r
- | indexer_declaration\r
- | operator_declaration\r
- | constructor_declaration\r
- | type_declaration\r
- ;\r
-\r
-constant_declaration\r
- : opt_attributes \r
- opt_modifiers\r
- CONST\r
- type\r
- constant_declarators\r
- SEMICOLON\r
- { \r
- Modifiers.Check (Constant.AllowedModifiers, (int) $2, Modifiers.PRIVATE);\r
-\r
- foreach (DictionaryEntry constant in (ArrayList) $5){\r
- Constant c = new Constant (\r
- (string) $4, (string) constant.Key, \r
- (Expression) constant.Value);\r
-\r
- CheckDef (current_container.AddConstant (c), c.Name);\r
- }\r
- }\r
- ;\r
-\r
-constant_declarators\r
- : constant_declarator \r
- {\r
- ArrayList constants = new ArrayList ();\r
- constants.Add ($1);\r
- $$ = constants;\r
- }\r
- | constant_declarators COMMA constant_declarator\r
- {\r
- ArrayList constants = (ArrayList) $1;\r
-\r
- constants.Add ($3);\r
- }\r
- ;\r
-\r
-constant_declarator\r
- : IDENTIFIER ASSIGN constant_expression {\r
- $$ = new DictionaryEntry ($1, $3);\r
- }\r
- ;\r
-\r
-field_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- type \r
- variable_declarators\r
- SEMICOLON\r
- { \r
- string type = (string) $3;\r
- int mod = (int) $2;\r
-\r
- foreach (VariableDeclaration var in (ArrayList) $4){\r
- Field field = new Field (type, mod, var.identifier, \r
- var.expression_or_array_initializer);\r
-\r
- CheckDef (current_container.AddField (field), field.Name);\r
- }\r
- }\r
-\r
- ;\r
-\r
-variable_declarators\r
- : variable_declarator \r
- {\r
- ArrayList decl = new ArrayList ();\r
- $$ = decl;\r
- decl.Add ($1);\r
- }\r
- | variable_declarators COMMA variable_declarator\r
- {\r
- ArrayList decls = (ArrayList) $1;\r
- decls.Add ($3);\r
- $$ = $1;\r
- }\r
- ;\r
-\r
-variable_declarator\r
- : IDENTIFIER ASSIGN variable_initializer\r
- {\r
- $$ = new VariableDeclaration ((string) $1, $3);\r
- }\r
- | IDENTIFIER\r
- {\r
- $$ = new VariableDeclaration ((string) $1, null);\r
- }\r
- ;\r
-\r
-variable_initializer\r
- : expression\r
- | array_initializer\r
- ;\r
-\r
-method_declaration\r
- : method_header\r
- method_body\r
- {\r
- Method method = (Method) $1;\r
-\r
- method.Block = (Block) $2;\r
- CheckDef (current_container.AddMethod (method), method.Name);\r
-\r
- current_local_parameters = null;\r
- }\r
- ;\r
-\r
-method_header\r
- : opt_attributes\r
- opt_modifiers\r
- type\r
- member_name\r
- OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
- {\r
- Method method = new Method ((string) $3, (int) $2, (string) $4, (Parameters) $6);\r
-\r
- current_local_parameters = (Parameters) $6;\r
-\r
- $$ = method;\r
- }\r
- | opt_attributes\r
- opt_modifiers\r
- VOID\r
- member_name\r
- OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
- {\r
- Method method = new Method ("void", (int) $2, (string) $4, (Parameters) $6);\r
-\r
- current_local_parameters = (Parameters) $6;\r
- $$ = method;\r
- }\r
- ;\r
-\r
-method_body\r
- : block\r
- | SEMICOLON { $$ = null; }\r
- ;\r
-\r
-opt_formal_parameter_list\r
- : /* empty */ { $$ = new Parameters (null, null); }\r
- | formal_parameter_list\r
- ;\r
-\r
-formal_parameter_list\r
- : fixed_parameters \r
- { \r
- $$ = new Parameters ((ParameterCollection) $1, null); \r
- } \r
- | fixed_parameters COMMA parameter_array\r
- {\r
- $$ = new Parameters ((ParameterCollection) $1, (Parameter) $3); \r
- }\r
- | parameter_array \r
- {\r
- $$ = new Parameters (null, (Parameter) $1);\r
- }\r
- ;\r
-\r
-fixed_parameters\r
- : fixed_parameter \r
- {\r
- ParameterCollection pars = new ParameterCollection ();\r
- pars.Add ((Parameter) $1);\r
- $$ = pars;\r
- }\r
- | fixed_parameters COMMA fixed_parameter\r
- {\r
- ParameterCollection pars = (ParameterCollection) $1;\r
- pars.Add ((Parameter) $3);\r
- $$ = $1;\r
- }\r
- ;\r
-\r
-fixed_parameter\r
- : opt_attributes\r
- opt_parameter_modifier\r
- type\r
- IDENTIFIER\r
- {\r
- $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2);\r
- }\r
- ;\r
-\r
-opt_parameter_modifier\r
- : /* empty */ { $$ = Parameter.Modifier.NONE; }\r
- | parameter_modifier\r
- ;\r
-\r
-parameter_modifier\r
- : REF { $$ = Parameter.Modifier.REF; }\r
- | OUT { $$ = Parameter.Modifier.OUT; }\r
- ;\r
-\r
-parameter_array\r
- : opt_attributes PARAMS type IDENTIFIER\r
- { \r
- $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS);\r
- note ("type must be a single-dimension array type"); \r
- }\r
- ;\r
-\r
-member_name \r
- : IDENTIFIER { $$ = $1.ToString (); }\r
- | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }\r
- ;\r
-\r
-property_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- type member_name\r
- OPEN_BRACE \r
- {\r
- Parameter implicit_value_parameter;\r
- implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE);\r
-\r
- lexer.properties = true;\r
- \r
- implicit_value_parameters = new ParameterCollection ();\r
- implicit_value_parameters.Add (implicit_value_parameter);\r
- }\r
- accessor_declarations \r
- {\r
- lexer.properties = false;\r
- }\r
- CLOSE_BRACE\r
- { \r
- Property prop;\r
- DictionaryEntry pair = (DictionaryEntry) $7;\r
- Block get_block = null;\r
- Block set_block = null;\r
-\r
- if (pair.Key != null)\r
- get_block = (Block) pair.Key;\r
- if (pair.Value != null)\r
- set_block = (Block) pair.Value;\r
-\r
- prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block);\r
- \r
- CheckDef (current_container.AddProperty (prop), prop.Name);\r
- implicit_value_parameters = null;\r
- }\r
- ;\r
-\r
-accessor_declarations\r
- : get_accessor_declaration opt_set_accessor_declaration\r
- { \r
- $$ = new DictionaryEntry ($1, $2);\r
- }\r
- | set_accessor_declaration opt_get_accessor_declaration\r
- {\r
- $$ = new DictionaryEntry ($2, $1);\r
- }\r
- ;\r
-\r
-opt_get_accessor_declaration\r
- : /* empty */ { $$ = null; }\r
- | get_accessor_declaration\r
- ;\r
-\r
-opt_set_accessor_declaration\r
- : /* empty */ { $$ = null; }\r
- | set_accessor_declaration\r
- ;\r
-\r
-get_accessor_declaration\r
- : opt_attributes GET accessor_body \r
- {\r
- $$ = $3;\r
- }\r
- ;\r
-\r
-set_accessor_declaration\r
- : opt_attributes SET \r
- { \r
- current_local_parameters = new Parameters (implicit_value_parameters, null);\r
- }\r
- accessor_body\r
- {\r
- $$ = $4;\r
- current_local_parameters = null;\r
- }\r
- ;\r
-\r
-accessor_body\r
- : block \r
- | SEMICOLON { $$ = new Block (null); }\r
- ;\r
-\r
-interface_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- INTERFACE IDENTIFIER\r
- {\r
- Interface new_interface;\r
- string full_interface_name = MakeName ((string) $4);\r
-\r
- new_interface = new Interface (current_container, full_interface_name, (int) $2);\r
- if (current_interface != null)\r
- error (-2, "Internal compiler error: interface inside interface");\r
- current_interface = new_interface;\r
- tree.RecordInterface (full_interface_name, new_interface);\r
- }\r
- opt_interface_base\r
- interface_body\r
- { \r
- Interface new_interface = (Interface) current_interface;\r
-\r
- if ($6 != null)\r
- new_interface.Bases = (ArrayList) $6;\r
-\r
- current_interface = null;\r
- CheckDef (current_container.AddInterface (new_interface), new_interface.Name);\r
- }\r
- ;\r
-\r
-opt_interface_base\r
- : /* empty */ { $$ = null; }\r
- | interface_base\r
- ;\r
-\r
-interface_base\r
- : COLON interface_type_list { $$ = $2; }\r
- ;\r
-\r
-interface_type_list\r
- : interface_type\r
- {\r
- ArrayList interfaces = new ArrayList ();\r
-\r
- interfaces.Add ($1);\r
- $$ = interfaces;\r
- }\r
- | interface_type_list COMMA interface_type\r
- {\r
- ArrayList interfaces = (ArrayList) $1;\r
- interfaces.Add ($3);\r
- $$ = interfaces;\r
- }\r
- ;\r
-\r
-interface_body\r
- : OPEN_BRACE\r
- opt_interface_member_declarations\r
- CLOSE_BRACE\r
- ;\r
-\r
-opt_interface_member_declarations\r
- : /* empty */\r
- | interface_member_declarations\r
- ;\r
-\r
-interface_member_declarations\r
- : interface_member_declaration\r
- | interface_member_declarations interface_member_declaration\r
- ;\r
-\r
-interface_member_declaration\r
- : interface_method_declaration \r
- { \r
- InterfaceMethod m = (InterfaceMethod) $1;\r
-\r
- CheckDef (current_interface.AddMethod (m), m.Name);\r
- }\r
- | interface_property_declaration \r
- { \r
- InterfaceProperty p = (InterfaceProperty) $1;\r
-\r
- CheckDef (current_interface.AddProperty (p), p.Name);\r
- }\r
- | interface_event_declaration \r
- { \r
- InterfaceEvent e = (InterfaceEvent) $1;\r
-\r
- CheckDef (current_interface.AddEvent (e), e.Name);\r
- }\r
- | interface_indexer_declaration\r
- { \r
- InterfaceIndexer i = (InterfaceIndexer) $1;\r
-\r
- CheckDef (current_interface.AddIndexer (i), "indexer");\r
- }\r
- ;\r
-\r
-opt_new\r
- : /* empty */ { $$ = false; }\r
- | NEW { $$ = true; }\r
- ;\r
-\r
-interface_method_declaration\r
- : opt_attributes opt_new type IDENTIFIER \r
- OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS\r
- SEMICOLON\r
- {\r
- $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6);\r
- }\r
- | opt_attributes opt_new VOID IDENTIFIER \r
- OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS\r
- SEMICOLON\r
- {\r
- $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6);\r
- }\r
- ;\r
-\r
-interface_property_declaration\r
- : opt_attributes\r
- opt_new\r
- type IDENTIFIER \r
- OPEN_BRACE \r
- { lexer.properties = true; }\r
- interface_accesors \r
- { lexer.properties = false; }\r
- CLOSE_BRACE\r
- {\r
- int gs = (int) $7;\r
-\r
- $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2, \r
- (gs & 1) == 1, (gs & 2) == 2);\r
- }\r
- ;\r
-\r
-interface_accesors\r
- : opt_attributes GET SEMICOLON { $$ = 1; }\r
- | opt_attributes SET SEMICOLON { $$ = 2; }\r
- | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON \r
- { $$ = 3; }\r
- | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON\r
- { $$ = 3; }\r
- ;\r
-\r
-interface_event_declaration\r
- : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON\r
- {\r
- $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2);\r
- }\r
- ;\r
-\r
-interface_indexer_declaration \r
- : opt_attributes opt_new type THIS \r
- OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
- OPEN_BRACE \r
- { lexer.properties = true; }\r
- interface_accesors \r
- { lexer.properties = false; }\r
- CLOSE_BRACE\r
- {\r
- int a_flags = (int) $10;\r
-\r
- bool do_get = (a_flags & 1) == 1;\r
- bool do_set = (a_flags & 2) == 2;\r
-\r
- $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2);\r
- }\r
- ;\r
-\r
-operator_declaration\r
- : opt_attributes opt_modifiers operator_declarator block\r
- {\r
- // FIXME: validate that opt_modifiers is exactly: PUBLIC and STATIC\r
- }\r
- ;\r
-\r
-operator_declarator\r
- : type OPERATOR overloadable_operator \r
- OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
- {\r
- // FIXME: since reduce/reduce on this\r
- // rule, validate overloadable_operator is unary\r
- }\r
- | type OPERATOR overloadable_operator\r
- OPEN_PARENS \r
- type IDENTIFIER COMMA\r
- type IDENTIFIER \r
- CLOSE_PARENS\r
- {\r
- // FIXME: because of the reduce/reduce on PLUS and MINUS\r
- // validate overloadable_operator is binary\r
- }\r
- | conversion_operator_declarator\r
- ;\r
-\r
-overloadable_operator\r
-// Unary operators:\r
- : BANG\r
- | TILDE\r
- | OP_INC\r
- | OP_DEC\r
- | TRUE\r
- | FALSE\r
-// Unary and binary:\r
- | PLUS \r
- | MINUS\r
-// Binary:\r
- | STAR \r
- | DIV \r
- | PERCENT \r
- | BITWISE_AND \r
- | BITWISE_OR \r
- | CARRET \r
- | OP_SHIFT_LEFT\r
- | OP_SHIFT_RIGHT\r
- | OP_EQ\r
- | OP_NE\r
- | OP_GT\r
- | OP_LT\r
- | OP_GE\r
- | OP_LE\r
- ;\r
-\r
-conversion_operator_declarator\r
- : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
- | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS\r
- ;\r
-\r
-constructor_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- constructor_declarator\r
- block\r
- { \r
- Constructor c = (Constructor) $3;\r
- c.Block = (Block) $4;\r
- c.ModFlags = (int) $2;\r
-\r
- if ((c.ModFlags & Modifiers.STATIC) != 0){\r
- if ((c.ModFlags & Modifiers.Accessibility) != 0){\r
- error (515, "Access modifiers are not allowed on static constructors");\r
- }\r
- }\r
- CheckDef (current_container.AddConstructor (c), c.Name);\r
-\r
- current_local_parameters = null;\r
- }\r
- ;\r
-\r
-constructor_declarator\r
- : IDENTIFIER \r
- OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS \r
- opt_constructor_initializer\r
- {\r
- ConstructorInitializer i = null;\r
-\r
- if ($5 != null)\r
- i = (ConstructorInitializer) $5;\r
-\r
- $$ = new Constructor ((string) $1, (Parameters) $3, i);\r
- \r
- current_local_parameters = (Parameters) $3;\r
- }\r
- ;\r
-\r
-opt_constructor_initializer\r
- : /* empty */ { $$ = null; }\r
- | constructor_initializer\r
- ;\r
-\r
-constructor_initializer\r
- : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS\r
- {\r
- $$ = new ConstructorBaseInitializer ((ArrayList) $4);\r
- }\r
- | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS\r
- {\r
- $$ = new ConstructorThisInitializer ((ArrayList) $4);\r
- }\r
- ;\r
-\r
-destructor_declaration\r
- : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block\r
- {\r
- Method d = new Method ("System.Void", 0, "Finalize", new Parameters (null, null));\r
-\r
- d.Block = (Block) $6;\r
- CheckDef (current_container.AddMethod (d), d.Name);\r
- }\r
- ;\r
-\r
-event_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- EVENT type variable_declarators SEMICOLON\r
- { note ("validate that the flags only contain new public protected internal private static virtual sealed override abstract"); }\r
- | opt_attributes\r
- opt_modifiers\r
- EVENT type member_name \r
- OPEN_BRACE event_accesor_declarations CLOSE_BRACE SEMICOLON\r
- { note ("validate that the flags only contain new public protected internal private static virtual sealed override abstract"); }\r
- ;\r
-\r
-event_accesor_declarations\r
- : add_accessor_declaration remove_accessor_declaration\r
- | remove_accessor_declaration add_accessor_declaration\r
- ;\r
-\r
-add_accessor_declaration\r
- : opt_attributes ADD block\r
- ;\r
-\r
-remove_accessor_declaration\r
- : opt_attributes REMOVE block\r
- ;\r
-\r
-indexer_declaration\r
- : opt_attributes opt_modifiers indexer_declarator \r
- OPEN_BRACE \r
- { lexer.properties = true; }\r
- accessor_declarations \r
- { lexer.properties = false; }\r
- CLOSE_BRACE\r
- { \r
- // The signature is computed from the signature of the indexer. Look\r
- // at section 3.6 on the spec\r
- note ("verify modifiers are NEW PUBLIC PROTECTED INTERNAL PRIVATE VIRTUAL SEALED OVERRIDE ABSTRACT"); \r
- }\r
- ;\r
-\r
-indexer_declarator\r
- : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
- | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET\r
- ;\r
-\r
-enum_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- ENUM IDENTIFIER\r
- opt_enum_base\r
- enum_body\r
- opt_semicolon\r
- { \r
- string name = (string) $4;\r
- Enum e = new Enum ((string) $5, (int) $2, name);\r
-\r
- foreach (VariableDeclaration ev in (ArrayList) $6){\r
- CheckDef (\r
- e.AddEnum (\r
- ev.identifier, \r
- (Expression) ev.expression_or_array_initializer),\r
- ev.identifier);\r
- }\r
-\r
- CheckDef (current_container.AddEnum (e), name);\r
- }\r
- ;\r
-\r
-opt_enum_base\r
- : /* empty */ { $$ = "System.Int32"; }\r
- | COLON integral_type { $$ = $2; }\r
- ;\r
-\r
-enum_body\r
- : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE\r
- {\r
- $$ = $2;\r
- }\r
- ;\r
-\r
-opt_enum_member_declarations\r
- : /* empty */ { $$ = new ArrayList (); }\r
- | enum_member_declarations opt_comma { $$ = $1; }\r
- ;\r
-\r
-enum_member_declarations\r
- : enum_member_declaration \r
- {\r
- ArrayList l = new ArrayList ();\r
-\r
- l.Add ($1);\r
- $$ = l;\r
- }\r
- | enum_member_declarations COMMA enum_member_declaration\r
- {\r
- ArrayList l = (ArrayList) $1;\r
-\r
- l.Add ($3);\r
-\r
- $$ = l;\r
- }\r
- ;\r
-\r
-enum_member_declaration\r
- : opt_attributes IDENTIFIER \r
- {\r
- $$ = new VariableDeclaration ((string) $2, null);\r
- }\r
- | opt_attributes IDENTIFIER ASSIGN expression\r
- { \r
- $$ = new VariableDeclaration ((string) $2, $4);\r
- }\r
- ;\r
-\r
-delegate_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- DELEGATE type \r
- IDENTIFIER OPEN_PARENS \r
- formal_parameter_list\r
- CLOSE_PARENS \r
- SEMICOLON\r
- { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }\r
-\r
- | opt_attributes\r
- opt_modifiers\r
- DELEGATE VOID \r
- IDENTIFIER OPEN_PARENS \r
- formal_parameter_list\r
- CLOSE_PARENS \r
- SEMICOLON\r
- { note ("validate that modifiers only contains NEW PUBLIC PROTECTED INTERNAL PRIVATE"); }\r
- ;\r
-\r
-type_name\r
- : namespace_or_type_name\r
- ;\r
-\r
-namespace_or_type_name\r
- : qualified_identifier\r
- ;\r
-\r
-/* \r
- * Before you think of adding a return_type, notice that we have been\r
- * using two rules in the places where it matters (one rule using type\r
- * and another identical one that uses VOID as the return type). This\r
- * gets rid of a shift/reduce couple\r
- */\r
-type\r
- : type_name { /* class_type */\r
- /* \r
- This does interfaces, delegates, struct_types, class_types, \r
- parent classes, and more! 4.2 \r
- */\r
- $$ = $1; \r
- }\r
- | builtin_types\r
- | array_type\r
- ;\r
-\r
-type_list\r
- : type\r
- {\r
- ArrayList types = new ArrayList ();\r
-\r
- types.Add ($1);\r
- $$ = types;\r
- }\r
- | type_list COMMA type\r
- {\r
- ArrayList types = (ArrayList) $1;\r
-\r
- types.Add ($3);\r
- $$ = types;\r
- }\r
- ;\r
-\r
-/*\r
- * replaces all the productions for isolating the various\r
- * simple types, but we need this to reuse it easily in local_variable_type\r
- */\r
-builtin_types\r
- : OBJECT { $$ = "System.Object"; }\r
- | STRING { $$ = "System.String"; }\r
- | BOOL { $$ = "System.Boolean"; }\r
- | DECIMAL { $$ = "System.Decimal"; }\r
- | FLOAT { $$ = "System.Single"; }\r
- | DOUBLE { $$ = "System.Double"; }\r
- | integral_type\r
- ;\r
-\r
-integral_type\r
- : SBYTE { $$ = "System.SByte"; }\r
- | BYTE { $$ = "System.Byte"; }\r
- | SHORT { $$ = "System.Int16"; }\r
- | USHORT { $$ = "System.UInt16"; }\r
- | INT { $$ = "System.Int32"; }\r
- | UINT { $$ = "System.UInt32"; }\r
- | LONG { $$ = "System.Int64"; }\r
- | ULONG { $$ = "System.UInt64"; }\r
- | CHAR { $$ = "System.Char"; }\r
- ;\r
-\r
-interface_type\r
- : type_name\r
- ;\r
-\r
-array_type\r
- : type rank_specifiers\r
- {\r
- $$ = $1;\r
- // FIXME: We need to create a type for the nested thing.\r
- }\r
- ;\r
-\r
-//\r
-// Expressions, section 7.5\r
-//\r
-primary_expression\r
- : literal\r
- {\r
- // 7.5.1: Literals\r
- \r
- }\r
- \r
- | qualified_identifier\r
- {\r
- string name = (string) $1;\r
-\r
- $$ = null;\r
- if (name.IndexOf ('.') == -1){\r
- //\r
- // we need to check against current_block not being null\r
- // as `expression' is allowed in argument_lists, which \r
- // do not exist inside a block. \r
- //\r
- if (current_block != null){\r
- if (current_block.IsVariableDefined (name))\r
- $$ = new LocalVariableReference (current_block, name);\r
- }\r
- if (($$ == null) && (current_local_parameters != null)){\r
- Parameter par = current_local_parameters.GetParameterByName (name);\r
- if (par != null)\r
- $$ = new ParameterReference (current_local_parameters, name);\r
- }\r
- }\r
- if ($$ == null)\r
- $$ = new SimpleName (name);\r
- }\r
- | parenthesized_expression\r
- | member_access\r
- | invocation_expression\r
- | element_access\r
- | this_access\r
- | base_access\r
- | post_increment_expression\r
- | post_decrement_expression\r
- | new_expression\r
- | typeof_expression\r
- | sizeof_expression\r
- | checked_expression\r
- | unchecked_expression\r
- ;\r
-\r
-literal\r
- : boolean_literal\r
- | integer_literal\r
- | real_literal\r
- | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }\r
- | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }\r
- | NULL { $$ = new NullLiteral (); }\r
- ;\r
-\r
-real_literal\r
- : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }\r
- | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }\r
- | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }\r
- ;\r
-\r
-integer_literal\r
- : LITERAL_INTEGER { $$ = new IntLiteral ((Int32) lexer.Value); }\r
- ;\r
-\r
-boolean_literal\r
- : TRUE { $$ = new BoolLiteral (true); }\r
- | FALSE { $$ = new BoolLiteral (false); }\r
- ;\r
-\r
-parenthesized_expression\r
- : OPEN_PARENS expression CLOSE_PARENS\r
- { $$ = $2; }\r
- ;\r
-\r
-member_access\r
- : primary_expression DOT IDENTIFIER\r
- {\r
- $$ = new MemberAccess ((Expression) $1, (string) $3);\r
- }\r
- | predefined_type DOT IDENTIFIER\r
- {\r
- $$ = new BuiltinTypeAccess ((string) $1, (string) $3);\r
- }\r
- ;\r
-\r
-predefined_type\r
- : builtin_types\r
- ;\r
-\r
-invocation_expression\r
- : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS\r
- {\r
- // FIXME:\r
- // if $1 is MethodGroup\r
- // $$ = new Call ($1, $3);\r
- // else \r
- // $$ = new DelegateCall ($1, $3);\r
- if ($1 == null)\r
- error (1, "THIS IS CRAZY");\r
-\r
- $$ = new Invocation ((Expression) $1, (ArrayList) $3);\r
- }\r
- ; \r
-\r
-opt_argument_list\r
- : /* empty */ { $$ = new ArrayList (); }\r
- | argument_list\r
- ;\r
-\r
-argument_list\r
- : argument \r
- { \r
- ArrayList list = new ArrayList ();\r
- list.Add ($1);\r
- $$ = list;\r
- }\r
- | argument_list COMMA argument\r
- {\r
- ArrayList list = (ArrayList) $1;\r
- list.Add ($3);\r
- $$ = list;\r
- }\r
- ;\r
-\r
-argument\r
- : expression\r
- {\r
- $$ = new Argument ((Expression) $1, Argument.AType.Expression);\r
- }\r
- | REF variable_reference \r
- { \r
- $$ = new Argument ((Expression) $2, Argument.AType.Ref);\r
- }\r
- | OUT variable_reference \r
- { \r
- $$ = new Argument ((Expression) $2, Argument.AType.Out);\r
- }\r
- ;\r
-\r
-variable_reference\r
- : expression { note ("section 5.4"); $$ = $1; }\r
- ;\r
-\r
-element_access\r
- : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET \r
- // finishme\r
- ;\r
-\r
-expression_list\r
- : expression\r
- | expression_list COMMA expression\r
- ;\r
-\r
-this_access\r
- : THIS\r
- {\r
- $$ = new This ();\r
- }\r
- ;\r
-\r
-base_access\r
- : BASE DOT IDENTIFIER\r
- // finishme\r
- | BASE OPEN_BRACKET expression_list CLOSE_BRACKET\r
- // finishme\r
- ;\r
-\r
-post_increment_expression\r
- : primary_expression OP_INC\r
- {\r
- $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1);\r
- }\r
- ;\r
-\r
-post_decrement_expression\r
- : primary_expression OP_DEC\r
- {\r
- $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1);\r
- }\r
- ;\r
-\r
-new_expression\r
- : object_or_delegate_creation_expression\r
- | array_creation_expression\r
- ;\r
-\r
-object_or_delegate_creation_expression\r
- : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS\r
- {\r
- $$ = new New ((string) $2, (ArrayList) $4);\r
- }\r
- ;\r
-\r
-array_creation_expression\r
- : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET \r
- opt_rank_specifier\r
- opt_array_initializer\r
- // finishme\r
- ;\r
-\r
-opt_rank_specifier\r
- : /* empty */\r
- | rank_specifiers\r
- ;\r
-\r
-rank_specifiers\r
- : rank_specifier\r
- | rank_specifier rank_specifiers\r
- // finishme\r
- ;\r
-\r
-rank_specifier\r
- : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
- // finishme\r
- ;\r
-\r
-opt_dim_separators\r
- : /* empty */\r
- | dim_separators\r
- // finishme\r
- ;\r
-\r
-dim_separators\r
- : COMMA\r
- | dim_separators COMMA\r
- // finishme\r
- ;\r
-\r
-opt_array_initializer\r
- : /* empty */\r
- | array_initializer\r
- ;\r
-\r
-array_initializer\r
- : OPEN_BRACE CLOSE_BRACE\r
- | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE\r
- // finishme\r
- ;\r
-\r
-variable_initializer_list\r
- : variable_initializer\r
- | variable_initializer_list COMMA variable_initializer\r
- // finishme\r
- ;\r
-\r
-typeof_expression\r
- : TYPEOF OPEN_PARENS type CLOSE_PARENS\r
- {\r
- $$ = new TypeOf ((string) $3);\r
- }\r
- ;\r
-\r
-sizeof_expression\r
- : SIZEOF OPEN_PARENS type CLOSE_PARENS { \r
- $$ = new SizeOf ((string) $3);\r
-\r
- note ("Verify type is unmanaged"); \r
- note ("if (5.8) builtin, yield constant expression");\r
- }\r
- ;\r
-\r
-checked_expression\r
- : CHECKED OPEN_PARENS expression CLOSE_PARENS\r
- ;\r
-\r
-unchecked_expression\r
- : UNCHECKED OPEN_PARENS expression CLOSE_PARENS\r
- ;\r
-\r
-unary_expression\r
- : primary_expression\r
- | PLUS unary_expression { \r
- $$ = new Unary (Unary.Operator.Plus, (Expression) $2);\r
- } \r
- | MINUS unary_expression \r
- { \r
- $$ = new Unary (Unary.Operator.Minus, (Expression) $2);\r
- }\r
- | BANG unary_expression \r
- {\r
- $$ = new Unary (Unary.Operator.Negate, (Expression) $2);\r
- }\r
- | TILDE unary_expression\r
- {\r
- $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2);\r
- }\r
- | STAR unary_expression\r
- {\r
- $$ = new Unary (Unary.Operator.Indirection, (Expression) $2);\r
- }\r
- | BITWISE_AND unary_expression\r
- {\r
- $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);\r
- }\r
- | OP_INC unary_expression \r
- {\r
- $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);\r
- }\r
- | OP_DEC unary_expression \r
- {\r
- $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);\r
- }\r
- | cast_expression \r
- /*\r
- we can not do cast expressions at this level,\r
- as there is an ambiguity. Check "Cast Expressions" 7.6.8\r
- for the recipe to handle this.\r
- */\r
- ;\r
-\r
-pre_increment_expression\r
- : OP_INC unary_expression \r
- {\r
- $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2);\r
- }\r
- ;\r
-\r
-pre_decrement_expression\r
- : OP_DEC unary_expression \r
- {\r
- $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2);\r
- }\r
- ;\r
-\r
-cast_expression\r
- /* \r
- * FIXME: This is actually wrong, it should be `type' but that\r
- * introduces a lot of {shift,reduce}/reduces\r
- *\r
- * This is really really wrong. We need to track down\r
- * the source of problems with QIs because expressions like:\r
- * foreach (string s in (string []) object) wont be parsed.\r
- */\r
- : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression\r
- {\r
- $$ = new Cast ((string) $2, (Expression) $4);\r
- }\r
- | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression\r
- {\r
- $$ = new Cast ((string) $2, (Expression) $4);\r
- }\r
- ;\r
-\r
-multiplicative_expression\r
- : unary_expression\r
- | multiplicative_expression STAR unary_expression\r
- {\r
- $$ = new Binary (Binary.Operator.Multiply, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | multiplicative_expression DIV unary_expression\r
- {\r
- $$ = new Binary (Binary.Operator.Divide, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | multiplicative_expression PERCENT unary_expression \r
- {\r
- $$ = new Binary (Binary.Operator.Modulo, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ;\r
-\r
-additive_expression\r
- : multiplicative_expression\r
- | additive_expression PLUS multiplicative_expression \r
- {\r
- $$ = new Binary (Binary.Operator.Add, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | additive_expression MINUS multiplicative_expression\r
- {\r
- $$ = new Binary (Binary.Operator.Substract, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ;\r
-\r
-shift_expression\r
- : additive_expression\r
- | shift_expression OP_SHIFT_LEFT additive_expression\r
- {\r
- $$ = new Binary (Binary.Operator.ShiftLeft, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | shift_expression OP_SHIFT_RIGHT additive_expression\r
- {\r
- $$ = new Binary (Binary.Operator.ShiftRight, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ; \r
-\r
-relational_expression\r
- : shift_expression\r
- | relational_expression OP_LT shift_expression\r
- {\r
- $$ = new Binary (Binary.Operator.LessThan, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | relational_expression OP_GT shift_expression\r
- {\r
- $$ = new Binary (Binary.Operator.GreatherThan, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | relational_expression OP_LE shift_expression\r
- {\r
- $$ = new Binary (Binary.Operator.LessOrEqual, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | relational_expression OP_GE shift_expression\r
- {\r
- $$ = new Binary (Binary.Operator.GreatherOrEqual, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | relational_expression IS type\r
- {\r
- $$ = new Probe (Probe.Operator.Is, \r
- (Expression) $1, (string) $3);\r
- }\r
- | relational_expression AS type\r
- {\r
- $$ = new Probe (Probe.Operator.As, \r
- (Expression) $1, (string) $3);\r
- }\r
- ;\r
-\r
-equality_expression\r
- : relational_expression\r
- | equality_expression OP_EQ relational_expression\r
- {\r
- $$ = new Binary (Binary.Operator.Equal, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- | equality_expression OP_NE relational_expression\r
- {\r
- $$ = new Binary (Binary.Operator.NotEqual, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ; \r
-\r
-and_expression\r
- : equality_expression\r
- | and_expression BITWISE_AND equality_expression\r
- {\r
- $$ = new Binary (Binary.Operator.BitwiseAnd, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ;\r
-\r
-exclusive_or_expression\r
- : and_expression\r
- | exclusive_or_expression CARRET and_expression\r
- {\r
- $$ = new Binary (Binary.Operator.ExclusiveOr, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ;\r
-\r
-inclusive_or_expression\r
- : exclusive_or_expression\r
- | inclusive_or_expression BITWISE_OR exclusive_or_expression\r
- {\r
- $$ = new Binary (Binary.Operator.BitwiseOr, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ;\r
-\r
-conditional_and_expression\r
- : inclusive_or_expression\r
- | conditional_and_expression OP_AND inclusive_or_expression\r
- {\r
- $$ = new Binary (Binary.Operator.LogicalAnd, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ;\r
-\r
-conditional_or_expression\r
- : conditional_and_expression\r
- | conditional_or_expression OP_OR conditional_and_expression\r
- {\r
- $$ = new Binary (Binary.Operator.LogicalOr, \r
- (Expression) $1, (Expression) $3);\r
- }\r
- ;\r
-\r
-conditional_expression\r
- : conditional_or_expression\r
- | conditional_or_expression INTERR expression COLON expression \r
- {\r
- $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);\r
- }\r
- ;\r
-\r
-assignment_expression\r
- : unary_expression ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1, (Expression) $3);\r
- }\r
- | unary_expression OP_MULT_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.Multiply, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_DIV_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.Divide, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_MOD_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.Modulo, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_ADD_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.Add, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_SUB_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.Substract, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_SHIFT_LEFT_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.ShiftLeft, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_SHIFT_RIGHT_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.ShiftRight, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_AND_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.BitwiseAnd, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_OR_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.BitwiseOr, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- | unary_expression OP_XOR_ASSIGN expression\r
- {\r
- $$ = new Assign ((Expression) $1,\r
- new Binary (Binary.Operator.ExclusiveOr, \r
- (Expression) $1,\r
- (Expression) $3));\r
- }\r
- ;\r
-\r
-expression\r
- : conditional_expression\r
- | assignment_expression\r
- ;\r
-\r
-constant_expression\r
- : expression\r
- ;\r
-\r
-boolean_expression\r
- : expression { CheckBoolean ((Expression) $1); $$ = $1; } \r
- ;\r
-\r
-//\r
-// 10 classes\r
-//\r
-class_declaration\r
- : opt_attributes\r
- opt_modifiers\r
- CLASS IDENTIFIER\r
- {\r
- Class new_class;\r
- string full_class_name = MakeName ((string) $4);\r
-\r
- new_class = new Class (current_container, full_class_name, (int) $2);\r
- current_container = new_class;\r
- current_container.Namespace = current_namespace;\r
- tree.RecordClass (full_class_name, new_class);\r
- }\r
- opt_class_base\r
- class_body \r
- opt_semicolon \r
- {\r
- Class new_class = (Class) current_container;\r
-\r
- if ($6 != null)\r
- new_class.Bases = (ArrayList) $6;\r
-\r
- current_container = current_container.Parent;\r
- CheckDef (current_container.AddClass (new_class), new_class.Name);\r
-\r
- $$ = new_class;\r
- }\r
- ; \r
-\r
-opt_modifiers\r
- : /* empty */ { $$ = (int) 0; }\r
- | modifiers\r
- ;\r
-\r
-modifiers\r
- : modifier\r
- | modifiers modifier { \r
- int m1 = (int) $1;\r
- int m2 = (int) $2;\r
-\r
- if ((m1 & m2) != 0)\r
- error (1002, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");\r
-\r
- $$ = (int) (m1 | m2);\r
- }\r
- ;\r
-\r
-modifier\r
- : NEW { $$ = Modifiers.NEW; }\r
- | PUBLIC { $$ = Modifiers.PUBLIC; }\r
- | PROTECTED { $$ = Modifiers.PROTECTED; }\r
- | INTERNAL { $$ = Modifiers.INTERNAL; }\r
- | PRIVATE { $$ = Modifiers.PRIVATE; }\r
- | ABSTRACT { $$ = Modifiers.ABSTRACT; }\r
- | SEALED { $$ = Modifiers.SEALED; }\r
- | STATIC { $$ = Modifiers.STATIC; }\r
- | READONLY { $$ = Modifiers.READONLY; }\r
- | VIRTUAL { $$ = Modifiers.VIRTUAL; }\r
- | OVERRIDE { $$ = Modifiers.OVERRIDE; }\r
- | EXTERN { $$ = Modifiers.EXTERN; }\r
- ;\r
-\r
-opt_class_base\r
- : /* empty */ { $$ = null; }\r
- | class_base { $$ = $1; }\r
- ;\r
-\r
-class_base\r
- : COLON type_list { $$ = $2; }\r
- ;\r
-\r
-//\r
-// Statements (8.2)\r
-//\r
-\r
-//\r
-// A block is "contained" on the following places:\r
-// method_body\r
-// property_declaration as part of the accessor body (get/set)\r
-// operator_declaration\r
-// constructor_declaration\r
-// destructor_declaration\r
-// event_declaration as part of add_accessor_declaration or remove_accessor_declaration\r
-// \r
-block\r
- : OPEN_BRACE \r
- {\r
- current_block = new Block (current_block);\r
- } \r
- opt_statement_list CLOSE_BRACE \r
- { \r
- while (current_block.Implicit)\r
- current_block = current_block.Parent;\r
- $$ = current_block;\r
- current_block = current_block.Parent;\r
- }\r
- ;\r
-\r
-opt_statement_list\r
- : /* empty */\r
- | statement_list \r
- ;\r
-\r
-statement_list\r
- : statement\r
- | statement_list statement\r
- ;\r
-\r
-statement\r
- : declaration_statement\r
- {\r
- if ((Block) $1 != current_block){\r
- current_block.AddStatement ((Statement) $1);\r
- current_block = (Block) $1;\r
- }\r
- }\r
- | embedded_statement\r
- {\r
- current_block.AddStatement ((Statement) $1);\r
- }\r
- | labeled_statement \r
- {\r
- current_block.AddStatement ((Statement) $1);\r
- }\r
- ;\r
-\r
-embedded_statement\r
- : block\r
- | empty_statement\r
- | expression_statement\r
- | selection_statement\r
- | iteration_statement\r
- | jump_statement \r
- | try_statement\r
- | checked_statement\r
- | unchecked_statement\r
- | lock_statement\r
- | using_statement\r
- ;\r
-\r
-empty_statement\r
- : SEMICOLON\r
- {\r
- $$ = new EmptyStatement ();\r
- }\r
- ;\r
-\r
-labeled_statement\r
- : IDENTIFIER COLON statement\r
- {\r
- string lab = (String) $1;\r
- Block block;\r
-\r
- block = new Block (current_block, lab);\r
- block.AddStatement ((Statement) $3);\r
- $$ = block;\r
-\r
- if (!current_block.AddLabel (lab, block)){\r
- error (140, "The label '" + lab + "' is a duplicate");\r
- $$ = $3;\r
- } \r
- }\r
- ;\r
-\r
-declaration_statement\r
- : local_variable_declaration SEMICOLON // done\r
- | local_constant_declaration SEMICOLON // finishme\r
- ;\r
-\r
-/* \r
- * The following is from Rhys' grammar:\r
- * > Types in local variable declarations must be recognized as \r
- * > expressions to prevent reduce/reduce errors in the grammar.\r
- * > The expressions are converted into types during semantic analysis.\r
- */\r
-local_variable_type\r
- : primary_expression type_suffixes\r
- { \r
- // FIXME: Do something smart here regarding the composition of the type.\r
- //\r
-\r
- // Ok, the above "primary_expression" is there to get rid of\r
- // both reduce/reduce and shift/reduces in the grammar, it should\r
- // really just be "type_name". If you use type_name, a reduce/reduce\r
- // creeps up. If you use qualified_identifier (which is all we need\r
- // really) two shift/reduces appear.\r
- // \r
- // So, instead we do a super trick: we just allow ($1) to be a \r
- // SimpleName Expression.\r
- //\r
- if (((Expression) $1) is SimpleName)\r
- $$ = ((SimpleName) $1).Name;\r
- else {\r
- error (-1, "Invalid Type definition");\r
- $$ = "System.Object";\r
- }\r
- }\r
- | builtin_types type_suffixes\r
- {\r
- // FIXME: Do something smart with the type here.\r
- $$ = $1; \r
- }\r
- | VOID type_suffixes\r
- {\r
- // FIXME: this is a string that represents the type\r
- // Figure out something to make this work.\r
- $$ = "VOID SOMETHING TYPE FIXME";\r
- }\r
- ;\r
-\r
-type_suffixes\r
- : /* empty */\r
- | type_suffix_list\r
- ;\r
-\r
-type_suffix_list \r
- : type_suffix\r
- | type_suffix_list type_suffix\r
- ;\r
-\r
-type_suffix\r
- : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET\r
- /* FIXME: | MULTIPLY */\r
- ;\r
-\r
-local_variable_declaration\r
- : local_variable_type variable_declarators\r
- {\r
- $$ = declare_local_variables ((string) $1, (ArrayList) $2);\r
- }\r
- ;\r
-\r
-local_constant_declaration\r
- : CONST type constant_declarator\r
- // finishme \r
- ;\r
-\r
-expression_statement\r
- : statement_expression SEMICOLON\r
- {\r
- $$ = $1;\r
- }\r
- ;\r
-\r
- //\r
- // We have to do the wrapping here and not in the case above,\r
- // because statement_expression is used for example in for_statement\r
- //\r
-statement_expression\r
- : invocation_expression { $$ = new StatementExpression ((Expression) $1); }\r
- | object_creation_expression { $$ = new StatementExpression ((Expression) $1); }\r
- | assignment_expression { $$ = new StatementExpression ((Expression) $1); }\r
- | post_increment_expression { $$ = new StatementExpression ((Expression) $1); }\r
- | post_decrement_expression { $$ = new StatementExpression ((Expression) $1); }\r
- | pre_increment_expression { $$ = new StatementExpression ((Expression) $1); }\r
- | pre_decrement_expression { $$ = new StatementExpression ((Expression) $1); }\r
- ;\r
-\r
-object_creation_expression\r
- : object_or_delegate_creation_expression\r
- { note ("complain if this is a delegate maybe?"); } \r
- ;\r
-\r
-selection_statement\r
- : if_statement\r
- | switch_statement\r
- ; \r
-\r
-if_statement\r
- : IF OPEN_PARENS boolean_expression CLOSE_PARENS \r
- embedded_statement\r
- { \r
- $$ = new If ((Expression) $3, (Statement) $5);\r
- }\r
- | IF OPEN_PARENS boolean_expression CLOSE_PARENS\r
- embedded_statement ELSE embedded_statement\r
- {\r
- $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);\r
- }\r
- ;\r
-\r
-switch_statement\r
- : SWITCH OPEN_PARENS expression CLOSE_PARENS \r
- switch_block\r
- {\r
- $$ = new Switch ((Expression) $3, (ArrayList) $5);\r
- }\r
- ;\r
-\r
-switch_block\r
- : OPEN_BRACE\r
- opt_switch_sections\r
- CLOSE_BRACE\r
- {\r
- $$ = $2;\r
- }\r
- ;\r
-\r
-opt_switch_sections\r
- : /* empty */ { $$ = new ArrayList (); }\r
- | switch_sections\r
- ;\r
-\r
-switch_sections\r
- : switch_section \r
- {\r
- ArrayList sections = new ArrayList ();\r
-\r
- sections.Add ($1);\r
- $$ = sections;\r
- }\r
- | switch_sections switch_section\r
- {\r
- ArrayList sections = (ArrayList) $1;\r
-\r
- sections.Add ($2);\r
- $$ = sections;\r
- }\r
- ;\r
-\r
-switch_section\r
- : switch_labels\r
- {\r
- current_block = new Block (current_block);\r
- }\r
- statement_list \r
- {\r
- while (current_block.Implicit)\r
- current_block = current_block.Parent;\r
- $$ = new SwitchSection ((ArrayList) $1, current_block);\r
- current_block = current_block.Parent;\r
- }\r
- ;\r
-\r
-switch_labels\r
- : switch_label \r
- {\r
- ArrayList labels = new ArrayList ();\r
-\r
- labels.Add ($1);\r
- $$ = labels;\r
- }\r
- | switch_labels switch_label \r
- {\r
- ArrayList labels = (ArrayList) ($1);\r
- labels.Add ($2);\r
-\r
- $$ = labels;\r
- }\r
- ;\r
-\r
-switch_label\r
- : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2); }\r
- | DEFAULT COLON { $$ = new SwitchLabel (null); }\r
- ;\r
-\r
-iteration_statement\r
- : while_statement\r
- | do_statement\r
- | for_statement\r
- | foreach_statement\r
- ;\r
-\r
-while_statement\r
- : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement\r
- {\r
- $$ = new While ((Expression) $3, (Statement) $5);\r
- }\r
- ;\r
-\r
-do_statement\r
- : DO embedded_statement \r
- WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON\r
- {\r
- $$ = new Do ((Statement) $2, (Expression) $5);\r
- }\r
- ;\r
-\r
-for_statement\r
- : FOR OPEN_PARENS \r
- opt_for_initializer SEMICOLON\r
- opt_for_condition SEMICOLON\r
- opt_for_iterator CLOSE_PARENS \r
- embedded_statement\r
- {\r
- $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);\r
- }\r
- ;\r
-\r
-opt_for_initializer\r
- : /* empty */ { $$ = new EmptyStatement (); }\r
- | for_initializer \r
- ;\r
-\r
-for_initializer\r
- : local_variable_declaration\r
- | statement_expression_list\r
- ;\r
-\r
-opt_for_condition\r
- : /* empty */ { $$ = new BoolLiteral (true); }\r
- | boolean_expression\r
- ;\r
-\r
-opt_for_iterator\r
- : /* empty */ { $$ = new EmptyStatement (); }\r
- | for_iterator\r
- ;\r
-\r
-for_iterator\r
- : statement_expression_list\r
- ;\r
-\r
-statement_expression_list\r
- : statement_expression \r
- {\r
- Block b = new Block (null, true);\r
-\r
- b.AddStatement ((Statement) $1);\r
- $$ = b;\r
- }\r
- | statement_expression_list COMMA statement_expression\r
- {\r
- Block b = (Block) $1;\r
-\r
- b.AddStatement ((Statement) $3);\r
- $$ = $1;\r
- }\r
- ;\r
-\r
-foreach_statement\r
- : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS \r
- embedded_statement\r
- {\r
- string temp_id = current_block.MakeInternalID ();\r
- Expression assign_e, ma;\r
- Statement getcurrent;\r
- Block foreach_block, child_block;\r
-\r
- foreach_block = new Block (current_block, true);\r
-\r
- foreach_block.AddVariable ("System.IEnumerator", temp_id);\r
- foreach_block.AddVariable ((string) $3, (string) $4);\r
- assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id), \r
- new Invocation (\r
- new MemberAccess ((Expression) $6, "GetEnumerator"), null));\r
- current_block.AddStatement (new StatementExpression (assign_e));\r
- ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");\r
- child_block = new Block (current_block);\r
-\r
- getcurrent = new StatementExpression (\r
- new Assign (\r
- new LocalVariableReference (foreach_block, (string) $4),\r
- new Cast (\r
- (string) $3, \r
- new MemberAccess (\r
- new LocalVariableReference (foreach_block, temp_id), "Current"))));\r
-\r
- child_block.AddStatement (getcurrent);\r
- child_block.AddStatement ((Statement) $8);\r
- foreach_block.AddStatement (new While (ma, (Statement) child_block));\r
-\r
- $$ = foreach_block;\r
- }\r
- ;\r
-\r
-jump_statement\r
- : break_statement\r
- | continue_statement\r
- | goto_statement\r
- | return_statement\r
- | throw_statement\r
- ;\r
-\r
-break_statement\r
- : BREAK SEMICOLON\r
- {\r
- $$ = new Break ();\r
- }\r
- ;\r
-\r
-continue_statement\r
- : CONTINUE SEMICOLON\r
- {\r
- $$ = new Continue ();\r
- }\r
- ;\r
-\r
-goto_statement\r
- : GOTO IDENTIFIER SEMICOLON \r
- {\r
- $$ = new Goto ((string) $2);\r
- }\r
- | GOTO CASE constant_expression SEMICOLON\r
- | GOTO DEFAULT SEMICOLON \r
- ; \r
-\r
-return_statement\r
- : RETURN opt_expression SEMICOLON\r
- {\r
- $$ = new Return ((Expression) $2);\r
- }\r
- ;\r
-\r
-throw_statement\r
- : THROW opt_expression SEMICOLON\r
- {\r
- $$ = new Throw ((Expression) $2);\r
- }\r
- ;\r
-\r
-opt_expression\r
- : /* empty */\r
- | expression\r
- ;\r
-\r
-try_statement\r
- : TRY block catch_clauses \r
- {\r
- DictionaryEntry cc = (DictionaryEntry) $3;\r
- ArrayList s = null;\r
-\r
- if (cc.Key != null)\r
- s = (ArrayList) cc.Key;\r
-\r
- $$ = new Try ((Block) $2, s, (Catch) cc.Value, null);\r
- }\r
- | TRY block FINALLY block\r
- {\r
- $$ = new Try ((Block) $2, null, null, (Block) $4);\r
- }\r
- | TRY block catch_clauses FINALLY block\r
- {\r
- DictionaryEntry cc = (DictionaryEntry) $3;\r
- ArrayList s = null;\r
-\r
- if (cc.Key != null)\r
- s = (ArrayList) cc.Key;\r
-\r
- $$ = new Try ((Block) $2, s, (Catch) cc.Value, (Block) $5);\r
- }\r
- ;\r
-\r
-catch_clauses\r
- : specific_catch_clauses opt_general_catch_clause\r
- {\r
- DictionaryEntry pair = new DictionaryEntry ();\r
-\r
- pair.Key = $1; \r
- pair.Value = $2;\r
-\r
- $$ = pair;\r
- }\r
- | opt_specific_catch_clauses general_catch_clause\r
- {\r
- DictionaryEntry pair = new DictionaryEntry ();\r
- pair.Key = $1;\r
- pair.Value = $1;\r
-\r
- $$ = pair;\r
- }\r
- ;\r
-\r
-opt_general_catch_clause\r
- : /* empty */ { $$ = null; }\r
- | general_catch_clause \r
- ;\r
-\r
-opt_specific_catch_clauses\r
- : /* emtpy */ { $$ = null; }\r
- | specific_catch_clauses \r
- ;\r
-\r
-specific_catch_clauses\r
- : specific_catch_clause \r
- {\r
- ArrayList l = new ArrayList ();\r
-\r
- l.Add ($1);\r
- $$ = l;\r
- }\r
- | specific_catch_clauses specific_catch_clause\r
- {\r
- ArrayList l = (ArrayList) $1;\r
-\r
- l.Add ($2);\r
- $$ = l;\r
- }\r
- ;\r
-\r
-specific_catch_clause\r
- : CATCH OPEN_PARENS type opt_identifier CLOSE_PARENS block\r
- {\r
- string id = null;\r
-\r
- if ($4 != null)\r
- id = (string) $4;\r
-\r
- $$ = new Catch ((string) $3, id, (Block) $6);\r
- }\r
- ;\r
-\r
-opt_identifier\r
- : /* empty */ { $$ = null; }\r
- | IDENTIFIER\r
- ;\r
-\r
-general_catch_clause\r
- : CATCH block\r
- {\r
- $$ = new Catch (null, null, (Block) $2);\r
- }\r
- ;\r
-\r
-checked_statement\r
- : CHECKED block\r
- {\r
- $$ = new Checked ((Block) $2);\r
- }\r
- ;\r
-\r
-unchecked_statement\r
- : UNCHECKED block\r
- {\r
- $$ = new Unchecked ((Block) $2);\r
- }\r
- ;\r
-\r
-lock_statement\r
- : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement\r
- {\r
- $$ = new Lock ((Expression) $3, (Statement) $5);\r
- }\r
- ;\r
-\r
-using_statement\r
- : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement\r
- // finishme\r
- ; \r
-\r
-resource_acquisition\r
- : local_variable_declaration\r
- expression\r
- // finishme\r
- ;\r
-\r
-%%\r
-\r
-// <summary>\r
-// A class used to pass around variable declarations and constants\r
-// </summary>\r
-public class VariableDeclaration {\r
- public string identifier;\r
- public object expression_or_array_initializer;\r
-\r
- public VariableDeclaration (string id, object eoai){\r
- this.identifier = id;\r
- this.expression_or_array_initializer = eoai;\r
- }\r
-}\r
-\r
-// <summary>\r
-// Given the @class_name name, it creates a fully qualified name\r
-// based on the containing declaration space\r
-// </summary>\r
-string \r
-MakeName (string class_name)\r
-{\r
- string ns = current_namespace.Name;\r
- string container_name = current_container.Name;\r
-\r
- if (container_name == ""){\r
- if (ns != "")\r
- return ns + "." + class_name;\r
- else\r
- return class_name;\r
- } else\r
- return container_name + "." + class_name;\r
-}\r
-\r
-// <summary>\r
-// Used to report back to the user the result of a declaration\r
-// in the current declaration space\r
-// </summary>\r
-void \r
-CheckDef (DeclSpace.AdditionResult result, string name)\r
-{\r
- if (result == DeclSpace.AdditionResult.Success)\r
- return;\r
-\r
- switch (result){\r
- case DeclSpace.AdditionResult.NameExists:\r
- error (102, "The namespace `" + current_container.Name + \r
- "' already contains a definition for `"+\r
- name + "'");\r
- break;\r
-\r
-/*\r
- NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:\r
-\r
- case DeclSpace.AdditionResult.MethodDuplicated:\r
- error (111, "Class `"+current_container.Name+\r
- "' already defines a member called '" + \r
- name + "' with the same parameter types");\r
- break;\r
-*/\r
- case DeclSpace.AdditionResult.EnclosingClash:\r
- error (542, "Member names cannot be the same as their enclosing type");\r
- break;\r
-\r
- case DeclSpace.AdditionResult.NotAConstructor:\r
- error (1520, "Class, struct, or interface method must have a return type");\r
- break;\r
- }\r
-}\r
-\r
-void \r
-CheckDef (bool result, string name)\r
-{\r
- if (result)\r
- return;\r
- CheckDef (DeclSpace.AdditionResult.NameExists, name);\r
-}\r
-\r
-Block declare_local_variables (string type, ArrayList variable_declarators)\r
-{\r
- Block implicit_block;\r
- ArrayList inits = null;\r
-\r
- //\r
- // We use the `Used' property to check whether statements\r
- // have been added to the current block. If so, we need\r
- // to create another block to contain the new declaration\r
- // otherwise, as an optimization, we use the same block to\r
- // add the declaration.\r
- //\r
- // FIXME: A further optimization is to check if the statements\r
- // that were added were added as part of the initialization\r
- // below. In which case, no other statements have been executed\r
- // and we might be able to reduce the number of blocks for\r
- // situations like this:\r
- //\r
- // int j = 1; int k = j + 1;\r
- //\r
- if (current_block.Used)\r
- implicit_block = new Block (current_block, true);\r
- else\r
- implicit_block = new Block (current_block, true);\r
-\r
- foreach (VariableDeclaration decl in variable_declarators){\r
- if (implicit_block.AddVariable (type, decl.identifier)){\r
- if (decl.expression_or_array_initializer != null){\r
- if (inits == null)\r
- inits = new ArrayList ();\r
- inits.Add (decl);\r
- }\r
- } else {\r
- error (128, "A local variable `" + decl.identifier +\r
- "' is already defined in this scope");\r
- }\r
- }\r
-\r
- if (inits == null)\r
- return implicit_block;\r
-\r
- foreach (VariableDeclaration decl in inits){\r
- if (decl.expression_or_array_initializer is Expression){\r
- Expression expr = (Expression) decl.expression_or_array_initializer;\r
- Assign assign;\r
- \r
- assign = new Assign (new LocalVariableReference (implicit_block, decl.identifier), expr);\r
- implicit_block.AddStatement (new StatementExpression (assign));\r
- } else {\r
- }\r
- }\r
- \r
- return implicit_block;\r
-}\r
-\r
-void CheckConstant (Expression expr)\r
-{\r
- // finishme\r
-}\r
-\r
-void CheckBoolean (Expression expr)\r
-{\r
- // finishme\r
-}\r
-\r
-static public void error (int code, string desc)\r
-{\r
- Console.WriteLine ("Error CS"+code+": "+desc);\r
- global_errors++;\r
-}\r
-\r
-void output (string s)\r
-{\r
- Console.WriteLine (s);\r
-}\r
-\r
-void note (string s)\r
-{\r
- // Used to put annotations\r
-}\r
-\r
-Tokenizer lexer;\r
-\r
-public CSharpParser(CIR.Tree tree, string name, System.IO.Stream input) \r
-{\r
- current_namespace = new Namespace (null, "");\r
- this.tree = tree;\r
- this.name = name;\r
- this.input = input;\r
- current_container = tree.Types;\r
- current_container.Namespace = current_namespace;\r
-\r
- lexer = new Tokenizer (input, name);\r
-}\r
-\r
-public int parse ()\r
-{\r
- StringBuilder value = new StringBuilder ();\r
-\r
- global_errors = 0;\r
- try {\r
- if (yacc_verbose_flag)\r
- yyparse (lexer, new yydebug.yyDebugSimple ());\r
- else\r
- yyparse (lexer);\r
- } catch (Exception e){\r
- Console.WriteLine ("Fatal error: "+name);\r
- Console.WriteLine (e);\r
- Console.WriteLine (lexer.location);\r
- global_errors++;\r
- }\r
- \r
- return global_errors;\r
-}\r
-\r
-bool yacc_verbose_flag = false;\r
-\r
-public bool yacc_verbose {\r
- set {\r
- yacc_verbose_flag = value;\r
- }\r
-\r
- get {\r
- return yacc_verbose_flag;\r
- }\r
-}\r
-\r
-/* end end end */\r
-}\r
-}\r
-\r
+%{
+//
+// cs-parser.jay: The Parser for the C# compiler
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+// TODO:
+// (1) Get rid of the *Collections.cs, that is an idea I took from System.CodeDOM
+// And come to think of it, it is not that great, it duplicates a lot of code
+// for something which is not really needed. We still have piles of typecasts
+// anwyays (due to the nature of the stack being a collection of Objects).
+//
+// (2) Figure out why error productions dont work. `type-declaration' is a
+// great spot to put an `error' because you can reproduce it with this input:
+// "public X { }"
+//
+// (3) Move Modifier checking from each object into the parser itself, that will
+// get rid of the global "error" symbol that we use now to report errors.
+// We still need to pass a pointer to the tree.ErrorHandler, but that is a
+// separate problem
+//
+using System.Text;
+using CIR;
+using System;
+
+namespace CIR
+{
+ using System.Collections;
+ using Mono.Languages;
+
+ /// <summary>
+ /// The C# Parser
+ /// </summary>
+ public class CSharpParser : GenericParser {
+ Namespace current_namespace;
+ TypeContainer current_container;
+
+ // <summary>
+ // Current block is used to add statements as we find
+ // them.
+ // </summary>
+
+ Block current_block;
+
+ // <summary>
+ // Current interface is used by the various declaration
+ // productions in the interface declaration to "add"
+ // the interfaces as we find them.
+ // </summary>
+ Interface current_interface;
+
+ // <summary>
+ // This is used by the unary_expression code to resolve
+ // a name against a parameter.
+ // </summary>
+ Parameters current_local_parameters;
+
+ // <summary>
+ // Using during property parsing to describe the implicit
+ // value parameter that is passed to the "set" accesor
+ // method
+ // </summary>
+ Parameter [] implicit_value_parameters;
+
+ // <summary>
+ // Used to determine if we are parsing the get/set pair
+ // of an indexer or a property
+ // </summmary>
+ bool parsing_indexer;
+
+ // <summary>
+ // Used to record all types defined
+ // </summary>
+ Tree tree;
+ RootContext rc;
+
+%}
+
+%token EOF
+%token NONE /* This token is never returned by our lexer */
+%token ERROR // This is used not by the parser, but by the tokenizer.
+ // do not remove.
+
+/*
+ *These are the C# keywords
+ */
+%token ABSTRACT
+%token AS
+%token ADD
+%token BASE
+%token BOOL
+%token BREAK
+%token BYTE
+%token CASE
+%token CATCH
+%token CHAR
+%token CHECKED
+%token CLASS
+%token CONST
+%token CONTINUE
+%token DECIMAL
+%token DEFAULT
+%token DELEGATE
+%token DO
+%token DOUBLE
+%token ELSE
+%token ENUM
+%token EVENT
+%token EXPLICIT
+%token EXTERN
+%token FALSE
+%token FINALLY
+%token FIXED
+%token FLOAT
+%token FOR
+%token FOREACH
+%token GOTO
+%token IF
+%token IMPLICIT
+%token IN
+%token INT
+%token INTERFACE
+%token INTERNAL
+%token IS
+%token LOCK
+%token LONG
+%token NAMESPACE
+%token NEW
+%token NULL
+%token OBJECT
+%token OPERATOR
+%token OUT
+%token OVERRIDE
+%token PARAMS
+%token PRIVATE
+%token PROTECTED
+%token PUBLIC
+%token READONLY
+%token REF
+%token RETURN
+%token REMOVE
+%token SBYTE
+%token SEALED
+%token SHORT
+%token SIZEOF
+%token STATIC
+%token STRING
+%token STRUCT
+%token SWITCH
+%token THIS
+%token THROW
+%token TRUE
+%token TRY
+%token TYPEOF
+%token UINT
+%token ULONG
+%token UNCHECKED
+%token UNSAFE
+%token USHORT
+%token USING
+%token VIRTUAL
+%token VOID
+%token WHILE
+
+/* C# keywords which are not really keywords */
+%token GET "get"
+%token SET "set"
+
+/* C# single character operators/punctuation. */
+%token OPEN_BRACE "{"
+%token CLOSE_BRACE "}"
+%token OPEN_BRACKET "["
+%token CLOSE_BRACKET "]"
+%token OPEN_PARENS "("
+%token CLOSE_PARENS ")"
+%token DOT "."
+%token COMMA ","
+%token COLON ":"
+%token SEMICOLON ";"
+%token TILDE "~"
+
+%token PLUS "+"
+%token MINUS "-"
+%token BANG "!"
+%token ASSIGN "="
+%token OP_LT "<"
+%token OP_GT ">"
+%token BITWISE_AND "&"
+%token BITWISE_OR "|"
+%token STAR "*"
+%token PERCENT "%"
+%token DIV "/"
+%token CARRET "^"
+%token INTERR "?"
+
+/* C# multi-character operators. */
+%token OP_INC "++"
+%token OP_DEC "--"
+%token OP_SHIFT_LEFT "<<"
+%token OP_SHIFT_RIGHT ">>"
+%token OP_LE "<="
+%token OP_GE ">="
+%token OP_EQ "=="
+%token OP_NE "!="
+%token OP_AND "&&"
+%token OP_OR "||"
+%token OP_MULT_ASSIGN "*="
+%token OP_DIV_ASSIGN "/="
+%token OP_MOD_ASSIGN "%="
+%token OP_ADD_ASSIGN "+="
+%token OP_SUB_ASSIGN "-="
+%token OP_SHIFT_LEFT_ASSIGN "<<="
+%token OP_SHIFT_RIGHT_ASSIGN ">>="
+%token OP_AND_ASSIGN "&="
+%token OP_XOR_ASSIGN "^="
+%token OP_OR_ASSIGN "|="
+%token OP_PTR "->"
+
+/* Numbers */
+%token LITERAL_INTEGER "int literal"
+%token LITERAL_FLOAT "float literal"
+%token LITERAL_DOUBLE "double literal"
+%token LITERAL_DECIMAL "decimal literal"
+%token LITERAL_CHARACTER "character literal"
+%token LITERAL_STRING "string literal"
+
+%token IDENTIFIER
+
+/* Add precedence rules to solve dangling else s/r conflict */
+%nonassoc LOWPREC
+%nonassoc IF
+%nonassoc ELSE
+%right ASSIGN
+%left OP_OR
+%left OP_AND
+%left BITWISE_OR
+%left BITWISE_AND
+%left OP_SHIFT_LEFT OP_SHIFT_RIGHT
+%left PLUS MINUS
+%left STAR DIV PERCENT
+%right BANG CARRET UMINUS
+%nonassoc OP_INC OP_DEC
+%left OPEN_PARENS
+%left OPEN_BRACKET OPEN_BRACE
+%left DOT
+%nonassoc HIGHPREC
+
+%start compilation_unit
+/*%start namespace_declaration */
+%%
+
+compilation_unit
+ : opt_using_directives opt_attributes opt_namespace_member_declarations EOF
+ {
+ // Check that using comes only before namespace elements
+ }
+ ;
+
+using_directives
+ : using_directive
+ | using_directives using_directive
+ ;
+
+using_directive
+ : using_alias_directive
+ | using_namespace_directive
+ ;
+
+using_alias_directive
+ : USING IDENTIFIER ASSIGN
+ namespace_or_type_name SEMICOLON
+ {
+ // FIXME : Need to implement actual action.
+ }
+ ;
+
+using_namespace_directive
+ : USING namespace_name SEMICOLON
+ {
+ current_namespace.Using ((string) $2);
+ }
+ ;
+
+// namespace_declarations
+// : namespace_declaration
+// | namespace_declarations namespace_declaration
+
+namespace_declaration
+ : NAMESPACE qualified_identifier
+ {
+ current_namespace = new Namespace (current_namespace, (string) $2);
+ tree.RecordNamespace ((string) $2, current_namespace);
+ }
+ namespace_body opt_semicolon
+ {
+ current_namespace = current_namespace.Parent;
+ }
+ ;
+
+opt_semicolon
+ : /* empty */
+ | SEMICOLON
+ ;
+
+opt_comma
+ : /* empty */
+ | COMMA
+ ;
+
+qualified_identifier
+ : IDENTIFIER
+ | qualified_identifier DOT IDENTIFIER {
+ $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
+ ;
+
+
+namespace_name
+ : namespace_or_type_name
+ ;
+
+namespace_body
+ : OPEN_BRACE
+ opt_using_directives
+ opt_namespace_member_declarations
+ CLOSE_BRACE
+ {
+ }
+ ;
+
+opt_using_directives
+ : /* empty */
+ | using_directives
+ ;
+
+opt_namespace_member_declarations
+ : /* empty */
+ | namespace_member_declarations
+ ;
+
+namespace_member_declarations
+ : namespace_member_declaration
+ | namespace_member_declarations namespace_member_declaration
+ ;
+
+namespace_member_declaration
+ : type_declaration
+ {
+ int mod_flags = 0;
+ string name = "";
+
+ if ($1 is Class){
+ Class c = (Class) $1;
+ mod_flags = c.ModFlags;
+ name = c.Name;
+ } else if ($1 is Struct){
+ Struct s = (Struct) $1;
+ mod_flags = s.ModFlags;
+ name = s.Name;
+ } else
+ break;
+
+ //
+ // We remove this error until we can
+ //if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
+ // error (1527, "Namespace elements cant be explicitly " +
+ // "declared private or protected in `" + name + "'");
+ //}
+ }
+ | namespace_declaration
+ ;
+
+type_declaration
+ : class_declaration
+ | struct_declaration
+ | interface_declaration
+ | enum_declaration
+ | delegate_declaration
+ ;
+
+//
+// Attributes 17.2
+//
+opt_attributes
+ : /* empty */ { $$ = null; }
+ | attribute_section opt_attributes
+ {
+ Attributes attrs;
+
+ if ($2 != null) {
+ attrs = (Attributes) $2;
+ attrs.AddAttribute ((Attribute) $1);
+ } else
+ attrs = new Attributes ((Attribute) $1);
+
+ $$ = attrs;
+ }
+ ;
+
+attribute_section
+ : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET
+ {
+ string target = null;
+
+ if ($2 != null)
+ target = (string) $2;
+
+ $$ = new Attribute (target, (ArrayList) $3);
+ }
+ | OPEN_BRACKET attribute_list CLOSE_BRACKET
+ {
+ $$ = new Attribute (null, (ArrayList) $2);
+ }
+ ;
+
+attribute_target_specifier
+ : attribute_target COLON
+ {
+ $$ = $1;
+ }
+ ;
+
+attribute_target
+ : IDENTIFIER
+ {
+ CheckAttributeTarget ((string) $1);
+ $$ = $1;
+ }
+ | EVENT { $$ = "event"; }
+ | RETURN { $$ = "return"; }
+ ;
+
+attribute_list
+ : attribute
+ {
+ ArrayList attrs = new ArrayList ();
+ attrs.Add ($1);
+
+ $$ = attrs;
+
+ }
+ | attribute_list COMMA attribute
+ {
+ ArrayList attrs = (ArrayList) $1;
+ attrs.Add ($3);
+
+ $$ = attrs;
+ }
+ ;
+
+attribute
+ : attribute_name opt_attribute_arguments
+ {
+ $$ = new DictionaryEntry ($1, $2);
+ }
+ ;
+
+attribute_name
+ : type_name { /* reserved attribute name or identifier: 17.4 */ }
+ ;
+
+opt_attribute_arguments
+ : /* empty */ { $$ = null; }
+ | OPEN_PARENS attribute_arguments CLOSE_PARENS
+ {
+ $$ = $2;
+ }
+ ;
+
+attribute_arguments
+ : expression
+ {
+ ArrayList args = new ArrayList ();
+ args.Add ($1);
+
+ $$ = args;
+ }
+ | attribute_arguments COMMA expression
+ {
+ ArrayList args = (ArrayList) $1;
+ args.Add ($3);
+
+ $$ = args;
+ }
+ ;
+
+
+class_body
+ : OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
+ ;
+
+opt_class_member_declarations
+ : /* empty */
+ | class_member_declarations
+ ;
+
+class_member_declarations
+ : class_member_declaration
+ | class_member_declarations
+ class_member_declaration
+ ;
+
+class_member_declaration
+ : constant_declaration // done
+ | field_declaration // done
+ | method_declaration // done
+ | property_declaration // done
+ | event_declaration // done
+ | indexer_declaration // done
+ | operator_declaration // done
+ | constructor_declaration // done
+ | destructor_declaration // done
+ | type_declaration
+ ;
+
+struct_declaration
+ : opt_attributes
+ opt_modifiers
+ STRUCT IDENTIFIER
+ {
+ Struct new_struct;
+ string full_struct_name = MakeName ((string) $4);
+
+ new_struct = new Struct (rc, current_container, full_struct_name, (int) $2,
+ (Attributes) $1, lexer.Location);
+ current_container = new_struct;
+ current_container.Namespace = current_namespace;
+ tree.RecordStruct (full_struct_name, new_struct);
+ }
+ opt_struct_interfaces
+ struct_body
+ opt_semicolon
+ {
+ Struct new_struct = (Struct) current_container;
+
+ current_container = current_container.Parent;
+ CheckDef (current_container.AddStruct (new_struct), new_struct.Name);
+ $$ = new_struct;
+ }
+ ;
+
+opt_struct_interfaces
+ : /* empty */
+ | struct_interfaces
+ ;
+
+struct_interfaces
+ : struct_interface
+ | struct_interfaces struct_interface
+ ;
+
+struct_interface
+ : COLON type_list
+ ;
+
+struct_body
+ : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
+ ;
+
+opt_struct_member_declarations
+ : /* empty */
+ | struct_member_declarations
+ ;
+
+struct_member_declarations
+ : struct_member_declaration
+ | struct_member_declarations struct_member_declaration
+ ;
+
+struct_member_declaration
+ : constant_declaration
+ | field_declaration
+ | method_declaration
+ | property_declaration
+ | event_declaration
+ | indexer_declaration
+ | operator_declaration
+ | constructor_declaration
+ | type_declaration
+ ;
+
+constant_declaration
+ : opt_attributes
+ opt_modifiers
+ CONST
+ type
+ constant_declarators
+ SEMICOLON
+ {
+ foreach (DictionaryEntry constant in (ArrayList) $5){
+ Constant c = new Constant (
+ (string) $4, (string) constant.Key,
+ (Expression) constant.Value, (int) $2, (Attributes) $1);
+
+ CheckDef (current_container.AddConstant (c), c.Name);
+ }
+ }
+ ;
+
+constant_declarators
+ : constant_declarator
+ {
+ ArrayList constants = new ArrayList ();
+ constants.Add ($1);
+ $$ = constants;
+ }
+ | constant_declarators COMMA constant_declarator
+ {
+ ArrayList constants = (ArrayList) $1;
+
+ constants.Add ($3);
+ }
+ ;
+
+constant_declarator
+ : IDENTIFIER ASSIGN constant_expression
+ {
+ $$ = new DictionaryEntry ($1, $3);
+ }
+ ;
+
+field_declaration
+ : opt_attributes
+ opt_modifiers
+ type
+ variable_declarators
+ SEMICOLON
+ {
+ string type = (string) $3;
+ int mod = (int) $2;
+
+ foreach (VariableDeclaration var in (ArrayList) $4){
+ Field field = new Field (type, mod, var.identifier,
+ var.expression_or_array_initializer, (Attributes) $1);
+
+ CheckDef (current_container.AddField (field), field.Name);
+ }
+ }
+
+ ;
+
+variable_declarators
+ : variable_declarator
+ {
+ ArrayList decl = new ArrayList ();
+ decl.Add ($1);
+ $$ = decl;
+ }
+ | variable_declarators COMMA variable_declarator
+ {
+ ArrayList decls = (ArrayList) $1;
+ decls.Add ($3);
+ $$ = $1;
+ }
+ ;
+
+variable_declarator
+ : IDENTIFIER ASSIGN variable_initializer
+ {
+ $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
+ }
+ | IDENTIFIER
+ {
+ $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
+ }
+ ;
+
+variable_initializer
+ : expression
+ {
+ $$ = $1;
+ }
+ | array_initializer
+ {
+ $$ = $1;
+ }
+ ;
+
+method_declaration
+ : method_header
+ method_body
+ {
+ Method method = (Method) $1;
+ Block b = (Block) $2;
+
+ if (b == null){
+ if ((method.ModFlags & (Modifiers.EXTERN | Modifiers.ABSTRACT)) == 0){
+ Report.Error (
+ 501, lexer.Location, "`" +
+ current_container.Name + "." + method.Name + "'" +
+ "must declare a body because it is not marked abstract or extern");
+ }
+ }
+
+ method.Block = (Block) $2;
+ CheckDef (current_container.AddMethod (method), method.Name);
+
+ current_local_parameters = null;
+ }
+ ;
+
+method_header
+ : opt_attributes
+ opt_modifiers
+ type
+ member_name
+ OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ {
+ Method method = new Method ((string) $3, (int) $2, (string) $4,
+ (Parameters) $6, (Attributes) $1, lexer.Location);
+
+ current_local_parameters = (Parameters) $6;
+
+ $$ = method;
+ }
+ | opt_attributes
+ opt_modifiers
+ VOID
+ member_name
+ OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ {
+ Method method = new Method ("System.Void", (int) $2, (string) $4,
+ (Parameters) $6, (Attributes) $1, lexer.Location);
+
+ current_local_parameters = (Parameters) $6;
+ $$ = method;
+ }
+ ;
+
+method_body
+ : block
+ | SEMICOLON { $$ = null; }
+ ;
+
+opt_formal_parameter_list
+ : /* empty */ { $$ = new Parameters (null, null); }
+ | formal_parameter_list
+ ;
+
+formal_parameter_list
+ : fixed_parameters
+ {
+ ArrayList pars_list = (ArrayList) $1;
+
+ Parameter [] pars = new Parameter [pars_list.Count];
+ pars_list.CopyTo (pars);
+
+ $$ = new Parameters (pars, null);
+ }
+ | fixed_parameters COMMA parameter_array
+ {
+ ArrayList pars_list = (ArrayList) $1;
+
+ Parameter [] pars = new Parameter [pars_list.Count];
+ pars_list.CopyTo (pars);
+
+ $$ = new Parameters (pars, (Parameter) $3);
+ }
+ | parameter_array
+ {
+ $$ = new Parameters (null, (Parameter) $1);
+ }
+ ;
+
+fixed_parameters
+ : fixed_parameter
+ {
+ ArrayList pars = new ArrayList ();
+
+ pars.Add ($1);
+ $$ = pars;
+ }
+ | fixed_parameters COMMA fixed_parameter
+ {
+ ArrayList pars = (ArrayList) $1;
+
+ pars.Add ($3);
+ $$ = $1;
+ }
+ ;
+
+fixed_parameter
+ : opt_attributes
+ opt_parameter_modifier
+ type
+ IDENTIFIER
+ {
+ $$ = new Parameter ((string) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
+ }
+ ;
+
+opt_parameter_modifier
+ : /* empty */ { $$ = Parameter.Modifier.NONE; }
+ | parameter_modifier
+ ;
+
+parameter_modifier
+ : REF { $$ = Parameter.Modifier.REF; }
+ | OUT { $$ = Parameter.Modifier.OUT; }
+ ;
+
+parameter_array
+ : opt_attributes PARAMS type IDENTIFIER
+ {
+ $$ = new Parameter ((string) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
+ note ("type must be a single-dimension array type");
+ }
+ ;
+
+member_name
+ : IDENTIFIER { $$ = $1.ToString (); }
+ | interface_type DOT IDENTIFIER { $$ = $1.ToString () + "." + $3.ToString (); }
+ ;
+
+property_declaration
+ : opt_attributes
+ opt_modifiers
+ type member_name
+ OPEN_BRACE
+ {
+ Parameter implicit_value_parameter;
+ implicit_value_parameter = new Parameter ((string) $3, "value", Parameter.Modifier.NONE, null);
+
+ lexer.properties = true;
+
+ implicit_value_parameters = new Parameter [1];
+ implicit_value_parameters [0] = implicit_value_parameter;
+ }
+ accessor_declarations
+ {
+ lexer.properties = false;
+ }
+ CLOSE_BRACE
+ {
+ Property prop;
+ DictionaryEntry pair = (DictionaryEntry) $7;
+ Block get_block = null;
+ Block set_block = null;
+
+ if (pair.Key != null)
+ get_block = (Block) pair.Key;
+ if (pair.Value != null)
+ set_block = (Block) pair.Value;
+
+ prop = new Property ((string) $3, (string) $4, (int) $2, get_block, set_block, (Attributes) $1);
+
+ CheckDef (current_container.AddProperty (prop), prop.Name);
+ implicit_value_parameters = null;
+ }
+ ;
+
+accessor_declarations
+ : get_accessor_declaration opt_set_accessor_declaration
+ {
+ $$ = new DictionaryEntry ($1, $2);
+ }
+ | set_accessor_declaration opt_get_accessor_declaration
+ {
+ $$ = new DictionaryEntry ($2, $1);
+ }
+ ;
+
+opt_get_accessor_declaration
+ : /* empty */ { $$ = null; }
+ | get_accessor_declaration
+ ;
+
+opt_set_accessor_declaration
+ : /* empty */ { $$ = null; }
+ | set_accessor_declaration
+ ;
+
+get_accessor_declaration
+ : opt_attributes GET
+ {
+ // If this is not the case, then current_local_parameters has already
+ // been set in indexer_declaration
+ if (parsing_indexer == false)
+ current_local_parameters = new Parameters (implicit_value_parameters, null);
+
+
+ }
+ accessor_body
+ {
+ $$ = $4;
+ current_local_parameters = null;
+ }
+ ;
+
+set_accessor_declaration
+ : opt_attributes SET
+ {
+ if (parsing_indexer == false)
+ current_local_parameters = new Parameters (implicit_value_parameters, null);
+ }
+ accessor_body
+ {
+ $$ = $4;
+ current_local_parameters = null;
+ }
+ ;
+
+accessor_body
+ : block
+ | SEMICOLON { $$ = new Block (null); }
+ ;
+
+interface_declaration
+ : opt_attributes
+ opt_modifiers
+ INTERFACE IDENTIFIER
+ {
+ Interface new_interface;
+ string full_interface_name = MakeName ((string) $4);
+
+ new_interface = new Interface (current_container, full_interface_name, (int) $2,
+ (Attributes) $1, lexer.Location);
+ if (current_interface != null) {
+ Location l = lexer.Location;
+ Report.Error (-2, l, "Internal compiler error: interface inside interface");
+ }
+ current_interface = new_interface;
+ tree.RecordInterface (full_interface_name, new_interface);
+ }
+ opt_interface_base
+ interface_body
+ {
+ Interface new_interface = (Interface) current_interface;
+
+ if ($6 != null)
+ new_interface.Bases = (ArrayList) $6;
+
+ current_interface = null;
+ CheckDef (current_container.AddInterface (new_interface), new_interface.Name);
+ }
+ ;
+
+opt_interface_base
+ : /* empty */ { $$ = null; }
+ | interface_base
+ ;
+
+interface_base
+ : COLON interface_type_list { $$ = $2; }
+ ;
+
+interface_type_list
+ : interface_type
+ {
+ ArrayList interfaces = new ArrayList ();
+
+ interfaces.Add ($1);
+ $$ = interfaces;
+ }
+ | interface_type_list COMMA interface_type
+ {
+ ArrayList interfaces = (ArrayList) $1;
+ interfaces.Add ($3);
+ $$ = interfaces;
+ }
+ ;
+
+interface_body
+ : OPEN_BRACE
+ opt_interface_member_declarations
+ CLOSE_BRACE
+ ;
+
+opt_interface_member_declarations
+ : /* empty */
+ | interface_member_declarations
+ ;
+
+interface_member_declarations
+ : interface_member_declaration
+ | interface_member_declarations interface_member_declaration
+ ;
+
+interface_member_declaration
+ : interface_method_declaration
+ {
+ InterfaceMethod m = (InterfaceMethod) $1;
+
+ CheckDef (current_interface.AddMethod (m), m.Name);
+ }
+ | interface_property_declaration
+ {
+ InterfaceProperty p = (InterfaceProperty) $1;
+
+ CheckDef (current_interface.AddProperty (p), p.Name);
+ }
+ | interface_event_declaration
+ {
+ InterfaceEvent e = (InterfaceEvent) $1;
+
+ CheckDef (current_interface.AddEvent (e), e.Name);
+ }
+ | interface_indexer_declaration
+ {
+ InterfaceIndexer i = (InterfaceIndexer) $1;
+
+ CheckDef (current_interface.AddIndexer (i), "indexer");
+ }
+ ;
+
+opt_new
+ : /* empty */ { $$ = false; }
+ | NEW { $$ = true; }
+ ;
+
+interface_method_declaration
+ : opt_attributes opt_new type IDENTIFIER
+ OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ SEMICOLON
+ {
+ $$ = new InterfaceMethod ((string) $3, (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
+ }
+ | opt_attributes opt_new VOID IDENTIFIER
+ OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ SEMICOLON
+ {
+ $$ = new InterfaceMethod ("System.Void", (string) $4, (bool) $2, (Parameters) $6, (Attributes) $1);
+ }
+ ;
+
+interface_property_declaration
+ : opt_attributes
+ opt_new
+ type IDENTIFIER
+ OPEN_BRACE
+ { lexer.properties = true; }
+ interface_accesors
+ { lexer.properties = false; }
+ CLOSE_BRACE
+ {
+ int gs = (int) $7;
+
+ $$ = new InterfaceProperty ((string) $3, (string) $4, (bool) $2,
+ (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1);
+ }
+ ;
+
+interface_accesors
+ : opt_attributes GET SEMICOLON { $$ = 1; }
+ | opt_attributes SET SEMICOLON { $$ = 2; }
+ | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON
+ { $$ = 3; }
+ | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
+ { $$ = 3; }
+ ;
+
+interface_event_declaration
+ : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
+ {
+ $$ = new InterfaceEvent ((string) $4, (string) $5, (bool) $2, (Attributes) $1);
+ }
+ ;
+
+interface_indexer_declaration
+ : opt_attributes opt_new type THIS
+ OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+ OPEN_BRACE
+ { lexer.properties = true; }
+ interface_accesors
+ { lexer.properties = false; }
+ CLOSE_BRACE
+ {
+ int a_flags = (int) $10;
+
+ bool do_get = (a_flags & 1) == 1;
+ bool do_set = (a_flags & 2) == 2;
+
+ $$ = new InterfaceIndexer ((string) $3, (Parameters) $6, do_get, do_set, (bool) $2, (Attributes) $1);
+ }
+ ;
+
+operator_declaration
+ : opt_attributes opt_modifiers operator_declarator block
+ {
+ OperatorDeclaration decl = (OperatorDeclaration) $3;
+
+ Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
+ decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
+
+ // Note again, checking is done in semantic analysis
+ current_container.AddOperator (op);
+ }
+ ;
+
+operator_declarator
+ : type OPERATOR overloadable_operator
+ OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+ {
+ CheckUnaryOperator ((Operator.OpType) $3);
+
+ $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
+ null, null, lexer.Location);
+ }
+ | type OPERATOR overloadable_operator
+ OPEN_PARENS
+ type IDENTIFIER COMMA
+ type IDENTIFIER
+ CLOSE_PARENS
+ {
+ CheckBinaryOperator ((Operator.OpType) $3);
+
+ $$ = new OperatorDeclaration ((Operator.OpType) $3, (string) $1, (string) $5, (string) $6,
+ (string) $8, (string) $9, lexer.Location);
+ }
+ | conversion_operator_declarator
+ ;
+
+overloadable_operator
+// Unary operators:
+ : BANG { $$ = Operator.OpType.Negate; }
+ | TILDE { $$ = Operator.OpType.BitComplement; }
+ | OP_INC { $$ = Operator.OpType.Increment; }
+ | OP_DEC { $$ = Operator.OpType.Decrement; }
+ | TRUE { $$ = Operator.OpType.True; }
+ | FALSE { $$ = Operator.OpType.False; }
+// Unary and binary:
+ | PLUS { $$ = Operator.OpType.Addition; }
+ | MINUS { $$ = Operator.OpType.Subtraction; }
+// Binary:
+ | STAR { $$ = Operator.OpType.Multiply; }
+ | DIV { $$ = Operator.OpType.Division; }
+ | PERCENT { $$ = Operator.OpType.Modulus; }
+ | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
+ | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
+ | CARRET { $$ = Operator.OpType.ExclusiveOr; }
+ | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
+ | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
+ | OP_EQ { $$ = Operator.OpType.Equality; }
+ | OP_NE { $$ = Operator.OpType.Inequality; }
+ | OP_GT { $$ = Operator.OpType.GreaterThan; }
+ | OP_LT { $$ = Operator.OpType.LessThan; }
+ | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
+ | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
+ ;
+
+conversion_operator_declarator
+ : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+ {
+ $$ = new OperatorDeclaration (Operator.OpType.Implicit, (string) $3, (string) $5, (string) $6,
+ null, null, lexer.Location);
+ }
+ | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+ {
+ $$ = new OperatorDeclaration (Operator.OpType.Explicit, (string) $3, (string) $5, (string) $6,
+ null, null, lexer.Location);
+ }
+ ;
+
+constructor_declaration
+ : opt_attributes
+ opt_modifiers
+ constructor_declarator
+ block
+ {
+ Constructor c = (Constructor) $3;
+ c.Block = (Block) $4;
+ c.ModFlags = (int) $2;
+
+ if ((c.ModFlags & Modifiers.STATIC) != 0){
+ if ((c.ModFlags & Modifiers.Accessibility) != 0) {
+ Location l = lexer.Location;
+ Report.Error (515, l, "Access modifiers are not allowed on static constructors");
+ }
+
+ if (c.Initializer != null){
+ Location l = lexer.Location;
+ Report.Error (514, l, "Static constructors can not have an explicit this or base constructor invocations");
+ }
+
+ if (!c.Parameters.Empty){
+ Location l = lexer.Location;
+ Report.Error (103, l, "Static constructors should not have parameters");
+ }
+ }
+
+ CheckDef (current_container.AddConstructor (c), c.Name);
+
+ current_local_parameters = null;
+ }
+ ;
+
+constructor_declarator
+ : IDENTIFIER
+ OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ opt_constructor_initializer
+ {
+ Location l = lexer.Location;
+
+ $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $5, l);
+
+ current_local_parameters = (Parameters) $3;
+ }
+ ;
+
+opt_constructor_initializer
+ : /* empty */ { $$ = null; }
+ | constructor_initializer
+ ;
+
+constructor_initializer
+ : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
+ }
+ | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
+ }
+ ;
+
+destructor_declaration
+ : opt_attributes TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
+ {
+ Method d = new Method ("System.Void", 0, "Finalize",
+ new Parameters (null, null), (Attributes) $1, lexer.Location);
+
+ d.Block = (Block) $6;
+ CheckDef (current_container.AddMethod (d), d.Name);
+ }
+ ;
+
+event_declaration
+ : opt_attributes
+ opt_modifiers
+ EVENT type variable_declarators SEMICOLON
+ {
+ foreach (VariableDeclaration var in (ArrayList) $5) {
+
+ // FIXME : Is this right ?
+ Event e = new Event ((string) $4, var.identifier, var.expression_or_array_initializer,
+ (int) $2, null, null, (Attributes) $1);
+
+ CheckDef (current_container.AddEvent (e), e.Name);
+
+ }
+ }
+ | opt_attributes
+ opt_modifiers
+ EVENT type member_name
+ OPEN_BRACE event_accessor_declarations CLOSE_BRACE
+ {
+ DictionaryEntry pair = (DictionaryEntry) $7;
+ Block add_block = null;
+ Block rem_block = null;
+
+ if (pair.Key != null)
+ add_block = (Block) pair.Key;
+ if (pair.Value != null)
+ rem_block = (Block) pair.Value;
+
+ Event e = new Event ((string) $4, (string) $5, null, (int) $2, add_block, rem_block, (Attributes) $1);
+
+ CheckDef (current_container.AddEvent (e), e.Name);
+ }
+ ;
+
+event_accessor_declarations
+ : add_accessor_declaration remove_accessor_declaration
+ {
+ $$ = new DictionaryEntry ($1, $2);
+ }
+ | remove_accessor_declaration add_accessor_declaration
+ {
+ $$ = new DictionaryEntry ($2, $1);
+ }
+ ;
+
+add_accessor_declaration
+ : opt_attributes ADD block
+ {
+ $$ = $3;
+ }
+ ;
+
+remove_accessor_declaration
+ : opt_attributes REMOVE block
+ {
+ $$ = $3;
+ }
+ ;
+
+indexer_declaration
+ : opt_attributes opt_modifiers indexer_declarator
+ OPEN_BRACE
+ {
+ IndexerDeclaration decl = (IndexerDeclaration) $3;
+
+ lexer.properties = true;
+ parsing_indexer = true;
+
+ current_local_parameters = decl.param_list;
+ }
+ accessor_declarations
+ {
+ lexer.properties = false;
+ parsing_indexer = false;
+ }
+ CLOSE_BRACE
+ {
+ // The signature is computed from the signature of the indexer. Look
+ // at section 3.6 on the spec
+
+ Indexer indexer;
+ IndexerDeclaration decl = (IndexerDeclaration) $3;
+ DictionaryEntry pair = (DictionaryEntry) $6;
+ Block get_block = null;
+ Block set_block = null;
+
+ if (pair.Key != null)
+ get_block = (Block) pair.Key;
+ if (pair.Value != null)
+ set_block = (Block) pair.Value;
+
+ indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
+ get_block, set_block, (Attributes) $1);
+
+ // Note that there is no equivalent of CheckDef for this case
+ // We shall handle this in semantic analysis
+
+ current_container.AddIndexer (indexer);
+
+ current_local_parameters = null;
+ }
+ ;
+
+indexer_declarator
+ : type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+ {
+ $$ = new IndexerDeclaration ((string) $1, null, (Parameters) $4);
+ }
+ | type interface_type DOT THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+ {
+ $$ = new IndexerDeclaration ((string) $1, (string) $2, (Parameters) $6);
+ }
+ ;
+
+enum_declaration
+ : opt_attributes
+ opt_modifiers
+ ENUM IDENTIFIER
+ opt_enum_base
+ enum_body
+ opt_semicolon
+ {
+ string name = (string) $4;
+ Enum e = new Enum ((string) $5, (int) $2, name, (Attributes) $1, lexer.Location);
+
+ foreach (VariableDeclaration ev in (ArrayList) $6){
+ CheckDef (e.AddEnumMember (ev.identifier,
+ (Expression) ev.expression_or_array_initializer),
+ ev.identifier);
+ }
+
+ CheckDef (current_container.AddEnum (e), name);
+ }
+ ;
+
+opt_enum_base
+ : /* empty */ { $$ = "System.Int32"; }
+ | COLON integral_type { $$ = $2; }
+ ;
+
+enum_body
+ : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
+ {
+ $$ = $2;
+ }
+ ;
+
+opt_enum_member_declarations
+ : /* empty */ { $$ = new ArrayList (); }
+ | enum_member_declarations opt_comma { $$ = $1; }
+ ;
+
+enum_member_declarations
+ : enum_member_declaration
+ {
+ ArrayList l = new ArrayList ();
+
+ l.Add ($1);
+ $$ = l;
+ }
+ | enum_member_declarations COMMA enum_member_declaration
+ {
+ ArrayList l = (ArrayList) $1;
+
+ l.Add ($3);
+
+ $$ = l;
+ }
+ ;
+
+enum_member_declaration
+ : opt_attributes IDENTIFIER
+ {
+ $$ = new VariableDeclaration ((string) $2, null, lexer.Location);
+ }
+ | opt_attributes IDENTIFIER ASSIGN expression
+ {
+ $$ = new VariableDeclaration ((string) $2, $4, lexer.Location);
+ }
+ ;
+
+delegate_declaration
+ : opt_attributes
+ opt_modifiers
+ DELEGATE type
+ IDENTIFIER OPEN_PARENS
+ formal_parameter_list
+ CLOSE_PARENS
+ SEMICOLON
+ {
+ Delegate del = new Delegate ((string) $4, (int) $2, (string) $5, (Parameters) $7,
+ (Attributes) $1, lexer.Location);
+
+ CheckDef (current_container.AddDelegate (del), del.Name);
+ }
+ | opt_attributes
+ opt_modifiers
+ DELEGATE VOID
+ IDENTIFIER OPEN_PARENS
+ formal_parameter_list
+ CLOSE_PARENS
+ SEMICOLON
+ {
+ Delegate del = new Delegate (null, (int) $2, (string) $5, (Parameters) $7,
+ (Attributes) $1, lexer.Location);
+
+ CheckDef (current_container.AddDelegate (del), del.Name);
+ }
+ ;
+
+type_name
+ : namespace_or_type_name
+ ;
+
+namespace_or_type_name
+ : qualified_identifier
+ ;
+
+/*
+ * Before you think of adding a return_type, notice that we have been
+ * using two rules in the places where it matters (one rule using type
+ * and another identical one that uses VOID as the return type). This
+ * gets rid of a shift/reduce couple
+ */
+type
+ : type_name { /* class_type */
+ /*
+ This does interfaces, delegates, struct_types, class_types,
+ parent classes, and more! 4.2
+ */
+ $$ = $1;
+ }
+ | builtin_types
+ | array_type
+ ;
+
+type_list
+ : type
+ {
+ ArrayList types = new ArrayList ();
+
+ types.Add ($1);
+ $$ = types;
+ }
+ | type_list COMMA type
+ {
+ ArrayList types = (ArrayList) $1;
+
+ types.Add ($3);
+ $$ = types;
+ }
+ ;
+
+/*
+ * replaces all the productions for isolating the various
+ * simple types, but we need this to reuse it easily in local_variable_type
+ */
+builtin_types
+ : OBJECT { $$ = "System.Object"; }
+ | STRING { $$ = "System.String"; }
+ | BOOL { $$ = "System.Boolean"; }
+ | DECIMAL { $$ = "System.Decimal"; }
+ | FLOAT { $$ = "System.Single"; }
+ | DOUBLE { $$ = "System.Double"; }
+ | integral_type
+ ;
+
+integral_type
+ : SBYTE { $$ = "System.SByte"; }
+ | BYTE { $$ = "System.Byte"; }
+ | SHORT { $$ = "System.Int16"; }
+ | USHORT { $$ = "System.UInt16"; }
+ | INT { $$ = "System.Int32"; }
+ | UINT { $$ = "System.UInt32"; }
+ | LONG { $$ = "System.Int64"; }
+ | ULONG { $$ = "System.UInt64"; }
+ | CHAR { $$ = "System.Char"; }
+ ;
+
+interface_type
+ : type_name
+ ;
+
+array_type
+ : type rank_specifiers
+ {
+ $$ = (string) $1 + (string) $2;
+ }
+ ;
+
+//
+// Expressions, section 7.5
+//
+primary_expression
+ : literal
+ {
+ // 7.5.1: Literals
+ }
+
+ | qualified_identifier
+ {
+ string name = (string) $1;
+
+ $$ = null;
+ $$ = QualifiedIdentifier (name, lexer.Location);
+ }
+ | parenthesized_expression
+ | member_access
+ | invocation_expression
+ | element_access
+ | this_access
+ | base_access
+ | post_increment_expression
+ | post_decrement_expression
+ | new_expression
+ | typeof_expression
+ | sizeof_expression
+ | checked_expression
+ | unchecked_expression
+ ;
+
+literal
+ : boolean_literal
+ | integer_literal
+ | real_literal
+ | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
+ | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
+ | NULL { $$ = new NullLiteral (); }
+ ;
+
+real_literal
+ : LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value); }
+ | LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value); }
+ | LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value); }
+ ;
+
+integer_literal
+ : LITERAL_INTEGER {
+ object v = lexer.Value;
+
+ //
+ // FIXME: Possible optimization would be to
+ // compute the *Literal objects directly in the scanner
+ //
+ if (v is int)
+ $$ = new IntLiteral ((Int32) v);
+ else if (v is uint)
+ $$ = new UIntLiteral ((UInt32) v);
+ else if (v is long)
+ $$ = new LongLiteral ((Int64) v);
+ else if (v is ulong)
+ $$ = new ULongLiteral ((UInt64) v);
+ else
+ Console.WriteLine ("OOPS. Unexpected result from scanner");
+ }
+ ;
+
+boolean_literal
+ : TRUE { $$ = new BoolLiteral (true); }
+ | FALSE { $$ = new BoolLiteral (false); }
+ ;
+
+parenthesized_expression
+ : OPEN_PARENS expression CLOSE_PARENS
+ { $$ = $2; }
+ ;
+
+member_access
+ : primary_expression DOT IDENTIFIER
+ {
+ $$ = new MemberAccess ((Expression) $1, (string) $3);
+ }
+ | predefined_type DOT IDENTIFIER
+ {
+ $$ = new SimpleName ((string) $1 + "." + (string) $3, lexer.Location);
+ }
+ ;
+
+predefined_type
+ : builtin_types
+ ;
+
+invocation_expression
+ : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ // FIXME:
+ // if $1 is MethodGroup
+ // $$ = new Call ($1, $3);
+ // else
+ // $$ = new DelegateCall ($1, $3);
+ if ($1 == null) {
+ Location l = lexer.Location;
+ Report.Error (1, l, "THIS IS CRAZY");
+ }
+ $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
+
+ }
+ ;
+
+opt_argument_list
+ : /* empty */ { $$ = null; }
+ | argument_list
+ ;
+
+argument_list
+ : argument
+ {
+ ArrayList list = new ArrayList ();
+ list.Add ($1);
+ $$ = list;
+ }
+ | argument_list COMMA argument
+ {
+ ArrayList list = (ArrayList) $1;
+ list.Add ($3);
+ $$ = list;
+ }
+ ;
+
+argument
+ : expression
+ {
+ $$ = new Argument ((Expression) $1, Argument.AType.Expression);
+ }
+ | REF variable_reference
+ {
+ $$ = new Argument ((Expression) $2, Argument.AType.Ref);
+ }
+ | OUT variable_reference
+ {
+ $$ = new Argument ((Expression) $2, Argument.AType.Out);
+ }
+ ;
+
+variable_reference
+ : expression { note ("section 5.4"); $$ = $1; }
+ ;
+
+element_access
+ : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
+ {
+ $$ = new ElementAccess ((Expression) $1, (ArrayList) $3);
+ }
+ ;
+
+expression_list
+ : expression
+ {
+ ArrayList list = new ArrayList ();
+ list.Add ($1);
+ $$ = list;
+ }
+ | expression_list COMMA expression
+ {
+ ArrayList list = (ArrayList) $1;
+ list.Add ($3);
+ $$ = list;
+ }
+ ;
+
+this_access
+ : THIS
+ {
+ $$ = new This ();
+ }
+ ;
+
+base_access
+ : BASE DOT IDENTIFIER
+ {
+ $$ = new BaseAccess (BaseAccess.BaseAccessType.Member, (string) $3, null);
+ }
+ | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
+ {
+ $$ = new BaseAccess (BaseAccess.BaseAccessType.Indexer, null, (ArrayList) $3);
+ }
+ ;
+
+post_increment_expression
+ : primary_expression OP_INC
+ {
+ $$ = new Unary (Unary.Operator.PostIncrement, (Expression) $1, lexer.Location);
+ }
+ ;
+
+post_decrement_expression
+ : primary_expression OP_DEC
+ {
+ $$ = new Unary (Unary.Operator.PostDecrement, (Expression) $1, lexer.Location);
+ }
+ ;
+
+new_expression
+ : object_or_delegate_creation_expression
+ | array_creation_expression
+ ;
+
+object_or_delegate_creation_expression
+ : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ $$ = new New ((string) $2, (ArrayList) $4, lexer.Location);
+ }
+ ;
+
+array_creation_expression
+ : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
+ opt_rank_specifier
+ opt_array_initializer
+ {
+ $$ = new New ((string) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
+ }
+ ;
+
+opt_rank_specifier
+ : /* empty */
+ {
+ $$ = "";
+ }
+ | rank_specifiers
+ {
+ $$ = $1;
+ }
+ ;
+
+rank_specifiers
+ : rank_specifier
+ {
+ $$ = $1;
+ }
+ | rank_specifier rank_specifiers
+ {
+ $$ = (string) $1 + (string) $2;
+ }
+ ;
+
+rank_specifier
+ : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
+ {
+ $$ = "[" + (string) $2 + "]";
+ }
+ ;
+
+opt_dim_separators
+ : /* empty */
+ {
+ $$ = "";
+ }
+ | dim_separators
+ {
+ $$ = $1;
+ }
+ ;
+
+dim_separators
+ : COMMA
+ {
+ $$ = ",";
+ }
+ | dim_separators COMMA
+ {
+ $$ =(string) $1 + ",";
+ }
+ ;
+
+opt_array_initializer
+ : /* empty */
+ {
+ $$ = null;
+ }
+ | array_initializer
+ {
+ $$ = $1;
+ }
+ ;
+
+array_initializer
+ : OPEN_BRACE CLOSE_BRACE
+ {
+ ArrayList list = new ArrayList ();
+ $$ = list;
+ }
+ | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
+ {
+ $$ = (ArrayList) $2;
+ }
+ ;
+
+variable_initializer_list
+ : variable_initializer
+ {
+ ArrayList list = new ArrayList ();
+ list.Add ($1);
+ $$ = list;
+ }
+ | variable_initializer_list COMMA variable_initializer
+ {
+ ArrayList list = (ArrayList) $1;
+ list.Add ($3);
+ $$ = list;
+ }
+ ;
+
+typeof_expression
+ : TYPEOF OPEN_PARENS type CLOSE_PARENS
+ {
+ $$ = new TypeOf ((string) $3);
+ }
+ ;
+
+sizeof_expression
+ : SIZEOF OPEN_PARENS type CLOSE_PARENS {
+ $$ = new SizeOf ((string) $3);
+
+ note ("Verify type is unmanaged");
+ note ("if (5.8) builtin, yield constant expression");
+ }
+ ;
+
+checked_expression
+ : CHECKED OPEN_PARENS expression CLOSE_PARENS
+ {
+ $$ = new CheckedExpr ((Expression) $3);
+ }
+ ;
+
+unchecked_expression
+ : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
+ {
+ $$ = new UnCheckedExpr ((Expression) $3);
+ }
+ ;
+
+unary_expression
+ : primary_expression
+ | PLUS unary_expression {
+ $$ = new Unary (Unary.Operator.Addition, (Expression) $2, lexer.Location);
+ }
+ | MINUS unary_expression
+ {
+ $$ = new Unary (Unary.Operator.Subtraction, (Expression) $2, lexer.Location);
+ }
+ | BANG unary_expression
+ {
+ $$ = new Unary (Unary.Operator.Negate, (Expression) $2, lexer.Location);
+ }
+ | TILDE unary_expression
+ {
+ $$ = new Unary (Unary.Operator.BitComplement, (Expression) $2, lexer.Location);
+ }
+ | STAR unary_expression
+ {
+ $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
+ }
+ | BITWISE_AND unary_expression
+ {
+ $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
+ }
+ | OP_INC unary_expression
+ {
+ $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);
+ }
+ | OP_DEC unary_expression
+ {
+ $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);
+ }
+ | cast_expression
+ /*
+ we can not do cast expressions at this level,
+ as there is an ambiguity. Check "Cast Expressions" 7.6.8
+ for the recipe to handle this.
+ */
+ ;
+
+pre_increment_expression
+ : OP_INC unary_expression
+ {
+ $$ = new Unary (Unary.Operator.PreIncrement, (Expression) $2, lexer.Location);
+ }
+ ;
+
+pre_decrement_expression
+ : OP_DEC unary_expression
+ {
+ $$ = new Unary (Unary.Operator.PreDecrement, (Expression) $2, lexer.Location);
+ }
+ ;
+
+cast_expression
+ /*
+ * FIXME: This is actually wrong, it should be `type' but that
+ * introduces a lot of {shift,reduce}/reduces
+ *
+ * This is really really wrong. We need to track down
+ * the source of problems with QIs because expressions like:
+ * foreach (string s in (string []) object) wont be parsed.
+ */
+ : OPEN_PARENS qualified_identifier CLOSE_PARENS unary_expression
+ {
+ $$ = new Cast ((string) $2, (Expression) $4);
+ }
+ | OPEN_PARENS builtin_types CLOSE_PARENS unary_expression
+ {
+ $$ = new Cast ((string) $2, (Expression) $4);
+ }
+ ;
+
+multiplicative_expression
+ : unary_expression
+ | multiplicative_expression STAR unary_expression
+ {
+ $$ = new Binary (Binary.Operator.Multiply,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | multiplicative_expression DIV unary_expression
+ {
+ $$ = new Binary (Binary.Operator.Division,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | multiplicative_expression PERCENT unary_expression
+ {
+ $$ = new Binary (Binary.Operator.Modulus,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+additive_expression
+ : multiplicative_expression
+ | additive_expression PLUS multiplicative_expression
+ {
+ $$ = new Binary (Binary.Operator.Addition,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | additive_expression MINUS multiplicative_expression
+ {
+ $$ = new Binary (Binary.Operator.Subtraction,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+shift_expression
+ : additive_expression
+ | shift_expression OP_SHIFT_LEFT additive_expression
+ {
+ $$ = new Binary (Binary.Operator.LeftShift,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | shift_expression OP_SHIFT_RIGHT additive_expression
+ {
+ $$ = new Binary (Binary.Operator.RightShift,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+relational_expression
+ : shift_expression
+ | relational_expression OP_LT shift_expression
+ {
+ $$ = new Binary (Binary.Operator.LessThan,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | relational_expression OP_GT shift_expression
+ {
+ $$ = new Binary (Binary.Operator.GreaterThan,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | relational_expression OP_LE shift_expression
+ {
+ $$ = new Binary (Binary.Operator.LessThanOrEqual,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | relational_expression OP_GE shift_expression
+ {
+ $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | relational_expression IS type
+ {
+ $$ = new Probe (Probe.Operator.Is,
+ (Expression) $1, (string) $3);
+ }
+ | relational_expression AS type
+ {
+ $$ = new Probe (Probe.Operator.As,
+ (Expression) $1, (string) $3);
+ }
+ ;
+
+equality_expression
+ : relational_expression
+ | equality_expression OP_EQ relational_expression
+ {
+ $$ = new Binary (Binary.Operator.Equality,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | equality_expression OP_NE relational_expression
+ {
+ $$ = new Binary (Binary.Operator.Inequality,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+and_expression
+ : equality_expression
+ | and_expression BITWISE_AND equality_expression
+ {
+ $$ = new Binary (Binary.Operator.BitwiseAnd,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+exclusive_or_expression
+ : and_expression
+ | exclusive_or_expression CARRET and_expression
+ {
+ $$ = new Binary (Binary.Operator.ExclusiveOr,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+inclusive_or_expression
+ : exclusive_or_expression
+ | inclusive_or_expression BITWISE_OR exclusive_or_expression
+ {
+ $$ = new Binary (Binary.Operator.BitwiseOr,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+conditional_and_expression
+ : inclusive_or_expression
+ | conditional_and_expression OP_AND inclusive_or_expression
+ {
+ $$ = new Binary (Binary.Operator.LogicalAnd,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+conditional_or_expression
+ : conditional_and_expression
+ | conditional_or_expression OP_OR conditional_and_expression
+ {
+ $$ = new Binary (Binary.Operator.LogicalOr,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+conditional_expression
+ : conditional_or_expression
+ | conditional_or_expression INTERR expression COLON expression
+ {
+ $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
+ }
+ ;
+
+assignment_expression
+ : unary_expression ASSIGN expression
+ {
+ $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | unary_expression OP_MULT_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.Multiply,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_DIV_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.Division,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_MOD_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.Modulus,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_ADD_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.Addition,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_SUB_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.Subtraction,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_SHIFT_LEFT_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.LeftShift,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_SHIFT_RIGHT_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.RightShift,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_AND_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.BitwiseAnd,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_OR_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.BitwiseOr,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ | unary_expression OP_XOR_ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new Assign ((Expression) $1,
+ new Binary (Binary.Operator.ExclusiveOr,
+ (Expression) $1,
+ (Expression) $3, l), l);
+ }
+ ;
+
+expression
+ : conditional_expression
+ | assignment_expression
+ ;
+
+constant_expression
+ : expression
+ ;
+
+boolean_expression
+ : expression { CheckBoolean ((Expression) $1); $$ = $1; }
+ ;
+
+//
+// 10 classes
+//
+class_declaration
+ : opt_attributes
+ opt_modifiers
+ CLASS IDENTIFIER
+ {
+ Class new_class;
+ string full_class_name = MakeName ((string) $4);
+
+ new_class = new Class (rc, current_container, full_class_name, (int) $2,
+ (Attributes) $1, lexer.Location);
+ current_container = new_class;
+ current_container.Namespace = current_namespace;
+ tree.RecordClass (full_class_name, new_class);
+ }
+ opt_class_base
+ class_body
+ opt_semicolon
+ {
+ Class new_class = (Class) current_container;
+
+ if ($6 != null)
+ new_class.Bases = (ArrayList) $6;
+
+ current_container = current_container.Parent;
+ CheckDef (current_container.AddClass (new_class), new_class.Name);
+
+ $$ = new_class;
+ }
+ ;
+
+opt_modifiers
+ : /* empty */ { $$ = (int) 0; }
+ | modifiers
+ ;
+
+modifiers
+ : modifier
+ | modifiers modifier
+ {
+ int m1 = (int) $1;
+ int m2 = (int) $2;
+
+ if ((m1 & m2) != 0) {
+ Location l = lexer.Location;
+ Report.Error (1002, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
+ }
+ $$ = (int) (m1 | m2);
+ }
+ ;
+
+modifier
+ : NEW { $$ = Modifiers.NEW; }
+ | PUBLIC { $$ = Modifiers.PUBLIC; }
+ | PROTECTED { $$ = Modifiers.PROTECTED; }
+ | INTERNAL { $$ = Modifiers.INTERNAL; }
+ | PRIVATE { $$ = Modifiers.PRIVATE; }
+ | ABSTRACT { $$ = Modifiers.ABSTRACT; }
+ | SEALED { $$ = Modifiers.SEALED; }
+ | STATIC { $$ = Modifiers.STATIC; }
+ | READONLY { $$ = Modifiers.READONLY; }
+ | VIRTUAL { $$ = Modifiers.VIRTUAL; }
+ | OVERRIDE { $$ = Modifiers.OVERRIDE; }
+ | EXTERN { $$ = Modifiers.EXTERN; }
+ ;
+
+opt_class_base
+ : /* empty */ { $$ = null; }
+ | class_base { $$ = $1; }
+ ;
+
+class_base
+ : COLON type_list { $$ = $2; }
+ ;
+
+//
+// Statements (8.2)
+//
+
+//
+// A block is "contained" on the following places:
+// method_body
+// property_declaration as part of the accessor body (get/set)
+// operator_declaration
+// constructor_declaration
+// destructor_declaration
+// event_declaration as part of add_accessor_declaration or remove_accessor_declaration
+//
+block
+ : OPEN_BRACE
+ {
+ current_block = new Block (current_block);
+ }
+ opt_statement_list CLOSE_BRACE
+ {
+ while (current_block.Implicit)
+ current_block = current_block.Parent;
+ $$ = current_block;
+ current_block = current_block.Parent;
+ }
+ ;
+
+opt_statement_list
+ : /* empty */
+ | statement_list
+ ;
+
+statement_list
+ : statement
+ | statement_list statement
+ ;
+
+statement
+ : declaration_statement
+ {
+ if ((Block) $1 != current_block){
+ current_block.AddStatement ((Statement) $1);
+ current_block = (Block) $1;
+ }
+ }
+ | embedded_statement
+ {
+ current_block.AddStatement ((Statement) $1);
+ }
+ | labeled_statement
+ {
+ current_block.AddStatement ((Statement) $1);
+ }
+ ;
+
+embedded_statement
+ : block
+ | empty_statement
+ | expression_statement
+ | selection_statement
+ | iteration_statement
+ | jump_statement
+ | try_statement
+ | checked_statement
+ | unchecked_statement
+ | lock_statement
+ | using_statement
+ ;
+
+empty_statement
+ : SEMICOLON
+ {
+ $$ = new EmptyStatement ();
+ }
+ ;
+
+labeled_statement
+ : IDENTIFIER COLON statement
+ {
+ string lab = (String) $1;
+ Block block;
+
+ block = new Block (current_block, lab);
+ block.AddStatement ((Statement) $3);
+ $$ = block;
+
+ if (!current_block.AddLabel (lab, block)){
+ Location l = lexer.Location;
+ Report.Error (140, l, "The label '" + lab + "' is a duplicate");
+ $$ = $3;
+ }
+ }
+ ;
+
+declaration_statement
+ : local_variable_declaration SEMICOLON // done
+ | local_constant_declaration SEMICOLON // finishme
+ ;
+
+/*
+ * The following is from Rhys' grammar:
+ * > Types in local variable declarations must be recognized as
+ * > expressions to prevent reduce/reduce errors in the grammar.
+ * > The expressions are converted into types during semantic analysis.
+ */
+local_variable_type
+ : primary_expression type_suffixes
+ {
+ // FIXME: Do something smart here regarding the composition of the type.
+
+ // Ok, the above "primary_expression" is there to get rid of
+ // both reduce/reduce and shift/reduces in the grammar, it should
+ // really just be "type_name". If you use type_name, a reduce/reduce
+ // creeps up. If you use qualified_identifier (which is all we need
+ // really) two shift/reduces appear.
+ //
+ // So, instead we do a super trick: we just allow ($1) to be a
+ // SimpleName Expression.
+ //
+ if (((Expression) $1) is SimpleName)
+ $$ = ((SimpleName) $1).Name;
+ else {
+ Location l = lexer.Location;
+ Report.Error (-1, l, "Invalid Type definition");
+ $$ = "System.Object";
+ }
+ }
+ | builtin_types type_suffixes
+ {
+ $$ = (string) $1 + (string) $2;
+ }
+ ;
+
+// FIXME : How can the type of a local variable be void ? I don't quite see ;-)
+// | VOID
+// {
+// // FIXME: this is a string that represents the type
+// // Figure out something to make this work.
+// $$ = "void";
+// }
+// ;
+
+type_suffixes
+ : /* empty */
+ {
+ $$ = "";
+ }
+ | type_suffix_list
+ ;
+
+type_suffix_list
+ : type_suffix
+ | type_suffix_list type_suffix
+ {
+ $$ = (string) $1 + (string) $2;
+ }
+ ;
+
+type_suffix
+ : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
+ {
+ $$ = "[" + (string) $2 + "]";
+ }
+ ;
+
+local_variable_declaration
+ : local_variable_type variable_declarators
+ {
+ $$ = declare_local_variables ((string) $1, (ArrayList) $2);
+ }
+ ;
+
+local_constant_declaration
+ : CONST type constant_declarator
+ // finishme
+ ;
+
+expression_statement
+ : statement_expression SEMICOLON
+ {
+ $$ = $1;
+ }
+ ;
+
+ //
+ // We have to do the wrapping here and not in the case above,
+ // because statement_expression is used for example in for_statement
+ //
+statement_expression
+ : invocation_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
+ | object_creation_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
+ | assignment_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
+ | post_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
+ | post_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
+ | pre_increment_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
+ | pre_decrement_expression { $$ = new StatementExpression ((ExpressionStatement) $1); }
+ ;
+
+object_creation_expression
+ : object_or_delegate_creation_expression
+ { note ("complain if this is a delegate maybe?"); }
+ ;
+
+selection_statement
+ : if_statement
+ | switch_statement
+ ;
+
+if_statement
+ : IF OPEN_PARENS boolean_expression CLOSE_PARENS
+ embedded_statement
+ {
+ $$ = new If ((Expression) $3, (Statement) $5);
+ }
+ | IF OPEN_PARENS boolean_expression CLOSE_PARENS
+ embedded_statement ELSE embedded_statement
+ {
+ $$ = new If ((Expression) $3, (Statement) $5, (Statement) $7);
+ }
+ ;
+
+switch_statement
+ : SWITCH OPEN_PARENS expression CLOSE_PARENS
+ switch_block
+ {
+ $$ = new Switch ((Expression) $3, (ArrayList) $5);
+ }
+ ;
+
+switch_block
+ : OPEN_BRACE
+ opt_switch_sections
+ CLOSE_BRACE
+ {
+ $$ = $2;
+ }
+ ;
+
+opt_switch_sections
+ : /* empty */ { $$ = new ArrayList (); }
+ | switch_sections
+ ;
+
+switch_sections
+ : switch_section
+ {
+ ArrayList sections = new ArrayList ();
+
+ sections.Add ($1);
+ $$ = sections;
+ }
+ | switch_sections switch_section
+ {
+ ArrayList sections = (ArrayList) $1;
+
+ sections.Add ($2);
+ $$ = sections;
+ }
+ ;
+
+switch_section
+ : switch_labels
+ {
+ current_block = new Block (current_block);
+ }
+ statement_list
+ {
+ while (current_block.Implicit)
+ current_block = current_block.Parent;
+ $$ = new SwitchSection ((ArrayList) $1, current_block);
+ current_block = current_block.Parent;
+ }
+ ;
+
+switch_labels
+ : switch_label
+ {
+ ArrayList labels = new ArrayList ();
+
+ labels.Add ($1);
+ $$ = labels;
+ }
+ | switch_labels switch_label
+ {
+ ArrayList labels = (ArrayList) ($1);
+ labels.Add ($2);
+
+ $$ = labels;
+ }
+ ;
+
+switch_label
+ : CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2); }
+ | DEFAULT COLON { $$ = new SwitchLabel (null); }
+ ;
+
+iteration_statement
+ : while_statement
+ | do_statement
+ | for_statement
+ | foreach_statement
+ ;
+
+while_statement
+ : WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
+ {
+ $$ = new While ((Expression) $3, (Statement) $5);
+ }
+ ;
+
+do_statement
+ : DO embedded_statement
+ WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
+ {
+ $$ = new Do ((Statement) $2, (Expression) $5);
+ }
+ ;
+
+for_statement
+ : FOR OPEN_PARENS
+ opt_for_initializer SEMICOLON
+ opt_for_condition SEMICOLON
+ opt_for_iterator CLOSE_PARENS
+ embedded_statement
+ {
+ $$ = new For ((Statement) $3, (Expression) $5, (Statement) $7, (Statement) $9);
+ }
+ ;
+
+opt_for_initializer
+ : /* empty */ { $$ = new EmptyStatement (); }
+ | for_initializer
+ ;
+
+for_initializer
+ : local_variable_declaration
+ | statement_expression_list
+ ;
+
+opt_for_condition
+ : /* empty */ { $$ = new BoolLiteral (true); }
+ | boolean_expression
+ ;
+
+opt_for_iterator
+ : /* empty */ { $$ = new EmptyStatement (); }
+ | for_iterator
+ ;
+
+for_iterator
+ : statement_expression_list
+ ;
+
+statement_expression_list
+ : statement_expression
+ {
+ Block b = new Block (null, true);
+
+ b.AddStatement ((Statement) $1);
+ $$ = b;
+ }
+ | statement_expression_list COMMA statement_expression
+ {
+ Block b = (Block) $1;
+
+ b.AddStatement ((Statement) $3);
+ $$ = $1;
+ }
+ ;
+
+foreach_statement
+ : FOREACH OPEN_PARENS type IDENTIFIER IN expression CLOSE_PARENS
+ embedded_statement
+ {
+ string temp_id = current_block.MakeInternalID ();
+ ExpressionStatement assign_e;
+ Expression ma;
+ Statement getcurrent;
+ Block foreach_block, child_block;
+ Location l = lexer.Location;
+
+ foreach_block = new Block (current_block, true);
+
+ foreach_block.AddVariable ("System.IEnumerator", temp_id, l);
+ foreach_block.AddVariable ((string) $3, (string) $4, l);
+ assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id),
+ new Invocation (
+ new MemberAccess ((Expression) $6, "GetEnumerator"),
+ null, lexer.Location), lexer.Location);
+ current_block.AddStatement (new StatementExpression (assign_e));
+ ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");
+ child_block = new Block (current_block);
+
+ getcurrent = new StatementExpression (
+ new Assign (
+ new LocalVariableReference (foreach_block, (string) $4),
+ new Cast (
+ (string) $3,
+ new MemberAccess (
+ new LocalVariableReference (foreach_block, temp_id), "Current")),
+ lexer.Location));
+
+ child_block.AddStatement (getcurrent);
+ child_block.AddStatement ((Statement) $8);
+ foreach_block.AddStatement (new While (ma, (Statement) child_block));
+
+ $$ = foreach_block;
+ }
+ ;
+
+jump_statement
+ : break_statement
+ | continue_statement
+ | goto_statement
+ | return_statement
+ | throw_statement
+ ;
+
+break_statement
+ : BREAK SEMICOLON
+ {
+ $$ = new Break ();
+ }
+ ;
+
+continue_statement
+ : CONTINUE SEMICOLON
+ {
+ $$ = new Continue ();
+ }
+ ;
+
+goto_statement
+ : GOTO IDENTIFIER SEMICOLON
+ {
+ $$ = new Goto ((string) $2);
+ }
+ | GOTO CASE constant_expression SEMICOLON
+ | GOTO DEFAULT SEMICOLON
+ ;
+
+return_statement
+ : RETURN opt_expression SEMICOLON
+ {
+ $$ = new Return ((Expression) $2);
+ }
+ ;
+
+throw_statement
+ : THROW opt_expression SEMICOLON
+ {
+ $$ = new Throw ((Expression) $2);
+ }
+ ;
+
+opt_expression
+ : /* empty */
+ | expression
+ ;
+
+try_statement
+ : TRY block catch_clauses
+ {
+ Catch g = null;
+ ArrayList s = new ArrayList ();
+
+ foreach (Catch cc in (ArrayList) $3) {
+ if (cc.Type == null)
+ g = cc;
+ else
+ s.Add (cc);
+ }
+
+ // Now s contains the list of specific catch clauses
+ // and g contains the general one.
+
+ $$ = new Try ((Block) $2, s, g, null);
+ }
+ | TRY block opt_catch_clauses FINALLY block
+ {
+ Catch g = null;
+ ArrayList s = new ArrayList ();
+
+ foreach (Catch cc in (ArrayList) $3) {
+ if (cc.Type == null)
+ g = cc;
+ else
+ s.Add (cc);
+ }
+
+ $$ = new Try ((Block) $2, s, g, (Block) $5);
+ }
+ ;
+
+opt_catch_clauses
+ : /* empty */ { $$ = null; }
+ | catch_clauses
+ ;
+
+catch_clauses
+ : catch_clause
+ {
+ ArrayList l = new ArrayList ();
+
+ l.Add ($1);
+ $$ = l;
+ }
+ | catch_clauses catch_clause
+ {
+ ArrayList l = (ArrayList) $1;
+
+ l.Add ($2);
+ $$ = l;
+ }
+ ;
+
+opt_identifier
+ : /* empty */ { $$ = null; }
+ | IDENTIFIER
+ ;
+
+catch_clause
+ : CATCH opt_catch_args block
+ {
+ string type = null;
+ string id = null;
+
+ if ($2 != null) {
+ DictionaryEntry cc = (DictionaryEntry) $2;
+ type = (string) cc.Key;
+ id = (string) cc.Value;
+ }
+
+ $$ = new Catch (type, id, (Block) $3);
+ }
+ ;
+
+opt_catch_args
+ : /* empty */ { $$ = null; }
+ | catch_args
+ ;
+
+catch_args
+ : OPEN_PARENS type opt_identifier CLOSE_PARENS
+ {
+ $$ = new DictionaryEntry ($2, $3);
+ }
+ ;
+
+checked_statement
+ : CHECKED block
+ {
+ $$ = new Checked ((Block) $2);
+ }
+ ;
+
+unchecked_statement
+ : UNCHECKED block
+ {
+ $$ = new Unchecked ((Block) $2);
+ }
+ ;
+
+lock_statement
+ : LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
+ {
+ $$ = new Lock ((Expression) $3, (Statement) $5);
+ }
+ ;
+
+using_statement
+ : USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
+ // finishme
+ ;
+
+resource_acquisition
+ : local_variable_declaration
+ expression
+ // finishme
+ ;
+
+%%
+
+// <summary>
+// A class used to pass around variable declarations and constants
+// </summary>
+public class VariableDeclaration {
+ public string identifier;
+ public object expression_or_array_initializer;
+ public Location Location;
+
+ public VariableDeclaration (string id, object eoai, Location l){
+ this.identifier = id;
+ this.expression_or_array_initializer = eoai;
+ this.Location = l;
+ }
+}
+
+// <summary>
+// A class used to hold info about an indexer declarator
+// </summary>
+
+public class IndexerDeclaration {
+ public string type;
+ public string interface_type;
+ public Parameters param_list;
+
+ public IndexerDeclaration (string type, string interface_type, Parameters param_list)
+ {
+ this.type = type;
+ this.interface_type = interface_type;
+ this.param_list = param_list;
+ }
+}
+
+// <summary>
+// A class used to hold info about an operator declarator
+// </summary>
+
+public class OperatorDeclaration {
+ public Operator.OpType optype;
+ public string ret_type;
+ public string arg1type;
+ public string arg1name;
+ public string arg2type;
+ public string arg2name;
+ public Location location;
+
+ public OperatorDeclaration (Operator.OpType op, string ret_type, string arg1type, string arg1name,
+ string arg2type, string arg2name, Location location)
+ {
+ optype = op;
+ this.ret_type = ret_type;
+ this.arg1type = arg1type;
+ this.arg1name = arg1name;
+ this.arg2type = arg2type;
+ this.arg2name = arg2name;
+ this.location = location;
+ }
+
+}
+
+// <summary>
+// Given the @class_name name, it creates a fully qualified name
+// based on the containing declaration space
+// </summary>
+string
+MakeName (string class_name)
+{
+ string ns = current_namespace.Name;
+ string container_name = current_container.Name;
+
+ if (container_name == ""){
+ if (ns != "")
+ return ns + "." + class_name;
+ else
+ return class_name;
+ } else
+ return container_name + "." + class_name;
+}
+
+// <summary>
+// Used to report back to the user the result of a declaration
+// in the current declaration space
+// </summary>
+void
+CheckDef (DeclSpace.AdditionResult result, string name)
+{
+ if (result == DeclSpace.AdditionResult.Success)
+ return;
+
+ Location l = lexer.Location;
+
+ switch (result){
+ case DeclSpace.AdditionResult.NameExists:
+ Report.Error (102, l, "The namespace `" + current_container.Name +
+ "' already contains a definition for `"+
+ name + "'");
+ break;
+
+
+// NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
+//
+// case DeclSpace.AdditionResult.MethodDuplicated:
+// error (111, "Class `"+current_container.Name+
+// "' already defines a member called '" +
+// name + "' with the same parameter types");
+// break;
+
+ case DeclSpace.AdditionResult.EnclosingClash:
+ Report.Error (542, l, "Member names cannot be the same as their enclosing type");
+ break;
+
+ case DeclSpace.AdditionResult.NotAConstructor:
+ Report.Error (1520, l, "Class, struct, or interface method must have a return type");
+ break;
+ }
+}
+
+void
+CheckDef (bool result, string name)
+{
+ if (result)
+ return;
+ CheckDef (DeclSpace.AdditionResult.NameExists, name);
+}
+
+object
+SimpleLookup (string name)
+{
+ //
+ // we need to check against current_block not being null
+ // as `expression' is allowed in argument_lists, which
+ // do not exist inside a block.
+ //
+ if (current_block != null){
+ if (current_block.IsVariableDefined (name))
+ return new LocalVariableReference (current_block, name);
+ }
+
+ if (current_local_parameters != null){
+ int idx;
+ Parameter par = current_local_parameters.GetParameterByName (name, out idx);
+ if (par != null)
+ return new ParameterReference (current_local_parameters, idx, name);
+ }
+
+ return null;
+}
+
+//
+// Assumes that the name contains a `.' and tries to perform a simple lookup
+// and shape the result to be a MemberAccess on a Local/Parameter
+//
+object CompositeLookup (string name)
+{
+ int pos = name.IndexOf (".");
+ string left = name.Substring (0, pos);
+ object o;
+
+ o = SimpleLookup (left);
+ if (o != null){
+ string right = name.Substring (pos + 1);
+ return new MemberAccess ((Expression) o, right);
+ }
+
+ return null;
+}
+
+object QualifiedIdentifier (string name, Location l)
+{
+ object o;
+
+ if (name.IndexOf ('.') == -1)
+ o = SimpleLookup (name);
+ else
+ o = CompositeLookup (name);
+
+ if (o == null)
+ o = new SimpleName (name, l);
+
+ return o;
+}
+
+Block declare_local_variables (string type, ArrayList variable_declarators)
+{
+ Block implicit_block;
+ ArrayList inits = null;
+
+ //
+ // We use the `Used' property to check whether statements
+ // have been added to the current block. If so, we need
+ // to create another block to contain the new declaration
+ // otherwise, as an optimization, we use the same block to
+ // add the declaration.
+ //
+ // FIXME: A further optimization is to check if the statements
+ // that were added were added as part of the initialization
+ // below. In which case, no other statements have been executed
+ // and we might be able to reduce the number of blocks for
+ // situations like this:
+ //
+ // int j = 1; int k = j + 1;
+ //
+ if (current_block.Used)
+ implicit_block = new Block (current_block, true);
+ else
+ implicit_block = new Block (current_block, true);
+
+ foreach (VariableDeclaration decl in variable_declarators){
+ if (implicit_block.AddVariable (type, decl.identifier, decl.Location)){
+ if (decl.expression_or_array_initializer != null){
+ if (inits == null)
+ inits = new ArrayList ();
+ inits.Add (decl);
+ }
+ } else {
+ Location l = lexer.Location;
+ Report.Error (128, l, "A local variable `" + decl.identifier +
+ "' is already defined in this scope");
+ }
+ }
+
+ if (inits == null)
+ return implicit_block;
+
+ foreach (VariableDeclaration decl in inits){
+ if (decl.expression_or_array_initializer is Expression){
+ Expression expr = (Expression) decl.expression_or_array_initializer;
+ Assign assign;
+
+ assign = new Assign (new LocalVariableReference (
+ implicit_block, decl.identifier),
+ expr, lexer.Location);
+ implicit_block.AddStatement (new StatementExpression (assign));
+ } else {
+ Console.WriteLine ("Not handling Array initializers yet");
+ }
+ }
+
+ return implicit_block;
+}
+
+void CheckConstant (Expression expr)
+{
+ // finishme
+}
+
+void CheckBoolean (Expression expr)
+{
+ // finishme
+}
+
+void CheckAttributeTarget (string a)
+{
+ switch (a) {
+
+ case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
+ return;
+
+ default :
+ Location l = lexer.Location;
+ Report.Error (658, l, "Invalid attribute target");
+ break;
+ }
+
+}
+
+void CheckUnaryOperator (Operator.OpType op)
+{
+ switch (op) {
+
+ case Operator.OpType.Negate:
+ case Operator.OpType.BitComplement:
+ case Operator.OpType.Increment:
+ case Operator.OpType.Decrement:
+ case Operator.OpType.True:
+ case Operator.OpType.False:
+ case Operator.OpType.Addition:
+ case Operator.OpType.Subtraction:
+
+ break;
+
+ default :
+ Location l = lexer.Location;
+ Report.Error (1019, l, "Overloadable unary operator expected");
+ break;
+
+ }
+}
+
+void CheckBinaryOperator (Operator.OpType op)
+{
+ switch (op) {
+
+ case Operator.OpType.Addition:
+ case Operator.OpType.Subtraction:
+ case Operator.OpType.Multiply:
+ case Operator.OpType.Division:
+ case Operator.OpType.Modulus:
+ case Operator.OpType.BitwiseAnd:
+ case Operator.OpType.BitwiseOr:
+ case Operator.OpType.ExclusiveOr:
+ case Operator.OpType.LeftShift:
+ case Operator.OpType.RightShift:
+ case Operator.OpType.Equality:
+ case Operator.OpType.Inequality:
+ case Operator.OpType.GreaterThan:
+ case Operator.OpType.LessThan:
+ case Operator.OpType.GreaterThanOrEqual:
+ case Operator.OpType.LessThanOrEqual:
+ break;
+
+ default :
+ Location l = lexer.Location;
+ Report.Error (1020, l, "Overloadable binary operator expected");
+ break;
+ }
+
+}
+
+void output (string s)
+{
+ Console.WriteLine (s);
+}
+
+void note (string s)
+{
+ // Used to put annotations
+}
+
+Tokenizer lexer;
+
+public Tokenizer Lexer {
+ get {
+ return lexer;
+ }
+}
+
+public CSharpParser(RootContext rc, string name, System.IO.Stream input)
+{
+ current_namespace = new Namespace (null, "");
+ this.rc = rc;
+ this.tree = rc.Tree;
+ this.name = name;
+ this.input = input;
+ current_container = tree.Types;
+ current_container.Namespace = current_namespace;
+
+ lexer = new Tokenizer (input, name);
+}
+
+public override int parse ()
+{
+ StringBuilder value = new StringBuilder ();
+
+ global_errors = 0;
+ try {
+ if (yacc_verbose_flag)
+ yyparse (lexer, new yydebug.yyDebugSimple ());
+ else
+ yyparse (lexer);
+ } catch (Exception e){
+ // Console.WriteLine ("Fatal error: " + name);
+ // Console.WriteLine (lexer.location);
+
+ Console.WriteLine (lexer.location + " : Parsing error");
+ Console.WriteLine (e);
+ global_errors++;
+ }
+
+ return global_errors;
+}
+
+
+/* end end end */
+}