X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fcs-parser.jay;h=68df7ca00741aa2f52426ed8bea440c58ac8df02;hb=4f18285002b709dba48164d1bfc195601d3d0337;hp=b412673f4c95ca4107179cb954b56292251a1489;hpb=d8a6fc45c58787be3510b3bca1525ff422935463;p=mono.git diff --git a/mcs/gmcs/cs-parser.jay b/mcs/gmcs/cs-parser.jay index b412673f4c9..68df7ca0074 100644 --- a/mcs/gmcs/cs-parser.jay +++ b/mcs/gmcs/cs-parser.jay @@ -4,6 +4,7 @@ // // Authors: Miguel de Icaza (miguel@gnu.org) // Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) // // Licensed under the terms of the GNU GPL // @@ -41,7 +42,7 @@ namespace Mono.CSharp /// Current block is used to add statements as we find /// them. /// - Block current_block, top_current_block; + Block current_block; Delegate current_delegate; @@ -79,7 +80,7 @@ namespace Mono.CSharp /// /// An out-of-band stack. /// - Stack oob_stack; + static Stack oob_stack; /// /// Switch stack. @@ -205,10 +206,25 @@ namespace Mono.CSharp %token ARGLIST %token PARTIAL %token ARROW +%token QUERY_FIRST_TOKEN +%token FROM +%token JOIN +%token ON +%token EQUALS +%token SELECT +%token GROUP +%token BY +%token LET +%token ORDERBY +%token ASCENDING +%token DESCENDING +%token INTO +%token QUERY_LAST_TOKEN /* C# keywords which are not really keywords */ %token GET "get" %token SET "set" +%token VAR %left LAST_KEYWORD @@ -264,6 +280,7 @@ namespace Mono.CSharp %token OP_XOR_ASSIGN "^=" %token OP_OR_ASSIGN "|=" %token OP_PTR "->" +%token OP_COALESCING "??" /* Numbers */ %token LITERAL_INTEGER "int literal" @@ -560,55 +577,63 @@ opt_attributes attribute_sections : attribute_section { - ArrayList sect = (ArrayList) $1; - - if (global_attrs_enabled) { - if (current_attr_target == "module") { - CodeGen.Module.AddAttributes (sect); - $$ = null; - } else if (current_attr_target != null && current_attr_target.Length > 0) { - CodeGen.Assembly.AddAttributes (sect); - $$ = null; + if (current_attr_target != String.Empty) { + ArrayList sect = (ArrayList) $1; + + if (global_attrs_enabled) { + if (current_attr_target == "module") { + CodeGen.Module.AddAttributes (sect); + $$ = null; + } else if (current_attr_target != null && current_attr_target.Length > 0) { + CodeGen.Assembly.AddAttributes (sect); + $$ = null; + } else { + $$ = new Attributes (sect); + } + if ($$ == null) { + if (RootContext.Documentation != null) { + Lexer.check_incorrect_doc_comment (); + Lexer.doc_state = + XmlCommentState.Allowed; + } + } } else { $$ = new Attributes (sect); - } - if ($$ == null) { - if (RootContext.Documentation != null) { - Lexer.check_incorrect_doc_comment (); - Lexer.doc_state = - XmlCommentState.Allowed; - } - } - } else { - $$ = new Attributes (sect); - } + } + } + else + $$ = null; current_attr_target = null; - } + } | attribute_sections attribute_section { - Attributes attrs = $1 as Attributes; - ArrayList sect = (ArrayList) $2; - - if (global_attrs_enabled) { - if (current_attr_target == "module") { - CodeGen.Module.AddAttributes (sect); - $$ = null; - } else if (current_attr_target == "assembly") { - CodeGen.Assembly.AddAttributes (sect); - $$ = null; + if (current_attr_target != String.Empty) { + Attributes attrs = $1 as Attributes; + ArrayList sect = (ArrayList) $2; + + if (global_attrs_enabled) { + if (current_attr_target == "module") { + CodeGen.Module.AddAttributes (sect); + $$ = null; + } else if (current_attr_target == "assembly") { + CodeGen.Assembly.AddAttributes (sect); + $$ = null; + } else { + if (attrs == null) + attrs = new Attributes (sect); + else + attrs.AddAttributes (sect); + } } else { if (attrs == null) attrs = new Attributes (sect); else - attrs.AddAttributes (sect); - } - } else { - if (attrs == null) - attrs = new Attributes (sect); - else - attrs.AddAttributes (sect); - } - $$ = attrs; + attrs.AddAttributes (sect); + } + $$ = attrs; + } + else + $$ = null; current_attr_target = null; } ; @@ -636,11 +661,15 @@ attribute_target : IDENTIFIER { LocatedToken lt = (LocatedToken) $1; - CheckAttributeTarget (lt.Value, lt.Location); - $$ = lt.Value; // Location won't be required anymore. + $$ = CheckAttributeTarget (lt.Value, lt.Location); } | EVENT { $$ = "event"; } | RETURN { $$ = "return"; } + | error + { + string name = yyNames [yyToken].ToLower (); + $$ = CheckAttributeTarget (name, GetLocation ($1)); + } ; attribute_list @@ -676,7 +705,9 @@ attribute Expression left_expr = left == null ? null : left.GetTypeExpression (); - if (current_attr_target == "assembly" || current_attr_target == "module") + if (current_attr_target == String.Empty) + $$ = null; + else if (current_attr_target == "assembly" || current_attr_target == "module") // FIXME: supply "nameEscaped" parameter here. $$ = new GlobalAttribute (current_namespace, current_attr_target, left_expr, identifier, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location)); @@ -814,7 +845,7 @@ struct_declaration MemberName name = MakeName ((MemberName) $6); push_current_class (new Struct ( current_namespace, current_class, name, (int) $2, - (Attributes) $1), false, $3); + (Attributes) $1), $3); } opt_class_base opt_type_parameter_constraints_clauses @@ -1097,6 +1128,7 @@ method_declaration anonymous_host = (IAnonymousHost) $1; if (RootContext.Documentation != null) Lexer.doc_state = XmlCommentState.NotAllowed; + Lexer.VarParsing = true; } method_body { @@ -1110,6 +1142,7 @@ method_declaration if (RootContext.Documentation != null) Lexer.doc_state = XmlCommentState.Allowed; + Lexer.VarParsing = false; } ; @@ -1132,11 +1165,22 @@ opt_error_modifier } ; + // + // This rule is used to handle the cases where OPEN_PARENS_LAMBDA + // is returned (type followed by an identifier), these are the + // declarations (methods, overloads, constructors, etc) and a handful + // of expressions ("using", "fixed") or "catch". + // +open_parens + : OPEN_PARENS + | OPEN_PARENS_LAMBDA + ; + method_header : opt_attributes opt_modifiers type namespace_or_type_name - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + open_parens opt_formal_parameter_list CLOSE_PARENS { lexer.ConstraintsParsing = true; } @@ -1175,7 +1219,7 @@ method_header | opt_attributes opt_modifiers VOID namespace_or_type_name - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + open_parens opt_formal_parameter_list CLOSE_PARENS { lexer.ConstraintsParsing = true; } @@ -1213,7 +1257,7 @@ method_header | opt_attributes opt_modifiers type - modifiers namespace_or_type_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + modifiers namespace_or_type_name open_parens opt_formal_parameter_list CLOSE_PARENS { MemberName name = (MemberName) $5; Report.Error (1585, name.Location, @@ -1314,8 +1358,12 @@ fixed_parameters | fixed_parameters COMMA fixed_parameter { ArrayList pars = (ArrayList) $1; - - pars.Add ($3); + Parameter p = (Parameter)$3; + if (p != null) { + if ((p.modFlags & Parameter.Modifier.This) != 0) + Report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter"); + pars.Add (p); + } $$ = $1; } ; @@ -1377,14 +1425,31 @@ parameter_modifiers } | parameter_modifiers parameter_modifier { - Report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier"); - $$ = $1; + Parameter.Modifier p2 = (Parameter.Modifier)$2; + Parameter.Modifier mod = (Parameter.Modifier)$1 | p2; + if (((Parameter.Modifier)$1 & p2) == p2) { + Error_DuplicateParameterModifier (lexer.Location, p2); + } else { + switch (mod & ~Parameter.Modifier.This) { + case Parameter.Modifier.REF: + Report.Error (1101, lexer.Location, "The parameter modifiers `this' and `ref' cannot be used altogether"); + break; + case Parameter.Modifier.OUT: + Report.Error (1102, lexer.Location, "The parameter modifiers `this' and `out' cannot be used altogether"); + break; + default: + Report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier"); + break; + } + } + $$ = mod; } ; parameter_modifier : REF { $$ = Parameter.Modifier.REF; } | OUT { $$ = Parameter.Modifier.OUT; } + | THIS { $$ = Parameter.Modifier.This; } ; parameter_array @@ -1393,10 +1458,20 @@ parameter_array LocatedToken lt = (LocatedToken) $4; $$ = new ParamsParameter ((Expression) $3, lt.Value, (Attributes) $1, lt.Location); } + | opt_attributes PARAMS PARAMS type IDENTIFIER + { + Error_DuplicateParameterModifier (lexer.Location, Parameter.Modifier.PARAMS); + $$ = null; + } | opt_attributes PARAMS parameter_modifier type IDENTIFIER { - Report.Error (1611, (Location) $2, "The params parameter cannot be declared as ref or out"); - $$ = null; + Parameter.Modifier mod = (Parameter.Modifier)$3; + if ((mod & Parameter.Modifier.This) != 0) { + Report.Error (1104, lexer.Location, "The parameter modifiers `this' and `params' cannot be used altogether"); + } else { + Report.Error (1611, (Location) $2, "The params parameter cannot be declared as ref or out"); + } + $$ = null; } | opt_attributes PARAMS type error { CheckIdentifierToken (yyToken, GetLocation ($4)); @@ -1440,8 +1515,8 @@ property_declaration syntax_error (lexer.Location, "a property can't have type arguments"); prop = new Property (current_class, (Expression) $3, (int) $2, false, - name, (Attributes) $1, get_block, set_block, accessors.declared_in_reverse); - + name, (Attributes) $1, get_block, set_block, accessors.declared_in_reverse, current_block); + current_container.AddProperty (prop); implicit_value_parameter_type = null; @@ -1587,7 +1662,7 @@ interface_declaration push_current_class (new Interface ( current_namespace, current_class, name, (int) $2, - (Attributes) $1), true, $3); + (Attributes) $1), $3); } opt_class_base opt_type_parameter_constraints_clauses @@ -1749,7 +1824,7 @@ opt_new ; interface_method_declaration_body - : OPEN_BRACE + : OPEN_BRACE { lexer.ConstraintsParsing = false; } @@ -1764,7 +1839,7 @@ interface_method_declaration_body interface_method_declaration : opt_attributes opt_new type namespace_or_type_name - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + open_parens opt_formal_parameter_list CLOSE_PARENS { lexer.ConstraintsParsing = true; } @@ -1797,7 +1872,7 @@ interface_method_declaration ((Method) $$).DocComment = Lexer.consume_doc_comment (); } | opt_attributes opt_new VOID namespace_or_type_name - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + open_parens opt_formal_parameter_list CLOSE_PARENS { lexer.ConstraintsParsing = true; } @@ -2017,13 +2092,13 @@ operator_body ; operator_declarator : type OPERATOR overloadable_operator - OPEN_PARENS opt_parameter_modifier type IDENTIFIER CLOSE_PARENS + open_parens opt_attributes opt_parameter_modifier type IDENTIFIER CLOSE_PARENS { // TODO: wrong location - if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE) + if ((Parameter.Modifier)$6 != Parameter.Modifier.NONE) Error_ParameterModifierNotValid ((Location) $2); - LocatedToken lt = (LocatedToken) $7; + LocatedToken lt = (LocatedToken) $8; Operator.OpType op = (Operator.OpType) $3; CheckUnaryOperator (op, lt.Location); @@ -2034,9 +2109,9 @@ operator_declarator op = Operator.OpType.UnaryNegation; Parameter [] pars = new Parameter [1]; - Expression type = (Expression) $6; + Expression type = (Expression) $7; - pars [0] = new Parameter (type, lt.Value, Parameter.Modifier.NONE, null, lt.Location); + pars [0] = new Parameter (type, lt.Value, Parameter.Modifier.NONE, (Attributes) $5, lt.Location); current_local_parameters = new Parameters (pars); @@ -2049,26 +2124,26 @@ operator_declarator null, null, (Location) $2); } | type OPERATOR overloadable_operator - OPEN_PARENS - opt_parameter_modifier type IDENTIFIER COMMA - opt_parameter_modifier type IDENTIFIER + open_parens + opt_attributes opt_parameter_modifier type IDENTIFIER COMMA + opt_attributes opt_parameter_modifier type IDENTIFIER CLOSE_PARENS { // TODO: wrong location - if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE || (Parameter.Modifier)$9 != Parameter.Modifier.NONE) + if ((Parameter.Modifier)$6 != Parameter.Modifier.NONE || (Parameter.Modifier)$11 != Parameter.Modifier.NONE) Error_ParameterModifierNotValid ((Location) $2); - LocatedToken ltParam1 = (LocatedToken) $7; - LocatedToken ltParam2 = (LocatedToken) $11; + LocatedToken ltParam1 = (LocatedToken) $8; + LocatedToken ltParam2 = (LocatedToken) $13; CheckBinaryOperator ((Operator.OpType) $3, (Location) $2); Parameter [] pars = new Parameter [2]; - Expression typeL = (Expression) $6; - Expression typeR = (Expression) $10; + Expression typeL = (Expression) $7; + Expression typeR = (Expression) $12; - pars [0] = new Parameter (typeL, ltParam1.Value, Parameter.Modifier.NONE, null, ltParam1.Location); - pars [1] = new Parameter (typeR, ltParam2.Value, Parameter.Modifier.NONE, null, ltParam2.Location); + pars [0] = new Parameter (typeL, ltParam1.Value, Parameter.Modifier.NONE, (Attributes) $5, ltParam1.Location); + pars [1] = new Parameter (typeR, ltParam2.Value, Parameter.Modifier.NONE, (Attributes) $10, ltParam2.Location); current_local_parameters = new Parameters (pars); @@ -2083,18 +2158,16 @@ operator_declarator } | conversion_operator_declarator | type OPERATOR overloadable_operator - OPEN_PARENS - opt_parameter_modifier type IDENTIFIER COMMA - opt_parameter_modifier type IDENTIFIER COMMA - opt_parameter_modifier type IDENTIFIER - CLOSE_PARENS + open_parens + opt_attributes opt_parameter_modifier type IDENTIFIER COMMA + opt_attributes opt_parameter_modifier type IDENTIFIER COMMA error { Report.Error (1534, (Location) $2, "Overloaded binary operator `{0}' takes two parameters", Operator.GetName ((Operator.OpType) $3)); $$ = null; } | type OPERATOR overloadable_operator - OPEN_PARENS CLOSE_PARENS + open_parens CLOSE_PARENS { Report.Error (1535, (Location) $2, "Overloaded unary operator `{0}' takes one parameter", Operator.GetName ((Operator.OpType) $3)); @@ -2131,7 +2204,7 @@ overloadable_operator ; conversion_operator_declarator - : IMPLICIT OPERATOR type OPEN_PARENS opt_parameter_modifier type IDENTIFIER CLOSE_PARENS + : IMPLICIT OPERATOR type open_parens opt_parameter_modifier type IDENTIFIER CLOSE_PARENS { // TODO: wrong location if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE) @@ -2152,7 +2225,7 @@ conversion_operator_declarator $$ = new OperatorDeclaration (Operator.OpType.Implicit, (Expression) $3, (Expression) $6, lt.Value, null, null, (Location) $2); } - | EXPLICIT OPERATOR type OPEN_PARENS opt_parameter_modifier type IDENTIFIER CLOSE_PARENS + | EXPLICIT OPERATOR type open_parens opt_parameter_modifier type IDENTIFIER CLOSE_PARENS { // TODO: wrong location if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE) @@ -2229,6 +2302,18 @@ constructor_declaration ; constructor_declarator + : constructor_header + { + $$ = $1; + } + | constructor_header constructor_initializer + { + ((Constructor)$1).Initializer = (ConstructorInitializer) $2; + $$ = $1; + } + ; + +constructor_header : IDENTIFIER { if (RootContext.Documentation != null) { @@ -2236,36 +2321,30 @@ constructor_declarator Lexer.doc_state = XmlCommentState.Allowed; } } - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS - { - current_local_parameters = (Parameters) $4; - } - opt_constructor_initializer + open_parens opt_formal_parameter_list CLOSE_PARENS { LocatedToken lt = (LocatedToken) $1; - $$ = new Constructor (current_class, lt.Value, 0, (Parameters) $4, - (ConstructorInitializer) $7, lt.Location); + current_local_parameters = (Parameters) $4; + current_block = new ToplevelBlock (null, current_local_parameters, null, lt.Location); + + $$ = new Constructor (current_class, lt.Value, 0, current_local_parameters, + null, lt.Location); anonymous_host = (IAnonymousHost) $$; } ; constructor_body - : block - | SEMICOLON { $$ = null; } - ; - -opt_constructor_initializer - : /* empty */ { $$ = null; } - | constructor_initializer + : block_prepared + | SEMICOLON { current_block = null; $$ = null; } ; constructor_initializer - : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS + : COLON BASE open_parens opt_argument_list CLOSE_PARENS { $$ = new ConstructorBaseInitializer ((ArrayList) $4, (Location) $2); } - | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS + | COLON THIS open_parens opt_argument_list CLOSE_PARENS { $$ = new ConstructorThisInitializer ((ArrayList) $4, (Location) $2); } @@ -2431,11 +2510,19 @@ add_accessor_declaration current_local_parameters = new Parameters (args); lexer.EventParsing = false; + + anonymous_host = SimpleAnonymousHost.GetSimple (); } block { - $$ = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, (Location) $2); + Accessor accessor = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, (Location) $2); lexer.EventParsing = true; + + current_local_parameters = null; + SimpleAnonymousHost.Simple.Propagate (accessor); + anonymous_host = null; + + $$ = accessor; } | opt_attributes ADD error { Report.Error (73, (Location) $2, "An add or remove accessor must have a body"); @@ -2592,8 +2679,9 @@ enum_declaration EnumMember em = null; foreach (VariableDeclaration ev in (ArrayList) $7) { - em = new EnumMember (e, em, (Expression) ev.expression_or_array_initializer, - new MemberName (ev.identifier, ev.Location), ev.OptAttributes); + em = new EnumMember ( + e, em, ev.identifier, (Expression) ev.expression_or_array_initializer, + ev.OptAttributes, ev.Location); // if (RootContext.Documentation != null) em.DocComment = ev.DocComment; @@ -2601,7 +2689,7 @@ enum_declaration e.AddEnumMember (em); } - current_container.AddEnum (e); + current_container.AddTypeContainer (e); $$ = e; } @@ -2693,7 +2781,7 @@ delegate_declaration lexer.ConstraintsParsing = true; } type member_name - OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + open_parens opt_formal_parameter_list CLOSE_PARENS { MemberName name = MakeName ((MemberName) $6); Parameters p = (Parameters) $8; @@ -2825,6 +2913,10 @@ type } | array_type | pointer_type + | VAR + { + $$ = new VarExpr (lexer.Location); + } ; pointer_type @@ -3089,6 +3181,111 @@ invocation_expression } ; +opt_object_initializer + : /* empty */ { $$ = null; } + | OPEN_BRACE variable_declarators CLOSE_BRACE + { + ArrayList vars = (ArrayList) $2; + ArrayList inits = new ArrayList (vars.Count); + foreach (VariableDeclaration variable in vars) { + Initializer i = new Initializer (variable.identifier, variable.expression_or_array_initializer); + inits.Add (i); + } + $$ = inits; + } + ; + +opt_object_or_collection_initializer + : /* empty */ { $$ = null; } + | object_or_collection_initializer + ; + +object_or_collection_initializer + : object_initializer + | collection_initializer + ; + +object_initializer + : OPEN_BRACE opt_member_initializer_list CLOSE_BRACE + { + if ($2 == null) + $$ = null; + else + $$ = new ObjectInitializer ((ArrayList)$2); + } + | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE + { + $$ = new ObjectInitializer ((ArrayList) $2); + } + ; + +opt_member_initializer_list + : /* empty */ { $$ = null; } + | member_initializer_list + ; + +member_initializer_list + : member_initializer + { + ArrayList a = new ArrayList (); + a.Add ($1); + $$ = a; + } + | member_initializer_list COMMA member_initializer + { + ArrayList a = (ArrayList)$1; + a.Add ($3); + $$ = a; + } + ; + +member_initializer + : IDENTIFIER ASSIGN initializer_value + { + LocatedToken id = $1 as LocatedToken; + IInitializable i = $3 as IInitializable; + if (i != null) + $$ = new Initializer (id.Value, i); + else + $$ = new Initializer (id.Value, (Expression)$3); + } + ; + +initializer_value + : expression + | object_or_collection_initializer + ; + +collection_initializer + : OPEN_BRACE element_initializer_list CLOSE_BRACE + { + $$ = new CollectionInitializer ((ArrayList) $2); + } + | OPEN_BRACE element_initializer_list COMMA CLOSE_BRACE + { + $$ = new CollectionInitializer ((ArrayList) $2); + } + ; + +element_initializer_list + : element_initializer + { + ArrayList a = new ArrayList (); + a.Add ($1); + $$ = a; + } + | element_initializer_list COMMA element_initializer + { + ArrayList a = $1 as ArrayList; + a.Add ($3); + $$ = a; + } + ; + +element_initializer + : non_assignment_expression + ; + opt_argument_list : /* empty */ { $$ = null; } | argument_list @@ -3142,6 +3339,10 @@ non_simple_argument Expression expr = new Arglist (args, (Location) $1); $$ = new Argument (expr, Argument.AType.Expression); } + | ARGLIST OPEN_PARENS CLOSE_PARENS + { + $$ = new Argument (new Arglist ((Location) $1), Argument.AType.Expression); + } | ARGLIST { $$ = new Argument (new ArglistAccess ((Location) $1), Argument.AType.ArgList); @@ -3240,12 +3441,31 @@ post_decrement_expression new_expression : object_or_delegate_creation_expression | array_creation_expression + | anonymous_type_expression ; object_or_delegate_creation_expression - : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS + : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer + { + if ($6 != null) { + if (RootContext.Version < LanguageVersion.LINQ) { + Error_ExpectingTypeName ((Expression) $2); + $$ = null; + } + else + $$ = new NewInitialize ((Expression) $2, (ArrayList) $4, (IInitializable) $6, (Location) $1); + } + else + $$ = new New ((Expression) $2, (ArrayList) $4, (Location) $1); + } + | NEW type object_or_collection_initializer { - $$ = new New ((Expression) $2, (ArrayList) $4, (Location) $1); + if (RootContext.Version < LanguageVersion.LINQ) { + Report.Error (1526, (Location) $1, "A new expression requires () or [] after type"); + $$ = null; + } + else + $$ = new NewInitialize ((Expression) $2, new ArrayList (), (IInitializable) $3, (Location) $1); } ; @@ -3260,6 +3480,15 @@ array_creation_expression { $$ = new ArrayCreation ((Expression) $2, (string) $3, (ArrayList) $4, (Location) $1); } + | NEW rank_specifiers array_initializer + { + if (RootContext.Version < LanguageVersion.LINQ) { + Report.Error (1031, (Location) $1, "Type expected"); + $$ = null; + } + else + $$ = new ArrayCreation (new VarExpr((Location) $1), (string) $2, (ArrayList) $3, (Location) $1); + } | NEW error { Report.Error (1031, (Location) $1, "Type expected"); @@ -3272,6 +3501,50 @@ array_creation_expression } ; +anonymous_type_expression + : NEW OPEN_BRACE anonymous_type_parameters CLOSE_BRACE + { + if (RootContext.Version < LanguageVersion.LINQ) { + Report.Error (1031, (Location) $1, "Type expected"); + $$ = null; + } + else + $$ = new AnonymousType ((ArrayList) $3, current_container, lexer.Location); + } + ; + +anonymous_type_parameters + : anonymous_type_parameter + { + ArrayList a = new ArrayList (4); + a.Add ($1); + $$ = a; + } + | anonymous_type_parameters COMMA anonymous_type_parameter + { + ArrayList a = (ArrayList) $1; + a.Add ($3); + $$ = a; + } + ; + +anonymous_type_parameter + : variable_declarator + { + VariableDeclaration v = (VariableDeclaration) $1; + Expression e = v.expression_or_array_initializer; + if (e == null) { + e = new LocalVariableReference (current_block, v.identifier, lexer.Location); + } + $$ = new AnonymousTypeParameter (e, v.identifier); + } + | member_access + { + MemberAccess ma = (MemberAccess) $1; + $$ = new AnonymousTypeParameter (ma, ma.Identifier); + } + ; + opt_rank_specifier : /* empty */ { @@ -3434,47 +3707,11 @@ pointer_member_access anonymous_method_expression : DELEGATE opt_anonymous_method_signature { - if (oob_stack == null) - oob_stack = new Stack (6); - - oob_stack.Push (current_anonymous_method); - oob_stack.Push (current_local_parameters); - current_local_parameters = (Parameters)$2; - - // Force the next block to be created as a ToplevelBlock - oob_stack.Push (current_block); - oob_stack.Push (top_current_block); - - Location loc = (Location) $1; - current_anonymous_method = new AnonymousMethodExpression ( - current_anonymous_method, current_generic_method, current_container, - (Parameters) $2, (ToplevelBlock) top_current_block, loc); - - parsing_anonymous_method = true; + start_anonymous (false, (Parameters) $2, (Location) $1); } block { - Location loc = (Location) $1; - top_current_block = (Block) oob_stack.Pop (); - current_block = (Block) oob_stack.Pop (); - - if (RootContext.Version == LanguageVersion.ISO_1){ - Report.FeatureIsNotISO1 (loc, "anonymous methods"); - $$ = null; - } else { - ToplevelBlock anon_block = (ToplevelBlock) $4; - - anon_block.Parent = current_block; - - current_anonymous_method.Block = anon_block; - if ((anonymous_host != null) && (current_anonymous_method.Parent == null)) - anonymous_host.AddAnonymousMethod (current_anonymous_method); - - $$ = current_anonymous_method; - } - - current_local_parameters = (Parameters) oob_stack.Pop (); - current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); + $$ = end_anonymous ((ToplevelBlock) $4, (Location) $1); } ; @@ -3484,7 +3721,7 @@ opt_anonymous_method_signature ; anonymous_method_signature - : OPEN_PARENS opt_anonymous_method_parameter_list CLOSE_PARENS + : open_parens opt_anonymous_method_parameter_list CLOSE_PARENS { if ($2 == null) $$ = Parameters.EmptyReadOnlyParameters; @@ -3498,7 +3735,7 @@ anonymous_method_signature ; opt_anonymous_method_parameter_list - : /* empty */ { $$ = null; } + : /* empty */ { $$ = null; } | anonymous_method_parameter_list { $$ = $1; } ; @@ -3794,9 +4031,9 @@ conditional_expression { $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5); } - | conditional_or_expression INTERR INTERR expression + | conditional_or_expression OP_COALESCING expression { - $$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $4, lexer.Location); + $$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3, lexer.Location); } // We'll be resolved into a `parenthesized_expression_0' later on. | conditional_or_expression INTERR CLOSE_PARENS @@ -3865,13 +4102,16 @@ assignment_expression implicitly_typed_lambda_parameter_list : IDENTIFIER { + LocatedToken lt = (LocatedToken) $1; ArrayList a = new ArrayList (4); - a.Add ($1); - $$ = a; + + a.Add (new Parameter ((Expression)null, lt.Value, Parameter.Modifier.NONE, null, lt.Location)); + $$ = a; } | implicitly_typed_lambda_parameter_list COMMA IDENTIFIER { + LocatedToken lt = (LocatedToken) $3; ArrayList a = (ArrayList) $1; - a.Add ($3); + a.Add (new Parameter ((Expression)null, lt.Value, Parameter.Modifier.NONE, null, lt.Location)); $$ = a; } ; @@ -3902,9 +4142,9 @@ explicitly_typed_lambda_parameter } | type IDENTIFIER { - LocatedToken lt = (LocatedToken) $3; + LocatedToken lt = (LocatedToken) $2; - $$ = new Parameter ((Expression) $2, lt.Value, Parameter.Modifier.NONE, null, lt.Location); + $$ = new Parameter ((Expression) $1, lt.Value, Parameter.Modifier.NONE, null, lt.Location); } ; @@ -3913,34 +4153,66 @@ lambda_parameter_list | explicitly_typed_lambda_parameter_list { $$ = $1; } ; +opt_lambda_parameter_list + : /* empty */ { $$ = null; } + | lambda_parameter_list { + ArrayList pars_list = (ArrayList) $1; + + Parameter [] pars = new Parameter [pars_list.Count]; + pars_list.CopyTo (pars); + $$ = new Parameters (pars); + } + ; + lambda_expression_body - : expression - | block + : { + start_block (lexer.Location); + } + expression + { + Block b = end_block (lexer.Location); + b.AddStatement (new ContextualReturn ((Expression) $2)); + $$ = b; + } + | block { + $$ = $1; + } ; lambda_expression - : IDENTIFIER ARROW lambda_expression_body + : IDENTIFIER ARROW { - LocatedToken lt = (LocatedToken) $2; - ArrayList a = new ArrayList (1); - a.Add ($1); - $$ = new LambdaExpression (a, $3, lt.Location); + Parameter [] pars = new Parameter [1]; + LocatedToken lt = (LocatedToken) $1; + pars [0] = new Parameter ((Expression)null, lt.Value, Parameter.Modifier.NONE, null, lt.Location); + + Parameters parameters = new Parameters (pars); + + start_anonymous (true, parameters, (Location) $2); } - | OPEN_PARENS CLOSE_PARENS ARROW lambda_expression_body { - LocatedToken lt = (LocatedToken) $3; - $$ = new LambdaExpression (new ArrayList (), $3, lt.Location); + lambda_expression_body + { + $$ = end_anonymous ((ToplevelBlock) $4, (Location) $2); } - | OPEN_PARENS_LAMBDA lambda_parameter_list CLOSE_PARENS ARROW lambda_expression_body + | OPEN_PARENS_LAMBDA opt_lambda_parameter_list CLOSE_PARENS ARROW { - LocatedToken lt = (LocatedToken) $4; - $$ = new LambdaExpression ((ArrayList) $2, $5, lt.Location); + start_anonymous (true, (Parameters) $2, (Location) $4); + } + lambda_expression_body + { + $$ = end_anonymous ((ToplevelBlock) $6, (Location) $4); } ; expression + : assignment_expression + | non_assignment_expression + ; + +non_assignment_expression : conditional_expression - | assignment_expression | lambda_expression + | query_expression ; constant_expression @@ -3969,7 +4241,7 @@ class_declaration push_current_class (new Class ( current_namespace, current_class, name, - mod_flags, (Attributes) $1), false, $3); + mod_flags, (Attributes) $1), $3); } opt_class_base opt_type_parameter_constraints_clauses @@ -4132,34 +4404,21 @@ type_parameter_constraint // event_declaration as part of add_accessor_declaration or remove_accessor_declaration // block - : OPEN_BRACE + : OPEN_BRACE { - if (parsing_anonymous_method) { - top_current_block = new ToplevelBlock ( - current_block, current_local_parameters, current_generic_method, - (Location) $1); - if (current_block != null) - current_block.AddAnonymousChild ((ToplevelBlock) top_current_block); - current_block = top_current_block; - parsing_anonymous_method = false; - } else if (current_block == null) { - current_block = new ToplevelBlock ( - (ToplevelBlock) top_current_block, current_local_parameters, - current_generic_method, (Location) $1); - top_current_block = current_block; - } else { - current_block = new Block (current_block, (Location) $1, Location.Null); - } + start_block ((Location) $1); } opt_statement_list CLOSE_BRACE { - while (current_block.Implicit) - current_block = current_block.Parent; - $$ = current_block; - current_block.SetEndLocation ((Location) $4); - current_block = current_block.Parent; - if (current_block == null) - top_current_block = null; + $$ = end_block ((Location) $4); + } + ; + +block_prepared + : OPEN_BRACE + opt_statement_list CLOSE_BRACE + { + $$ = end_block ((Location) $3); } ; @@ -4344,6 +4603,10 @@ local_variable_declaration else $$ = null; } + | VAR variable_declarators + { + $$ = new DictionaryEntry (new VarExpr (lexer.Location), $2); + } | local_variable_pointer_type opt_rank_specifier_or_nullable variable_declarators { if ($1 != null){ @@ -4490,11 +4753,7 @@ switch_section } statement_list { - Block topmost = current_block; - - while (topmost.Implicit) - topmost = topmost.Parent; - $$ = new SwitchSection ((ArrayList) $1, topmost); + $$ = new SwitchSection ((ArrayList) $1, current_block.Explicit); } ; @@ -4551,11 +4810,12 @@ do_statement ; for_statement - : FOR OPEN_PARENS + : FOR open_parens opt_for_initializer SEMICOLON { - Block assign_block = new Block (current_block); - current_block = assign_block; + Location l = lexer.Location; + start_block (l); + Block assign_block = current_block; if ($3 is DictionaryEntry){ DictionaryEntry de = (DictionaryEntry) $3; @@ -4571,7 +4831,6 @@ for_statement if (vi == null) continue; - Location l = lexer.Location; Expression expr = decl.expression_or_array_initializer; LocalVariableReference var; @@ -4600,10 +4859,8 @@ for_statement For f = new For ((Statement) $5, (Expression) $6, (Statement) $8, (Statement) $10, l); current_block.AddStatement (f); - while (current_block.Implicit) - current_block = current_block.Parent; - $$ = current_block; - current_block = current_block.Parent; + + $$ = end_block (lexer.Location); } ; @@ -4636,7 +4893,7 @@ statement_expression_list { // CHANGE: was `null' Statement s = (Statement) $1; - Block b = new Block (current_block, Block.Flags.Implicit, s.loc, lexer.Location); + Block b = new Block (current_block, s.loc, lexer.Location); b.AddStatement (s); $$ = b; @@ -4651,16 +4908,16 @@ statement_expression_list ; foreach_statement - : FOREACH OPEN_PARENS type IN expression CLOSE_PARENS + : FOREACH open_parens type IN expression CLOSE_PARENS { Report.Error (230, (Location) $1, "Type and identifier are both required in a foreach statement"); $$ = null; } - | FOREACH OPEN_PARENS type IDENTIFIER IN + | FOREACH open_parens type IDENTIFIER IN expression CLOSE_PARENS { - Block foreach_block = new Block (current_block); - current_block = foreach_block; + start_block (lexer.Location); + Block foreach_block = current_block; LocatedToken lt = (LocatedToken) $4; Location l = lt.Location; @@ -4689,10 +4946,7 @@ foreach_statement current_block.AddStatement (f); } - while (current_block.Implicit) - current_block = current_block.Parent; - $$ = current_block; - current_block = current_block.Parent; + $$ = end_block (lexer.Location); } ; @@ -4890,9 +5144,8 @@ catch_clause one.Add (new VariableDeclaration (lt, null)); - current_block = new Block (current_block); - Block b = declare_local_variables (type, one, lt.Location); - current_block = b; + start_block (lexer.Location); + current_block = declare_local_variables (type, one, lt.Location); } } } block { @@ -4907,10 +5160,7 @@ catch_clause if (lt != null){ id = lt.Value; - while (current_block.Implicit) - current_block = current_block.Parent; - var_block = current_block; - current_block = current_block.Parent; + var_block = end_block (lexer.Location); } } @@ -4924,7 +5174,7 @@ opt_catch_args ; catch_args - : OPEN_PARENS type opt_identifier CLOSE_PARENS + : open_parens type opt_identifier CLOSE_PARENS { $$ = new DictionaryEntry ($2, $3); } @@ -4955,7 +5205,7 @@ unsafe_statement ; fixed_statement - : FIXED OPEN_PARENS + : FIXED open_parens type fixed_pointer_declarators CLOSE_PARENS { @@ -4964,8 +5214,8 @@ fixed_statement Location l = (Location) $1; int top = list.Count; - Block assign_block = new Block (current_block); - current_block = assign_block; + start_block (lexer.Location); + Block assign_block = current_block; for (int i = 0; i < top; i++){ Pair p = (Pair) list [i]; @@ -4975,6 +5225,9 @@ fixed_statement if (v == null) continue; + if (type is VarExpr) + v.VariableType = typeof(VarExpr); // Kinda lame. Avoids a problem in the VariableMap ctor + v.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Fixed); v.Pinned = true; p.First = v; @@ -4988,10 +5241,8 @@ fixed_statement Fixed f = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l); current_block.AddStatement (f); - while (current_block.Implicit) - current_block = current_block.Parent; - $$ = current_block; - current_block = current_block.Parent; + + $$ = end_block (lexer.Location); } ; @@ -5037,10 +5288,10 @@ lock_statement ; using_statement - : USING OPEN_PARENS resource_acquisition CLOSE_PARENS + : USING open_parens resource_acquisition CLOSE_PARENS { - Block assign_block = new Block (current_block); - current_block = assign_block; + start_block (lexer.Location); + Block assign_block = current_block; if ($3 is DictionaryEntry){ DictionaryEntry de = (DictionaryEntry) $3; @@ -5088,10 +5339,7 @@ using_statement { Using u = new Using ($5, (Statement) $6, (Location) $1); current_block.AddStatement (u); - while (current_block.Implicit) - current_block = current_block.Parent; - $$ = current_block; - current_block = current_block.Parent; + $$ = end_block (lexer.Location); } ; @@ -5100,6 +5348,138 @@ resource_acquisition | expression ; + +// LINQ + +query_expression + : from_clause query_body + { + lexer.QueryParsing = false; + $$ = new Linq.QueryExpression (current_container, current_block, (Expression)$1, (Linq.AQueryClause)$2); + end_block (lexer.Location); + } + ; + +from_clause + : FROM IDENTIFIER IN expression opt_join_clauses + { + start_block (lexer.Location); + LocatedToken lt = (LocatedToken) $2; + + LocalInfo vi = current_block.AddVariable (TypeManager.system_object_expr, lt.Value, lt.Location); // TODO: null is var type + if (vi != null) { + $$ = new LocalVariableReference (current_block, lt.Value, lt.Location, vi, false); + } + $$ = $4; + } + | FROM type IDENTIFIER IN expression opt_join_clauses + { + start_block (lexer.Location); + LocatedToken lt = (LocatedToken) $3; + + Expression type = (Expression)$2; + LocalInfo vi = current_block.AddVariable (type, lt.Value, lt.Location); + $$ = new Linq.Cast (type, (Expression)$5, lt.Location); + } + ; + +opt_join_clauses + : /* empty */ + | join_clauses + ; + +join_clauses + : join_clause + | join_clauses join_clause + ; + +join_clause + : JOIN join_clause_body + | JOIN join_clause_body INTO IDENTIFIER + | JOIN type join_clause_body + | JOIN type join_clause_body INTO IDENTIFIER + ; + +join_clause_body + : IDENTIFIER IN expression ON expression EQUALS expression + ; + +query_body + : opt_from_let_where_clauses opt_orderby_clause SELECT expression opt_query_continuation + { + Linq.AQueryClause ret = new Linq.Select ((Expression)$4, GetLocation ($3)); + + if ($1 != null) { + ((Linq.AQueryClause)$1).Next = ret; + ret = (Linq.AQueryClause)$1; + } + + $$ = ret; + } + | opt_from_let_where_clauses opt_orderby_clause group_clause opt_query_continuation + ; + +opt_from_let_where_clauses + : /* empty */ + | from_let_where_clauses + ; + +from_let_where_clauses + : from_let_where_clause + | from_let_where_clauses from_let_where_clause + ; + +from_let_where_clause + : from_clause + | let_clause + | where_clause + ; + +let_clause + : LET IDENTIFIER ASSIGN expression + ; + +where_clause + : WHERE boolean_expression + { + $$ = new Linq.Where ((Expression)$2, GetLocation ($1)); + } + ; + +opt_orderby_clause + : /* empty */ + | orderby_clause + ; + +orderby_clause + : ORDERBY orderings + ; + +orderings + : ordering + | orderings COMMA ordering + ; + +ordering + : expression + | expression ASCENDING + | expression DESCENDING + ; + + +group_clause + : GROUP expression BY expression + ; + +opt_query_continuation + : /* empty */ + | query_continuation + ; + +query_continuation + : INTO IDENTIFIER opt_join_clauses query_body + ; + %% // @@ -5227,12 +5607,18 @@ public static void Error_ParameterModifierNotValid (Location loc) Report.Error (631, loc, "The modifiers `ref' and `out' are not valid in this context"); } -void push_current_class (TypeContainer tc, bool is_interface, object partial_token) +static void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod) +{ + Report.Error (1107, loc, "Duplicate parameter modifier `{0}'", + Parameter.GetModifierSignature (mod)); +} + +void push_current_class (TypeContainer tc, object partial_token) { if (partial_token != null) - current_container = current_container.AddPartial (tc, is_interface); + current_container = current_container.AddPartial (tc); else - current_container = current_container.AddTypeContainer (tc, is_interface); + current_container = current_container.AddTypeContainer (tc); current_class = tc; } @@ -5286,7 +5672,7 @@ Block declare_local_variables (Expression type, ArrayList variable_declarators, // int j = 1; int k = j + 1; // if (current_block.Used) - implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null); + implicit_block = new Block (current_block, loc, Location.Null); else implicit_block = current_block; @@ -5324,7 +5710,7 @@ Block declare_local_constants (Expression type, ArrayList declarators) Block implicit_block; if (current_block.Used) - implicit_block = new Block (current_block, Block.Flags.Implicit); + implicit_block = new Block (current_block); else implicit_block = current_block; @@ -5335,18 +5721,16 @@ Block declare_local_constants (Expression type, ArrayList declarators) return implicit_block; } -void CheckAttributeTarget (string a, Location l) +string CheckAttributeTarget (string a, Location l) { switch (a) { - case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" : - return; - - default : - Report.Error (658, l, "`" + a + "' is an invalid attribute target"); - break; + return a; } + Report.Warning (658, 1, l, + "`{0}' is invalid attribute target. All attributes in this attribute section will be ignored", a); + return string.Empty; } void CheckUnaryOperator (Operator.OpType op, Location l) @@ -5418,6 +5802,11 @@ public Tokenizer Lexer { } } +static CSharpParser () +{ + oob_stack = new Stack (); +} + public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines) { this.name = file.Name; @@ -5425,7 +5814,7 @@ public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList def current_namespace = new NamespaceEntry (null, file, null); current_class = current_namespace.SlaveDeclSpace; current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes - + oob_stack.Clear (); lexer = new Tokenizer (reader, file, defines); } @@ -5488,5 +5877,73 @@ Location GetLocation (object obj) return lexer.Location; } +void +start_block (Location loc) +{ + if (current_block == null || parsing_anonymous_method) { + current_block = new ToplevelBlock (current_block, current_local_parameters, current_generic_method, loc); + parsing_anonymous_method = false; + } else { + current_block = new ExplicitBlock (current_block, loc, Location.Null); + } +} + +Block +end_block (Location loc) +{ + Block retval = current_block.Explicit; + retval.SetEndLocation (loc); + current_block = retval.Parent; + return retval; +} + +void +start_anonymous (bool lambda, Parameters parameters, Location loc) +{ + oob_stack.Push (current_anonymous_method); + oob_stack.Push (current_local_parameters); + + current_local_parameters = parameters; + + ToplevelBlock top_current_block = current_block == null ? null : current_block.Toplevel; + + current_anonymous_method = lambda + ? new LambdaExpression ( + current_anonymous_method, current_generic_method, current_container, + parameters, top_current_block, loc) + : new AnonymousMethodExpression ( + current_anonymous_method, current_generic_method, current_container, + parameters, top_current_block, loc); + + // Force the next block to be created as a ToplevelBlock + parsing_anonymous_method = true; +} + +/* + * Completes the anonymous method processing, if lambda_expr is null, this + * means that we have a Statement instead of an Expression embedded + */ +AnonymousMethodExpression +end_anonymous (ToplevelBlock anon_block, Location loc) +{ + AnonymousMethodExpression retval; + + if (RootContext.Version == LanguageVersion.ISO_1){ + Report.FeatureIsNotISO1 (loc, "anonymous methods"); + retval = null; + } else { + current_anonymous_method.Block = anon_block; + if ((anonymous_host != null) && (current_anonymous_method.Parent == null)) + anonymous_host.AddAnonymousMethod (current_anonymous_method); + + retval = current_anonymous_method; + } + + current_local_parameters = (Parameters) oob_stack.Pop (); + current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); + + return retval; +} + /* end end end */ }