mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7474 lines
192 KiB
7474 lines
192 KiB
%{ |
|
// |
|
// cs-parser.jay: The Parser for the C# compiler |
|
// |
|
// Authors: Miguel de Icaza (miguel@gnome.org) |
|
// Ravi Pratap (ravi@ximian.com) |
|
// Marek Safar (marek.safar@gmail.com) |
|
// |
|
// Dual Licensed under the terms of the GNU GPL and the MIT X11 license |
|
// |
|
// (C) 2001 Ximian, Inc (http://www.ximian.com) |
|
// (C) 2004-2011 Novell, Inc |
|
// Copyright 2011-2012 Xamarin Inc. |
|
// |
|
|
|
using System.Text; |
|
using System.IO; |
|
using System; |
|
using System.Collections.Generic; |
|
|
|
namespace Mono.CSharp |
|
{ |
|
/// <summary> |
|
/// The C# Parser |
|
/// </summary> |
|
public class CSharpParser |
|
{ |
|
[Flags] |
|
enum ParameterModifierType |
|
{ |
|
Ref = 1 << 1, |
|
Out = 1 << 2, |
|
This = 1 << 3, |
|
Params = 1 << 4, |
|
Arglist = 1 << 5, |
|
DefaultValue = 1 << 6, |
|
|
|
All = Ref | Out | This | Params | Arglist | DefaultValue |
|
} |
|
|
|
static readonly object ModifierNone = 0; |
|
|
|
NamespaceContainer current_namespace; |
|
TypeContainer current_container; |
|
TypeDefinition current_type; |
|
PropertyBase current_property; |
|
EventProperty current_event; |
|
EventField current_event_field; |
|
FieldBase current_field; |
|
|
|
/// <summary> |
|
/// Current block is used to add statements as we find |
|
/// them. |
|
/// </summary> |
|
Block current_block; |
|
|
|
BlockVariableDeclaration current_variable; |
|
|
|
Delegate current_delegate; |
|
|
|
AnonymousMethodExpression current_anonymous_method; |
|
|
|
/// <summary> |
|
/// This is used by the unary_expression code to resolve |
|
/// a name against a parameter. |
|
/// </summary> |
|
|
|
// FIXME: This is very ugly and it's very hard to reset it correctly |
|
// on all places, especially when some parameters are autogenerated. |
|
ParametersCompiled current_local_parameters; |
|
|
|
bool parsing_anonymous_method; |
|
|
|
bool async_block; |
|
|
|
/// |
|
/// An out-of-band stack. |
|
/// |
|
Stack<object> oob_stack; |
|
|
|
/// |
|
/// Controls the verbosity of the errors produced by the parser |
|
/// |
|
int yacc_verbose_flag; |
|
|
|
/// |
|
/// Used by the interactive shell, flags whether EOF was reached |
|
/// and an error was produced |
|
/// |
|
public bool UnexpectedEOF; |
|
|
|
/// |
|
/// The current file. |
|
/// |
|
readonly CompilationSourceFile file; |
|
|
|
/// |
|
/// Temporary Xml documentation cache. |
|
/// For enum types, we need one more temporary store. |
|
/// |
|
string tmpComment; |
|
string enumTypeComment; |
|
|
|
/// Current attribute target |
|
string current_attr_target; |
|
|
|
ParameterModifierType valid_param_mod; |
|
|
|
bool default_parameter_used; |
|
|
|
/// When using the interactive parser, this holds the |
|
/// resulting expression |
|
public Class InteractiveResult; |
|
|
|
// |
|
// Keeps track of global data changes to undo on parser error |
|
// |
|
public Undo undo; |
|
|
|
Stack<Linq.QueryBlock> linq_clause_blocks; |
|
|
|
ModuleContainer module; |
|
|
|
readonly CompilerContext compiler; |
|
readonly LanguageVersion lang_version; |
|
readonly bool doc_support; |
|
readonly CompilerSettings settings; |
|
readonly Report report; |
|
|
|
// |
|
// Instead of allocating carrier array everytime we |
|
// share the bucket for very common constructs which can never |
|
// be recursive |
|
// |
|
List<Parameter> parameters_bucket; |
|
|
|
// |
|
// Full AST support members |
|
// |
|
LocationsBag lbag; |
|
List<Tuple<Modifiers, Location>> mod_locations; |
|
Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation; |
|
Location savedAttrParenOpenLocation, savedAttrParenCloseLocation, savedOperatorLocation; |
|
Stack<List<Location>> locationListStack = new Stack<List<Location>> (); // used for type parameters |
|
Stack<Location> opt_intoStack = new Stack<Location> (); |
|
|
|
bool HadAttributeParens; |
|
List<Location> attributeCommas = new List<Location> (); |
|
List<Location> attributeArgumentCommas = new List<Location> (); |
|
List<Location> parameterListCommas = new List<Location> (); |
|
%} |
|
|
|
%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 FIRST_KEYWORD |
|
%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 STACKALLOC |
|
%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 VOLATILE |
|
%token WHERE |
|
%token WHILE |
|
%token ARGLIST |
|
%token PARTIAL |
|
%token ARROW |
|
%token FROM |
|
%token FROM_FIRST |
|
%token JOIN |
|
%token ON |
|
%token EQUALS |
|
%token SELECT |
|
%token GROUP |
|
%token BY |
|
%token LET |
|
%token ORDERBY |
|
%token ASCENDING |
|
%token DESCENDING |
|
%token INTO |
|
%token INTERR_NULLABLE |
|
%token EXTERN_ALIAS |
|
%token REFVALUE |
|
%token REFTYPE |
|
%token MAKEREF |
|
%token ASYNC |
|
%token AWAIT |
|
|
|
/* C# keywords which are not really keywords */ |
|
%token GET |
|
%token SET |
|
|
|
%left LAST_KEYWORD |
|
|
|
/* 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 DOUBLE_COLON |
|
%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 |
|
%token OP_COALESCING |
|
|
|
/* Generics <,> tokens */ |
|
%token OP_GENERICS_LT |
|
%token OP_GENERICS_LT_DECL |
|
%token OP_GENERICS_GT |
|
|
|
%token LITERAL |
|
|
|
%token IDENTIFIER |
|
%token OPEN_PARENS_LAMBDA |
|
%token OPEN_PARENS_CAST |
|
%token GENERIC_DIMENSION |
|
%token DEFAULT_COLON |
|
%token OPEN_BRACKET_EXPR |
|
|
|
// Make the parser go into eval mode parsing (statements and compilation units). |
|
%token EVAL_STATEMENT_PARSER |
|
%token EVAL_COMPILATION_UNIT_PARSER |
|
%token EVAL_USING_DECLARATIONS_UNIT_PARSER |
|
|
|
%token DOC_SEE |
|
|
|
// |
|
// This token is generated to trigger the completion engine at this point |
|
// |
|
%token GENERATE_COMPLETION |
|
|
|
// |
|
// This token is return repeatedly after the first GENERATE_COMPLETION |
|
// token is produced and before the final EOF |
|
// |
|
%token COMPLETE_COMPLETION |
|
|
|
/* Add precedence rules to solve dangling else s/r conflict */ |
|
%nonassoc IF |
|
%nonassoc ELSE |
|
|
|
/* Define the operator tokens and their precedences */ |
|
%right ASSIGN |
|
%right OP_COALESCING |
|
%right INTERR |
|
%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 |
|
|
|
%start compilation_unit |
|
%% |
|
|
|
compilation_unit |
|
: outer_declaration opt_EOF |
|
{ |
|
Lexer.check_incorrect_doc_comment (); |
|
} |
|
| interactive_parsing { Lexer.CompleteOnEOF = false; } opt_EOF |
|
| documentation_parsing |
|
; |
|
|
|
outer_declaration |
|
: opt_extern_alias_directives opt_using_directives |
|
| opt_extern_alias_directives opt_using_directives namespace_or_type_declarations opt_attributes |
|
{ |
|
if ($4 != null) { |
|
Attributes attrs = (Attributes) $4; |
|
report.Error (1730, attrs.Attrs [0].Location, |
|
"Assembly and module attributes must precede all other elements except using clauses and extern alias declarations"); |
|
|
|
current_namespace.UnattachedAttributes = attrs; |
|
} |
|
} |
|
| opt_extern_alias_directives opt_using_directives attribute_sections |
|
{ |
|
module.AddAttributes ((Attributes) $3, current_namespace); |
|
} |
|
| error |
|
{ |
|
if (yyToken == Token.EXTERN_ALIAS) |
|
report.Error (439, lexer.Location, "An extern alias declaration must precede all other elements"); |
|
else |
|
Error_SyntaxError (yyToken); |
|
} |
|
; |
|
|
|
opt_EOF |
|
: /* empty */ |
|
| EOF |
|
; |
|
|
|
extern_alias_directives |
|
: extern_alias_directive |
|
| extern_alias_directives extern_alias_directive |
|
; |
|
|
|
extern_alias_directive |
|
: EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
string s = lt.Value; |
|
if (s != "alias") { |
|
syntax_error (lt.Location, "`alias' expected"); |
|
} else { |
|
if (lang_version == LanguageVersion.ISO_1) |
|
FeatureIsNotAvailable (lt.Location, "external alias"); |
|
|
|
lt = (Tokenizer.LocatedToken) $3; |
|
if (lt.Value == QualifiedAliasMember.GlobalAlias) { |
|
RootNamespace.Error_GlobalNamespaceRedefined (report, lt.Location); |
|
} |
|
|
|
var na = new UsingExternAlias (new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1)); |
|
current_namespace.AddUsing (na); |
|
|
|
lbag.AddLocation (na, GetLocation ($2), GetLocation ($4)); |
|
} |
|
} |
|
| EXTERN_ALIAS error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
} |
|
; |
|
|
|
using_directives |
|
: using_directive |
|
| using_directives using_directive |
|
; |
|
|
|
using_directive |
|
: using_namespace |
|
{ |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
; |
|
|
|
using_namespace |
|
: USING namespace_or_type_expr SEMICOLON |
|
{ |
|
var un = new UsingNamespace ((ATypeNameExpression) $2, GetLocation ($1)); |
|
current_namespace.AddUsing (un); |
|
|
|
lbag.AddLocation (un, GetLocation ($3)); |
|
} |
|
| USING IDENTIFIER ASSIGN namespace_or_type_expr SEMICOLON |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
if (lang_version != LanguageVersion.ISO_1 && lt.Value == "global") { |
|
report.Warning (440, 2, lt.Location, |
|
"An alias named `global' will not be used when resolving `global::'. The global namespace will be used instead"); |
|
} |
|
|
|
var un = new UsingAliasNamespace (new SimpleMemberName (lt.Value, lt.Location), (ATypeNameExpression) $4, GetLocation ($1)); |
|
current_namespace.AddUsing (un); |
|
lbag.AddLocation (un, GetLocation ($3), GetLocation ($5)); |
|
} |
|
| USING error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = null; |
|
} |
|
; |
|
|
|
// |
|
// Strictly speaking, namespaces don't have attributes but |
|
// we parse global attributes along with namespace declarations and then |
|
// detach them |
|
// |
|
namespace_declaration |
|
: opt_attributes NAMESPACE namespace_name |
|
{ |
|
Attributes attrs = (Attributes) $1; |
|
var name = (MemberName) $3; |
|
if (attrs != null) { |
|
bool valid_global_attrs = true; |
|
if ((current_namespace.DeclarationFound || current_namespace != file)) { |
|
valid_global_attrs = false; |
|
} else { |
|
foreach (var a in attrs.Attrs) { |
|
if (a.ExplicitTarget == "assembly" || a.ExplicitTarget == "module") |
|
continue; |
|
|
|
valid_global_attrs = false; |
|
break; |
|
} |
|
} |
|
|
|
if (!valid_global_attrs) |
|
report.Error (1671, name.Location, "A namespace declaration cannot have modifiers or attributes"); |
|
} |
|
|
|
module.AddAttributes (attrs, current_namespace); |
|
|
|
var ns = new NamespaceContainer (name, current_namespace); |
|
current_namespace.AddTypeContainer (ns); |
|
current_container = current_namespace = ns; |
|
} |
|
OPEN_BRACE |
|
{ |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon |
|
{ |
|
if ($11 != null) |
|
lbag.AddLocation (current_container, GetLocation ($2), GetLocation ($5), GetLocation ($10), GetLocation ($11)); |
|
else |
|
lbag.AddLocation (current_container, GetLocation ($2), GetLocation ($5), GetLocation ($10)); |
|
|
|
current_container = current_namespace = current_namespace.Parent; |
|
} |
|
; |
|
|
|
namespace_name |
|
: IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new MemberName (lt.Value, lt.Location); |
|
} |
|
| namespace_name DOT IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberName ((MemberName) $1, lt.Value, lt.Location) { |
|
DotLocation = GetLocation ($2) |
|
}; |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new MemberName ("<invalid>", lexer.Location); |
|
} |
|
; |
|
|
|
opt_semicolon |
|
: /* empty */ |
|
| SEMICOLON |
|
; |
|
|
|
opt_comma |
|
: /* empty */ |
|
| COMMA |
|
; |
|
|
|
opt_using_directives |
|
: /* empty */ |
|
| using_directives |
|
; |
|
|
|
opt_extern_alias_directives |
|
: /* empty */ |
|
| extern_alias_directives |
|
; |
|
|
|
opt_namespace_or_type_declarations |
|
: /* empty */ |
|
| namespace_or_type_declarations |
|
; |
|
|
|
namespace_or_type_declarations |
|
: namespace_or_type_declaration |
|
| namespace_or_type_declarations namespace_or_type_declaration |
|
; |
|
|
|
namespace_or_type_declaration |
|
: type_declaration |
|
{ |
|
if ($1 != null) { |
|
TypeContainer ds = (TypeContainer)$1; |
|
|
|
if ((ds.ModFlags & (Modifiers.PRIVATE | Modifiers.PROTECTED)) != 0){ |
|
report.Error (1527, ds.Location, |
|
"Namespace elements cannot be explicitly declared as private, protected or protected internal"); |
|
} |
|
|
|
// Here is a trick, for explicit attributes we don't know where they belong to until |
|
// we parse succeeding declaration hence we parse them as normal and re-attach them |
|
// when we know whether they are global (assembly:, module:) or local (type:). |
|
if (ds.OptAttributes != null) { |
|
ds.OptAttributes.ConvertGlobalAttributes (ds, current_namespace, !current_namespace.DeclarationFound && current_namespace == file); |
|
} |
|
} |
|
current_namespace.DeclarationFound = true; |
|
} |
|
| namespace_declaration |
|
{ |
|
current_namespace.DeclarationFound = true; |
|
} |
|
| attribute_sections CLOSE_BRACE { |
|
current_namespace.UnattachedAttributes = (Attributes) $1; |
|
report.Error (1518, lexer.Location, "Attributes must be attached to class, delegate, enum, interface or struct"); |
|
lexer.putback ('}'); |
|
} |
|
; |
|
|
|
type_declaration |
|
: class_declaration |
|
| struct_declaration |
|
| interface_declaration |
|
| enum_declaration |
|
| delegate_declaration |
|
// |
|
// Enable this when we have handled all errors, because this acts as a generic fallback |
|
// |
|
// | error { |
|
// Console.WriteLine ("Token=" + yyToken); |
|
// report.Error (1518, GetLocation ($1), "Expected class, struct, interface, enum or delegate"); |
|
// } |
|
; |
|
|
|
// |
|
// Attributes |
|
// |
|
|
|
opt_attributes |
|
: /* empty */ |
|
| attribute_sections |
|
; |
|
|
|
attribute_sections |
|
: attribute_section |
|
{ |
|
var sect = (List<Attribute>) $1; |
|
$$ = new Attributes (sect); |
|
if (locationListStack.Count > 0) |
|
lbag.AddLocation (sect, locationListStack.Pop ()); |
|
if (attributeCommas.Count > 0) { |
|
lbag.AppendTo (sect, attributeCommas); |
|
attributeCommas.Clear (); |
|
} |
|
} |
|
| attribute_sections attribute_section |
|
{ |
|
Attributes attrs = $1 as Attributes; |
|
var sect = (List<Attribute>) $2; |
|
|
|
if (locationListStack.Count > 0) |
|
lbag.AddLocation (sect, locationListStack.Pop ()); |
|
if (attrs == null) |
|
attrs = new Attributes (sect); |
|
else |
|
attrs.AddAttributes (sect); |
|
$$ = attrs; |
|
} |
|
; |
|
|
|
attribute_section |
|
: OPEN_BRACKET |
|
{ |
|
lexer.parsing_attribute_section = true; |
|
savedOpenLocation = GetLocation ($1); |
|
} |
|
attribute_section_cont |
|
{ |
|
lexer.parsing_attribute_section = false; |
|
$$ = $3; |
|
} |
|
; |
|
|
|
attribute_section_cont |
|
: attribute_target COLON |
|
{ |
|
current_attr_target = (string) $1; |
|
if (current_attr_target == "assembly" || current_attr_target == "module") { |
|
Lexer.check_incorrect_doc_comment (); |
|
} |
|
} |
|
attribute_list opt_comma CLOSE_BRACKET |
|
{ |
|
// when attribute target is invalid |
|
if (current_attr_target == string.Empty) |
|
$$ = new List<Attribute> (0); |
|
else |
|
$$ = $4; |
|
|
|
current_attr_target = null; |
|
lexer.parsing_attribute_section = false; |
|
if ($5 != null) { |
|
locationListStack.Push (new List<Location>(new [] { savedOpenLocation, savedCloseLocation, GetLocation ($2), GetLocation ($5), GetLocation ($6) })); |
|
} else { |
|
locationListStack.Push (new List<Location>(new [] { savedOpenLocation, savedCloseLocation, GetLocation ($2), GetLocation ($6) })); |
|
} |
|
} |
|
| attribute_list opt_comma CLOSE_BRACKET |
|
{ |
|
$$ = $1; |
|
if ($2 != null) { |
|
locationListStack.Push (new List<Location>(new [] { savedOpenLocation, GetLocation ($2), GetLocation ($3) })); |
|
} else { |
|
locationListStack.Push (new List<Location>(new [] { savedOpenLocation, GetLocation ($3) })); |
|
} |
|
} |
|
; |
|
|
|
attribute_target |
|
: IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = CheckAttributeTarget (lt.Value, lt.Location); |
|
savedCloseLocation = GetLocation ($1); |
|
} |
|
| EVENT { $$ = "event"; savedCloseLocation = GetLocation ($1); } |
|
| RETURN { $$ = "return"; savedCloseLocation = GetLocation ($1); } |
|
| error |
|
{ |
|
if (yyToken == Token.IDENTIFIER) { |
|
Error_SyntaxError (yyToken); |
|
$$ = null; |
|
} else { |
|
string name = GetTokenName (yyToken); |
|
$$ = CheckAttributeTarget (name, GetLocation ($1)); |
|
} |
|
} |
|
; |
|
|
|
attribute_list |
|
: attribute |
|
{ |
|
$$ = new List<Attribute> (4) { (Attribute) $1 }; |
|
} |
|
| attribute_list COMMA attribute |
|
{ |
|
var attrs = (List<Attribute>) $1; |
|
attrs.Add ((Attribute) $3); |
|
attributeCommas.Add (GetLocation ($2)); |
|
|
|
$$ = attrs; |
|
} |
|
; |
|
|
|
attribute |
|
: attribute_name |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
opt_attribute_arguments |
|
{ |
|
--lexer.parsing_block; |
|
|
|
var tne = (ATypeNameExpression) $1; |
|
if (tne.HasTypeArguments) { |
|
report.Error (404, tne.Location, "Attributes cannot be generic"); |
|
} |
|
Arguments [] arguments = (Arguments []) $3; |
|
|
|
$$ = new Attribute (current_attr_target, tne, (Arguments[]) $3, GetLocation ($1), lexer.IsEscapedIdentifier (tne)); |
|
if (arguments != null) { |
|
attributeArgumentCommas.Insert (0, savedAttrParenOpenLocation); |
|
attributeArgumentCommas.Add (savedAttrParenCloseLocation); |
|
lbag.AddLocation ($$, attributeArgumentCommas); |
|
attributeArgumentCommas.Clear (); |
|
} else if (HadAttributeParens) { |
|
lbag.AddLocation ($$, savedAttrParenOpenLocation, savedAttrParenCloseLocation); |
|
} |
|
} |
|
; |
|
|
|
attribute_name |
|
: namespace_or_type_expr |
|
; |
|
|
|
opt_attribute_arguments |
|
: /* empty */ { $$ = null; HadAttributeParens = false; } |
|
| OPEN_PARENS attribute_arguments CLOSE_PARENS |
|
{ |
|
savedAttrParenOpenLocation = GetLocation ($1); |
|
savedAttrParenCloseLocation = GetLocation ($3); |
|
$$ = $2; |
|
HadAttributeParens = true; |
|
} |
|
; |
|
|
|
|
|
attribute_arguments |
|
: /* empty */ { $$ = null; } |
|
| positional_or_named_argument |
|
{ |
|
Arguments a = new Arguments (4); |
|
a.Add ((Argument) $1); |
|
$$ = new Arguments [] { a, null }; |
|
} |
|
| named_attribute_argument |
|
{ |
|
Arguments a = new Arguments (4); |
|
a.Add ((Argument) $1); |
|
$$ = new Arguments [] { null, a }; |
|
} |
|
| attribute_arguments COMMA positional_or_named_argument |
|
{ |
|
Arguments[] o = (Arguments[]) $1; |
|
if (o [1] != null) { |
|
report.Error (1016, ((Argument) $3).Expr.Location, "Named attribute arguments must appear after the positional arguments"); |
|
o [0] = new Arguments (4); |
|
} |
|
|
|
Arguments args = ((Arguments) o [0]); |
|
if (args.Count > 0 && !($3 is NamedArgument) && args [args.Count - 1] is NamedArgument) |
|
Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); |
|
|
|
args.Add ((Argument) $3); |
|
attributeArgumentCommas.Add (GetLocation ($2)); |
|
} |
|
| attribute_arguments COMMA named_attribute_argument |
|
{ |
|
Arguments[] o = (Arguments[]) $1; |
|
if (o [1] == null) { |
|
o [1] = new Arguments (4); |
|
} |
|
|
|
((Arguments) o [1]).Add ((Argument) $3); |
|
attributeArgumentCommas.Add (GetLocation ($2)); |
|
} |
|
; |
|
|
|
positional_or_named_argument |
|
: expression |
|
{ |
|
$$ = new Argument ((Expression) $1); |
|
} |
|
| named_argument |
|
; |
|
|
|
named_attribute_argument |
|
: IDENTIFIER ASSIGN |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
expression |
|
{ |
|
--lexer.parsing_block; |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4); |
|
lbag.AddLocation ($$, GetLocation($2)); |
|
} |
|
; |
|
|
|
named_argument |
|
: identifier_inside_body COLON opt_named_modifier expression |
|
{ |
|
if (lang_version <= LanguageVersion.V_3) |
|
FeatureIsNotAvailable (GetLocation ($1), "named argument"); |
|
|
|
// Avoid boxing in common case (no modifier) |
|
var arg_mod = $3 == null ? Argument.AType.None : (Argument.AType) $3; |
|
|
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod); |
|
lbag.AddLocation ($$, GetLocation($2)); |
|
} |
|
; |
|
|
|
opt_named_modifier |
|
: /* empty */ { $$ = null; } |
|
| REF |
|
{ |
|
$$ = Argument.AType.Ref; |
|
} |
|
| OUT |
|
{ |
|
$$ = Argument.AType.Out; |
|
} |
|
; |
|
|
|
opt_class_member_declarations |
|
: /* empty */ |
|
| class_member_declarations |
|
; |
|
|
|
class_member_declarations |
|
: class_member_declaration |
|
{ |
|
lexer.parsing_modifiers = true; |
|
} |
|
| class_member_declarations class_member_declaration |
|
{ |
|
lexer.parsing_modifiers = true; |
|
} |
|
; |
|
|
|
class_member_declaration |
|
: constant_declaration |
|
| field_declaration |
|
| method_declaration |
|
| property_declaration |
|
| event_declaration |
|
| indexer_declaration |
|
| operator_declaration |
|
| constructor_declaration |
|
| destructor_declaration |
|
| type_declaration |
|
| attributes_without_members |
|
| error |
|
{ |
|
report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", |
|
GetSymbolName (yyToken)); |
|
$$ = null; |
|
lexer.parsing_generic_declaration = false; |
|
} |
|
; |
|
|
|
struct_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
opt_partial |
|
STRUCT |
|
{ |
|
lexer.ConstraintsParsing = true; |
|
} |
|
type_declaration_name |
|
{ |
|
push_current_container (new Struct (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3); |
|
lbag.AddMember (current_container, GetModifierLocations (), GetLocation ($4)); |
|
} |
|
opt_class_base |
|
opt_type_parameter_constraints_clauses |
|
{ |
|
lexer.ConstraintsParsing = false; |
|
|
|
if ($9 != null) |
|
current_container.SetConstraints ((List<Constraints>) $9); |
|
|
|
if (doc_support) |
|
current_container.PartialContainer.DocComment = Lexer.consume_doc_comment (); |
|
|
|
|
|
lexer.parsing_modifiers = true; |
|
} |
|
OPEN_BRACE |
|
{ |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
opt_class_member_declarations CLOSE_BRACE |
|
{ |
|
--lexer.parsing_declaration; |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
opt_semicolon |
|
{ |
|
if ($16 == null) { |
|
lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($14)); |
|
} else { |
|
lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($14), GetLocation ($16)); |
|
} |
|
$$ = pop_current_class (); |
|
} |
|
| opt_attributes opt_modifiers opt_partial STRUCT error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
} |
|
; |
|
|
|
constant_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
CONST type IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $5; |
|
var mod = (Modifiers) $2; |
|
current_field = new Const (current_type, (FullNamedExpression) $4, mod, new MemberName (lt.Value, lt.Location), (Attributes) $1); |
|
current_type.AddMember (current_field); |
|
|
|
if ((mod & Modifiers.STATIC) != 0) { |
|
report.Error (504, current_field.Location, "The constant `{0}' cannot be marked static", current_field.GetSignatureForError ()); |
|
} |
|
|
|
$$ = current_field; |
|
} |
|
constant_initializer opt_constant_declarators SEMICOLON |
|
{ |
|
if (doc_support) { |
|
current_field.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
current_field.Initializer = (ConstInitializer) $7; |
|
lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); |
|
current_field = null; |
|
} |
|
; |
|
|
|
opt_constant_declarators |
|
: /* empty */ |
|
| constant_declarators |
|
; |
|
|
|
constant_declarators |
|
: constant_declarator |
|
{ |
|
current_field.AddDeclarator ((FieldDeclarator) $1); |
|
} |
|
| constant_declarators constant_declarator |
|
{ |
|
current_field.AddDeclarator ((FieldDeclarator) $2); |
|
} |
|
; |
|
|
|
constant_declarator |
|
: COMMA IDENTIFIER constant_initializer |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
; |
|
|
|
constant_initializer |
|
: ASSIGN |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
constant_initializer_expr |
|
{ |
|
--lexer.parsing_block; |
|
$$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
| error |
|
{ |
|
report.Error (145, lexer.Location, "A const field requires a value to be provided"); |
|
$$ = null; |
|
} |
|
; |
|
|
|
constant_initializer_expr |
|
: constant_expression |
|
| array_initializer |
|
; |
|
|
|
field_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
member_type IDENTIFIER |
|
{ |
|
lexer.parsing_generic_declaration = false; |
|
|
|
FullNamedExpression type = (FullNamedExpression) $3; |
|
if (type.Type != null && type.Type.Kind == MemberKind.Void) |
|
report.Error (670, GetLocation ($3), "Fields cannot have void type"); |
|
|
|
var lt = (Tokenizer.LocatedToken) $4; |
|
current_field = new Field (current_type, type, (Modifiers) $2, new MemberName (lt.Value, lt.Location), (Attributes) $1); |
|
current_type.AddField (current_field); |
|
$$ = current_field; |
|
} |
|
opt_field_initializer |
|
opt_field_declarators |
|
SEMICOLON |
|
{ |
|
if (doc_support) { |
|
current_field.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($8)); |
|
$$ = current_field; |
|
current_field = null; |
|
} |
|
| opt_attributes |
|
opt_modifiers |
|
FIXED simple_type IDENTIFIER |
|
{ |
|
if (lang_version < LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($3), "fixed size buffers"); |
|
|
|
var lt = (Tokenizer.LocatedToken) $5; |
|
current_field = new FixedField (current_type, (FullNamedExpression) $4, (Modifiers) $2, |
|
new MemberName (lt.Value, lt.Location), (Attributes) $1); |
|
|
|
current_type.AddField (current_field); |
|
} |
|
fixed_field_size opt_fixed_field_declarators SEMICOLON |
|
{ |
|
if (doc_support) { |
|
current_field.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
current_field.Initializer = (ConstInitializer) $7; |
|
lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); |
|
$$ = current_field; |
|
current_field = null; |
|
} |
|
| opt_attributes |
|
opt_modifiers |
|
FIXED simple_type error |
|
SEMICOLON |
|
{ |
|
report.Error (1641, GetLocation ($5), "A fixed size buffer field must have the array size specifier after the field name"); |
|
} |
|
; |
|
|
|
opt_field_initializer |
|
: /* empty */ |
|
| ASSIGN |
|
{ |
|
++lexer.parsing_block; |
|
current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; |
|
start_block (GetLocation ($1)); |
|
} |
|
variable_initializer |
|
{ |
|
--lexer.parsing_block; |
|
current_field.Initializer = (Expression) $3; |
|
lbag.AppendToMember (current_field, GetLocation ($1)); |
|
end_block (lexer.Location); |
|
current_local_parameters = null; |
|
} |
|
; |
|
|
|
opt_field_declarators |
|
: /* empty */ |
|
| field_declarators |
|
; |
|
|
|
field_declarators |
|
: field_declarator |
|
{ |
|
current_field.AddDeclarator ((FieldDeclarator) $1); |
|
} |
|
| field_declarators field_declarator |
|
{ |
|
current_field.AddDeclarator ((FieldDeclarator) $2); |
|
} |
|
; |
|
|
|
field_declarator |
|
: COMMA IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
| COMMA IDENTIFIER ASSIGN |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
variable_initializer |
|
{ |
|
--lexer.parsing_block; |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); |
|
} |
|
; |
|
|
|
opt_fixed_field_declarators |
|
: /* empty */ |
|
| fixed_field_declarators |
|
; |
|
|
|
fixed_field_declarators |
|
: fixed_field_declarator |
|
{ |
|
current_field.AddDeclarator ((FieldDeclarator) $1); |
|
} |
|
| fixed_field_declarators fixed_field_declarator |
|
{ |
|
current_field.AddDeclarator ((FieldDeclarator) $2); |
|
} |
|
; |
|
|
|
fixed_field_declarator |
|
: COMMA IDENTIFIER fixed_field_size |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
; |
|
|
|
fixed_field_size |
|
: OPEN_BRACKET |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
expression CLOSE_BRACKET |
|
{ |
|
--lexer.parsing_block; |
|
$$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($4)); |
|
} |
|
| OPEN_BRACKET error |
|
{ |
|
report.Error (443, lexer.Location, "Value or constant expected"); |
|
$$ = null; |
|
} |
|
; |
|
|
|
variable_initializer |
|
: expression |
|
| array_initializer |
|
| error |
|
{ |
|
// It has to be here for the parent to safely restore artificial block |
|
Error_SyntaxError (yyToken); |
|
$$ = null; |
|
} |
|
; |
|
|
|
method_declaration |
|
: method_header |
|
{ |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
|
|
// Add it early in the case of body being eof for full ast |
|
Method m = (Method) $1; |
|
async_block = (m.ModFlags & Modifiers.ASYNC) != 0; |
|
current_type.AddMember (m); |
|
} |
|
method_body |
|
{ |
|
Method method = (Method) $1; |
|
method.Block = (ToplevelBlock) $3; |
|
async_block = false; |
|
|
|
if (method.Block == null) { |
|
lbag.AppendToMember (method, savedLocation); // semicolon |
|
method.ParameterInfo.CheckParameters (method); |
|
|
|
if ((method.ModFlags & Modifiers.ASYNC) != 0) { |
|
report.Error (1994, method.Location, "`{0}': The async modifier can only be used with methods that have a body", |
|
method.GetSignatureForError ()); |
|
} |
|
} else { |
|
if (current_container.Kind == MemberKind.Interface) { |
|
report.Error (531, method.Location, "`{0}': interface members cannot have a definition", |
|
method.GetSignatureForError ()); |
|
} |
|
} |
|
|
|
current_local_parameters = null; |
|
|
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
; |
|
|
|
method_header |
|
: opt_attributes |
|
opt_modifiers |
|
member_type |
|
method_declaration_name OPEN_PARENS |
|
{ |
|
valid_param_mod = ParameterModifierType.All; |
|
} |
|
opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
lexer.ConstraintsParsing = true; |
|
} |
|
opt_type_parameter_constraints_clauses |
|
{ |
|
lexer.ConstraintsParsing = false; |
|
valid_param_mod = 0; |
|
MemberName name = (MemberName) $4; |
|
current_local_parameters = (ParametersCompiled) $7; |
|
|
|
var method = Method.Create (current_type, (FullNamedExpression) $3, (Modifiers) $2, |
|
name, current_local_parameters, (Attributes) $1, $10 != null); |
|
|
|
if ($10 != null) |
|
method.SetConstraints ((List<Constraints>) $10); |
|
|
|
if (doc_support) |
|
method.DocComment = Lexer.consume_doc_comment (); |
|
|
|
lbag.AddMember (method, GetModifierLocations (), GetLocation ($5), GetLocation ($8)); |
|
$$ = method; |
|
} |
|
| opt_attributes |
|
opt_modifiers |
|
PARTIAL |
|
VOID |
|
{ |
|
lexer.parsing_generic_declaration = true; |
|
} |
|
method_declaration_name |
|
OPEN_PARENS |
|
{ |
|
lexer.parsing_generic_declaration = false; |
|
valid_param_mod = ParameterModifierType.All; |
|
} |
|
opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
lexer.ConstraintsParsing = true; |
|
} |
|
opt_type_parameter_constraints_clauses |
|
{ |
|
lexer.ConstraintsParsing = false; |
|
valid_param_mod = 0; |
|
|
|
MemberName name = (MemberName) $6; |
|
current_local_parameters = (ParametersCompiled) $9; |
|
|
|
var modifiers = (Modifiers) $2; |
|
modifiers |= Modifiers.PARTIAL; |
|
|
|
var method = Method.Create (current_type, new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($4)), |
|
modifiers, name, current_local_parameters, (Attributes) $1, $11 != null); |
|
|
|
if ($11 != null) |
|
method.SetConstraints ((List<Constraints>) $11); |
|
|
|
if (doc_support) |
|
method.DocComment = Lexer.consume_doc_comment (); |
|
|
|
StoreModifierLocation (Modifiers.PARTIAL, GetLocation ($3)); |
|
lbag.AddMember (method, GetModifierLocations (), GetLocation ($7), GetLocation ($10)); |
|
$$ = method; |
|
} |
|
| opt_attributes |
|
opt_modifiers |
|
member_type |
|
modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
MemberName name = (MemberName) $5; |
|
report.Error (1585, name.Location, |
|
"Member modifier `{0}' must precede the member type and name", ModifiersExtensions.Name ((Modifiers) $4)); |
|
|
|
var method = Method.Create (current_type, (FullNamedExpression) $3, |
|
0, name, (ParametersCompiled) $7, (Attributes) $1, false); |
|
|
|
current_local_parameters = (ParametersCompiled) $7; |
|
|
|
if (doc_support) |
|
method.DocComment = Lexer.consume_doc_comment (); |
|
|
|
$$ = method; |
|
} |
|
| opt_attributes |
|
opt_modifiers |
|
member_type |
|
method_declaration_name error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
current_local_parameters = ParametersCompiled.Undefined; |
|
|
|
MemberName name = (MemberName) $4; |
|
var method = Method.Create (current_type, (FullNamedExpression) $3, (Modifiers) $2, |
|
name, current_local_parameters, (Attributes) $1, false); |
|
|
|
if (doc_support) |
|
method.DocComment = Lexer.consume_doc_comment (); |
|
|
|
$$ = method; |
|
} |
|
; |
|
|
|
method_body |
|
: block |
|
| SEMICOLON { savedLocation = GetLocation ($1); $$ = null; } |
|
; |
|
|
|
opt_formal_parameter_list |
|
: /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } |
|
| formal_parameter_list |
|
; |
|
|
|
formal_parameter_list |
|
: fixed_parameters |
|
{ |
|
var pars_list = (List<Parameter>) $1; |
|
$$ = new ParametersCompiled (pars_list.ToArray ()); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
| fixed_parameters COMMA parameter_array |
|
{ |
|
var pars_list = (List<Parameter>) $1; |
|
pars_list.Add ((Parameter) $3); |
|
parameterListCommas.Add (GetLocation ($2)); |
|
|
|
$$ = new ParametersCompiled (pars_list.ToArray ()); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
| fixed_parameters COMMA arglist_modifier |
|
{ |
|
var pars_list = (List<Parameter>) $1; |
|
pars_list.Add (new ArglistParameter (GetLocation ($3))); |
|
parameterListCommas.Add (GetLocation ($2)); |
|
|
|
$$ = new ParametersCompiled (pars_list.ToArray (), true); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
| parameter_array COMMA error |
|
{ |
|
if ($1 != null) |
|
report.Error (231, ((Parameter) $1).Location, "A params parameter must be the last parameter in a formal parameter list"); |
|
|
|
$$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
| fixed_parameters COMMA parameter_array COMMA error |
|
{ |
|
if ($3 != null) |
|
report.Error (231, ((Parameter) $3).Location, "A params parameter must be the last parameter in a formal parameter list"); |
|
|
|
var pars_list = (List<Parameter>) $1; |
|
pars_list.Add (new ArglistParameter (GetLocation ($3))); |
|
parameterListCommas.Add (GetLocation ($2)); |
|
parameterListCommas.Add (GetLocation ($4)); |
|
|
|
$$ = new ParametersCompiled (pars_list.ToArray (), true); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
| arglist_modifier COMMA error |
|
{ |
|
report.Error (257, GetLocation ($1), "An __arglist parameter must be the last parameter in a formal parameter list"); |
|
|
|
$$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
| fixed_parameters COMMA ARGLIST COMMA error |
|
{ |
|
report.Error (257, GetLocation ($3), "An __arglist parameter must be the last parameter in a formal parameter list"); |
|
|
|
var pars_list = (List<Parameter>) $1; |
|
pars_list.Add (new ArglistParameter (GetLocation ($3))); |
|
parameterListCommas.Add (GetLocation ($2)); |
|
parameterListCommas.Add (GetLocation ($4)); |
|
|
|
$$ = new ParametersCompiled (pars_list.ToArray (), true); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
| parameter_array |
|
{ |
|
$$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); |
|
} |
|
| arglist_modifier |
|
{ |
|
$$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = ParametersCompiled.EmptyReadOnlyParameters; |
|
} |
|
; |
|
|
|
fixed_parameters |
|
: fixed_parameter |
|
{ |
|
parameters_bucket.Clear (); |
|
Parameter p = (Parameter) $1; |
|
parameters_bucket.Add (p); |
|
parameterListCommas.Clear (); |
|
default_parameter_used = p.HasDefaultValue; |
|
$$ = parameters_bucket; |
|
} |
|
| fixed_parameters COMMA fixed_parameter |
|
{ |
|
var pars = (List<Parameter>) $1; |
|
Parameter p = (Parameter) $3; |
|
if (p != null) { |
|
if (p.HasExtensionMethodModifier) |
|
report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter"); |
|
else if (!p.HasDefaultValue && default_parameter_used) |
|
report.Error (1737, p.Location, "Optional parameter cannot precede required parameters"); |
|
|
|
default_parameter_used |= p.HasDefaultValue; |
|
pars.Add (p); |
|
|
|
parameterListCommas.Add (GetLocation ($2)); |
|
} |
|
|
|
$$ = $1; |
|
} |
|
; |
|
|
|
fixed_parameter |
|
: opt_attributes |
|
opt_parameter_modifier |
|
parameter_type |
|
IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $4; |
|
$$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); |
|
lbag.AddLocation ($$, parameterModifierLocation); |
|
} |
|
| opt_attributes |
|
opt_parameter_modifier |
|
parameter_type |
|
IDENTIFIER OPEN_BRACKET CLOSE_BRACKET |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $4; |
|
report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); |
|
$$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); |
|
lbag.AddLocation ($$, parameterModifierLocation); |
|
} |
|
| attribute_sections error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
Location l = GetLocation ($2); |
|
$$ = new Parameter (null, null, Parameter.Modifier.NONE, (Attributes) $1, l); |
|
} |
|
| opt_attributes |
|
opt_parameter_modifier |
|
parameter_type |
|
error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
Location l = GetLocation ($4); |
|
$$ = new Parameter ((FullNamedExpression) $3, null, (Parameter.Modifier) $2, (Attributes) $1, l); |
|
lbag.AddLocation ($$, parameterModifierLocation); |
|
} |
|
| opt_attributes |
|
opt_parameter_modifier |
|
parameter_type |
|
IDENTIFIER |
|
ASSIGN |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
constant_expression |
|
{ |
|
--lexer.parsing_block; |
|
if (lang_version <= LanguageVersion.V_3) { |
|
FeatureIsNotAvailable (GetLocation ($5), "optional parameter"); |
|
} |
|
|
|
Parameter.Modifier mod = (Parameter.Modifier) $2; |
|
if (mod != Parameter.Modifier.NONE) { |
|
switch (mod) { |
|
case Parameter.Modifier.REF: |
|
case Parameter.Modifier.OUT: |
|
report.Error (1741, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", |
|
Parameter.GetModifierSignature (mod)); |
|
break; |
|
|
|
case Parameter.Modifier.This: |
|
report.Error (1743, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", |
|
Parameter.GetModifierSignature (mod)); |
|
break; |
|
default: |
|
throw new NotImplementedException (mod.ToString ()); |
|
} |
|
|
|
mod = Parameter.Modifier.NONE; |
|
} |
|
|
|
if ((valid_param_mod & ParameterModifierType.DefaultValue) == 0) |
|
report.Error (1065, GetLocation ($5), "Optional parameter is not valid in this context"); |
|
|
|
var lt = (Tokenizer.LocatedToken) $4; |
|
$$ = new Parameter ((FullNamedExpression) $3, lt.Value, mod, (Attributes) $1, lt.Location); |
|
lbag.AddLocation ($$, parameterModifierLocation, GetLocation ($5)); // parameterModifierLocation should be ignored when mod == NONE |
|
|
|
if ($7 != null) |
|
((Parameter) $$).DefaultValue = new DefaultParameterValueExpression ((Expression) $7); |
|
} |
|
; |
|
|
|
opt_parameter_modifier |
|
: /* empty */ { $$ = Parameter.Modifier.NONE; } |
|
| parameter_modifiers |
|
; |
|
|
|
parameter_modifiers |
|
: parameter_modifier |
|
{ |
|
$$ = $1; |
|
} |
|
| parameter_modifiers parameter_modifier |
|
{ |
|
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 |
|
{ |
|
if ((valid_param_mod & ParameterModifierType.Ref) == 0) |
|
Error_ParameterModifierNotValid ("ref", GetLocation ($1)); |
|
parameterModifierLocation = GetLocation ($1); |
|
$$ = Parameter.Modifier.REF; |
|
} |
|
| OUT |
|
{ |
|
if ((valid_param_mod & ParameterModifierType.Out) == 0) |
|
Error_ParameterModifierNotValid ("out", GetLocation ($1)); |
|
parameterModifierLocation = GetLocation ($1); |
|
$$ = Parameter.Modifier.OUT; |
|
} |
|
| THIS |
|
{ |
|
if ((valid_param_mod & ParameterModifierType.This) == 0) |
|
Error_ParameterModifierNotValid ("this", GetLocation ($1)); |
|
|
|
if (lang_version <= LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "extension methods"); |
|
parameterModifierLocation = GetLocation ($1); |
|
$$ = Parameter.Modifier.This; |
|
} |
|
; |
|
|
|
parameter_array |
|
: opt_attributes params_modifier type IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $4; |
|
$$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); |
|
lbag.AddLocation ($$, savedLocation); |
|
} |
|
| opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression |
|
{ |
|
report.Error (1751, GetLocation ($2), "Cannot specify a default value for a parameter array"); |
|
|
|
var lt = (Tokenizer.LocatedToken) $4; |
|
$$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); |
|
lbag.AddLocation ($$, savedLocation); |
|
} |
|
| opt_attributes params_modifier type error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = null; |
|
} |
|
; |
|
|
|
params_modifier |
|
: PARAMS |
|
{ |
|
if ((valid_param_mod & ParameterModifierType.Params) == 0) |
|
report.Error (1670, (GetLocation ($1)), "The `params' modifier is not allowed in current context"); |
|
savedLocation = GetLocation ($1); |
|
} |
|
| PARAMS parameter_modifier |
|
{ |
|
Parameter.Modifier mod = (Parameter.Modifier)$2; |
|
if ((mod & Parameter.Modifier.This) != 0) { |
|
report.Error (1104, GetLocation ($1), "The parameter modifiers `this' and `params' cannot be used altogether"); |
|
} else { |
|
report.Error (1611, GetLocation ($1), "The params parameter cannot be declared as ref or out"); |
|
} |
|
savedLocation = GetLocation ($1); |
|
} |
|
| PARAMS params_modifier |
|
{ |
|
Error_DuplicateParameterModifier (GetLocation ($1), Parameter.Modifier.PARAMS); |
|
} |
|
; |
|
|
|
arglist_modifier |
|
: ARGLIST |
|
{ |
|
if ((valid_param_mod & ParameterModifierType.Arglist) == 0) |
|
report.Error (1669, GetLocation ($1), "__arglist is not valid in this context"); |
|
} |
|
; |
|
|
|
property_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
member_type |
|
member_declaration_name |
|
{ |
|
if (doc_support) |
|
tmpComment = Lexer.consume_doc_comment (); |
|
} |
|
OPEN_BRACE |
|
{ |
|
var type = (FullNamedExpression) $3; |
|
current_property = new Property (current_type, type, (Modifiers) $2, |
|
(MemberName) $4, (Attributes) $1); |
|
|
|
if (type.Type != null && type.Type.Kind == MemberKind.Void) |
|
report.Error (547, GetLocation ($3), "`{0}': property or indexer cannot have void type", current_property.GetSignatureForError ()); |
|
|
|
current_type.AddMember (current_property); |
|
lbag.AddMember (current_property, GetModifierLocations (), GetLocation ($6)); |
|
|
|
lexer.PropertyParsing = true; |
|
} |
|
accessor_declarations |
|
{ |
|
lexer.PropertyParsing = false; |
|
|
|
if (doc_support) |
|
current_property.DocComment = ConsumeStoredComment (); |
|
} |
|
CLOSE_BRACE |
|
{ |
|
lbag.AppendToMember (current_property, GetLocation ($10)); |
|
current_property = null; |
|
} |
|
; |
|
|
|
|
|
indexer_declaration |
|
: opt_attributes opt_modifiers |
|
member_type indexer_declaration_name OPEN_BRACKET |
|
{ |
|
valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; |
|
} |
|
opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE |
|
{ |
|
valid_param_mod = 0; |
|
var type = (FullNamedExpression) $3; |
|
Indexer indexer = new Indexer (current_type, type, (MemberName) $4, (Modifiers) $2, (ParametersCompiled) $7, (Attributes) $1); |
|
|
|
current_property = indexer; |
|
|
|
current_type.AddIndexer (indexer); |
|
lbag.AddMember (current_property, GetModifierLocations (), GetLocation ($5), GetLocation ($8), GetLocation ($9)); |
|
|
|
if (type.Type != null && type.Type.Kind == MemberKind.Void) |
|
report.Error (620, GetLocation ($3), "`{0}': indexer return type cannot be `void'", indexer.GetSignatureForError ()); |
|
|
|
if (indexer.ParameterInfo.IsEmpty) { |
|
report.Error (1551, GetLocation ($5), "Indexers must have at least one parameter"); |
|
} |
|
|
|
if (doc_support) { |
|
tmpComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
lexer.PropertyParsing = true; |
|
} |
|
accessor_declarations |
|
{ |
|
lexer.PropertyParsing = false; |
|
} |
|
CLOSE_BRACE |
|
{ |
|
if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null) |
|
((Indexer) current_property).ParameterInfo.CheckParameters (current_property); |
|
|
|
if (doc_support) |
|
current_property.DocComment = ConsumeStoredComment (); |
|
|
|
lbag.AppendToMember (current_property, GetLocation ($12)); |
|
current_property = null; |
|
} |
|
; |
|
|
|
|
|
accessor_declarations |
|
: get_accessor_declaration |
|
| get_accessor_declaration accessor_declarations |
|
| set_accessor_declaration |
|
| set_accessor_declaration accessor_declarations |
|
| error |
|
{ |
|
if (yyToken == Token.CLOSE_BRACE) { |
|
report.Error (548, lexer.Location, "`{0}': property or indexer must have at least one accessor", current_property.GetSignatureForError ()); |
|
} else { |
|
if (yyToken == Token.SEMICOLON) |
|
report.Error (1597, lexer.Location, "Semicolon after method or accessor block is not valid"); |
|
else |
|
report.Error (1014, GetLocation ($1), "A get or set accessor expected"); |
|
} |
|
} |
|
; |
|
|
|
get_accessor_declaration |
|
: opt_attributes opt_modifiers GET |
|
{ |
|
if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { |
|
FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); |
|
} |
|
|
|
if (current_property.Get != null) { |
|
report.Error (1007, GetLocation ($3), "Property accessor already defined"); |
|
} |
|
|
|
if (current_property is Indexer) { |
|
current_property.Get = new Indexer.GetIndexerMethod (current_property, (Modifiers) $2, ((Indexer)current_property).ParameterInfo.Clone (), |
|
(Attributes) $1, GetLocation ($3)); |
|
} else { |
|
current_property.Get = new Property.GetMethod (current_property, |
|
(Modifiers) $2, (Attributes) $1, GetLocation ($3)); |
|
} |
|
|
|
current_local_parameters = current_property.Get.ParameterInfo; |
|
lexer.PropertyParsing = false; |
|
} |
|
accessor_body |
|
{ |
|
if ($5 != null) { |
|
current_property.Get.Block = (ToplevelBlock) $5; |
|
|
|
if (current_container.Kind == MemberKind.Interface) { |
|
report.Error (531, current_property.Get.Block.StartLocation, |
|
"`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); |
|
} |
|
lbag.AddMember (current_property.Get, GetModifierLocations ()); |
|
} else { |
|
lbag.AddMember (current_property.Get, GetModifierLocations (), savedLocation); |
|
} |
|
|
|
current_local_parameters = null; |
|
lexer.PropertyParsing = true; |
|
|
|
if (doc_support) |
|
if (Lexer.doc_state == XmlCommentState.Error) |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
} |
|
; |
|
|
|
set_accessor_declaration |
|
: opt_attributes opt_modifiers SET |
|
{ |
|
if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { |
|
FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); |
|
} |
|
|
|
if (current_property.Set != null) { |
|
report.Error (1007, GetLocation ($3), "Property accessor already defined"); |
|
} |
|
|
|
if (current_property is Indexer) { |
|
current_property.Set = new Indexer.SetIndexerMethod (current_property, (Modifiers) $2, |
|
ParametersCompiled.MergeGenerated (compiler, |
|
((Indexer)current_property).ParameterInfo, true, new Parameter ( |
|
current_property.TypeExpression, "value", Parameter.Modifier.NONE, null, GetLocation ($3)), |
|
null), |
|
(Attributes) $1, GetLocation ($3)); |
|
} else { |
|
current_property.Set = new Property.SetMethod (current_property, (Modifiers) $2, |
|
ParametersCompiled.CreateImplicitParameter (current_property.TypeExpression, GetLocation ($3)), |
|
(Attributes) $1, GetLocation ($3)); |
|
} |
|
|
|
current_local_parameters = current_property.Set.ParameterInfo; |
|
lexer.PropertyParsing = false; |
|
} |
|
accessor_body |
|
{ |
|
if ($5 != null) { |
|
current_property.Set.Block = (ToplevelBlock) $5; |
|
|
|
if (current_container.Kind == MemberKind.Interface) { |
|
report.Error (531, current_property.Set.Block.StartLocation, |
|
"`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); |
|
} |
|
lbag.AddMember (current_property.Set, GetModifierLocations ()); |
|
} else { |
|
lbag.AddMember (current_property.Set, GetModifierLocations (), savedLocation); |
|
} |
|
|
|
current_local_parameters = null; |
|
lexer.PropertyParsing = true; |
|
|
|
if (doc_support |
|
&& Lexer.doc_state == XmlCommentState.Error) |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
} |
|
; |
|
|
|
accessor_body |
|
: block |
|
| SEMICOLON |
|
{ |
|
savedLocation = GetLocation ($1); |
|
$$ = null; |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (1043, yyToken, "Invalid accessor body"); |
|
$$ = null; |
|
} |
|
; |
|
|
|
interface_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
opt_partial |
|
INTERFACE |
|
{ |
|
lexer.ConstraintsParsing = true; |
|
} |
|
type_declaration_name |
|
{ |
|
push_current_container (new Interface (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1), $3); |
|
lbag.AddMember (current_container, GetModifierLocations (), GetLocation ($4)); |
|
} |
|
opt_class_base |
|
opt_type_parameter_constraints_clauses |
|
{ |
|
lexer.ConstraintsParsing = false; |
|
|
|
if ($9 != null) |
|
current_container.SetConstraints ((List<Constraints>) $9); |
|
|
|
if (doc_support) { |
|
current_container.PartialContainer.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
lexer.parsing_modifiers = true; |
|
} |
|
OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE |
|
{ |
|
--lexer.parsing_declaration; |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
opt_semicolon |
|
{ |
|
if ($15 == null) { |
|
lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13)); |
|
} else { |
|
lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13), GetLocation ($15)); |
|
} |
|
$$ = pop_current_class (); |
|
} |
|
| opt_attributes opt_modifiers opt_partial INTERFACE error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
} |
|
; |
|
|
|
opt_interface_member_declarations |
|
: /* empty */ |
|
| interface_member_declarations |
|
; |
|
|
|
interface_member_declarations |
|
: interface_member_declaration |
|
{ |
|
lexer.parsing_modifiers = true; |
|
} |
|
| interface_member_declarations interface_member_declaration |
|
{ |
|
lexer.parsing_modifiers = true; |
|
} |
|
; |
|
|
|
interface_member_declaration |
|
: constant_declaration |
|
{ |
|
report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); |
|
} |
|
| field_declaration |
|
{ |
|
report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); |
|
} |
|
| method_declaration |
|
| property_declaration |
|
| event_declaration |
|
| indexer_declaration |
|
| operator_declaration |
|
{ |
|
report.Error (567, GetLocation ($1), "Interfaces cannot contain operators"); |
|
} |
|
| constructor_declaration |
|
{ |
|
report.Error (526, GetLocation ($1), "Interfaces cannot contain contructors"); |
|
} |
|
| type_declaration |
|
{ |
|
report.Error (524, GetLocation ($1), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); |
|
} |
|
; |
|
|
|
operator_declaration |
|
: opt_attributes opt_modifiers operator_declarator |
|
{ |
|
} |
|
operator_body |
|
{ |
|
OperatorDeclaration decl = (OperatorDeclaration) $3; |
|
if (decl != null) { |
|
Operator op = new Operator ( |
|
current_type, decl.optype, decl.ret_type, (Modifiers) $2, |
|
current_local_parameters, |
|
(ToplevelBlock) $5, (Attributes) $1, decl.location); |
|
|
|
if (op.Block == null) |
|
op.ParameterInfo.CheckParameters (op); |
|
|
|
if (doc_support) { |
|
op.DocComment = tmpComment; |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
// Note again, checking is done in semantic analysis |
|
current_type.AddOperator (op); |
|
|
|
lbag.AddMember (op, GetModifierLocations (), lbag.GetLocations (decl)); |
|
if ($5 == null) { // Semicolon |
|
lbag.AppendTo (op, savedLocation); |
|
} |
|
} |
|
|
|
current_local_parameters = null; |
|
} |
|
; |
|
|
|
operator_body |
|
: block |
|
| SEMICOLON { savedLocation = GetLocation ($1); $$ = null; } |
|
; |
|
|
|
operator_type |
|
: type_expression_or_array |
|
| VOID |
|
{ |
|
report.Error (590, GetLocation ($1), "User-defined operators cannot return void"); |
|
$$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); |
|
} |
|
; |
|
|
|
operator_declarator |
|
: operator_type OPERATOR overloadable_operator OPEN_PARENS |
|
{ |
|
valid_param_mod = ParameterModifierType.DefaultValue; |
|
} |
|
opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
valid_param_mod = 0; |
|
|
|
Location loc = GetLocation ($2); |
|
Operator.OpType op = (Operator.OpType) $3; |
|
current_local_parameters = (ParametersCompiled)$6; |
|
|
|
int p_count = current_local_parameters.Count; |
|
if (p_count == 1) { |
|
if (op == Operator.OpType.Addition) |
|
op = Operator.OpType.UnaryPlus; |
|
else if (op == Operator.OpType.Subtraction) |
|
op = Operator.OpType.UnaryNegation; |
|
} |
|
|
|
if (IsUnaryOperator (op)) { |
|
if (p_count == 2) { |
|
report.Error (1020, loc, "Overloadable binary operator expected"); |
|
} else if (p_count != 1) { |
|
report.Error (1535, loc, "Overloaded unary operator `{0}' takes one parameter", |
|
Operator.GetName (op)); |
|
} |
|
} else { |
|
if (p_count > 2) { |
|
report.Error (1534, loc, "Overloaded binary operator `{0}' takes two parameters", |
|
Operator.GetName (op)); |
|
} else if (p_count != 2) { |
|
report.Error (1019, loc, "Overloadable unary operator expected"); |
|
} |
|
} |
|
|
|
if (doc_support) { |
|
tmpComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
} |
|
|
|
$$ = new OperatorDeclaration (op, (FullNamedExpression) $1, loc); |
|
lbag.AddLocation ($$, GetLocation ($2), savedOperatorLocation, GetLocation ($4), GetLocation ($7)); |
|
} |
|
| conversion_operator_declarator |
|
; |
|
|
|
overloadable_operator |
|
// Unary operators: |
|
: BANG { $$ = Operator.OpType.LogicalNot; savedOperatorLocation = GetLocation ($1); } |
|
| TILDE { $$ = Operator.OpType.OnesComplement; savedOperatorLocation = GetLocation ($1); } |
|
| OP_INC { $$ = Operator.OpType.Increment; savedOperatorLocation = GetLocation ($1); } |
|
| OP_DEC { $$ = Operator.OpType.Decrement; savedOperatorLocation = GetLocation ($1); } |
|
| TRUE { $$ = Operator.OpType.True; savedOperatorLocation = GetLocation ($1); } |
|
| FALSE { $$ = Operator.OpType.False; savedOperatorLocation = GetLocation ($1); } |
|
// Unary and binary: |
|
| PLUS { $$ = Operator.OpType.Addition; savedOperatorLocation = GetLocation ($1); } |
|
| MINUS { $$ = Operator.OpType.Subtraction; savedOperatorLocation = GetLocation ($1); } |
|
// Binary: |
|
| STAR { $$ = Operator.OpType.Multiply; savedOperatorLocation = GetLocation ($1); } |
|
| DIV { $$ = Operator.OpType.Division; savedOperatorLocation = GetLocation ($1); } |
|
| PERCENT { $$ = Operator.OpType.Modulus; savedOperatorLocation = GetLocation ($1); } |
|
| BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; savedOperatorLocation = GetLocation ($1); } |
|
| BITWISE_OR { $$ = Operator.OpType.BitwiseOr; savedOperatorLocation = GetLocation ($1); } |
|
| CARRET { $$ = Operator.OpType.ExclusiveOr; savedOperatorLocation = GetLocation ($1); } |
|
| OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; savedOperatorLocation = GetLocation ($1); } |
|
| OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; savedOperatorLocation = GetLocation ($1); } |
|
| OP_EQ { $$ = Operator.OpType.Equality; savedOperatorLocation = GetLocation ($1); } |
|
| OP_NE { $$ = Operator.OpType.Inequality; savedOperatorLocation = GetLocation ($1); } |
|
| OP_GT { $$ = Operator.OpType.GreaterThan; savedOperatorLocation = GetLocation ($1); } |
|
| OP_LT { $$ = Operator.OpType.LessThan; savedOperatorLocation = GetLocation ($1); } |
|
| OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; savedOperatorLocation = GetLocation ($1); } |
|
| OP_LE { $$ = Operator.OpType.LessThanOrEqual; savedOperatorLocation = GetLocation ($1); } |
|
; |
|
|
|
conversion_operator_declarator |
|
: IMPLICIT OPERATOR type OPEN_PARENS |
|
{ |
|
valid_param_mod = ParameterModifierType.DefaultValue; |
|
} |
|
opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
valid_param_mod = 0; |
|
|
|
Location loc = GetLocation ($2); |
|
current_local_parameters = (ParametersCompiled)$6; |
|
|
|
if (doc_support) { |
|
tmpComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
} |
|
|
|
$$ = new OperatorDeclaration (Operator.OpType.Implicit, (FullNamedExpression) $3, loc); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); |
|
} |
|
| EXPLICIT OPERATOR type OPEN_PARENS |
|
{ |
|
valid_param_mod = ParameterModifierType.DefaultValue; |
|
} |
|
opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
valid_param_mod = 0; |
|
|
|
Location loc = GetLocation ($2); |
|
current_local_parameters = (ParametersCompiled)$6; |
|
|
|
if (doc_support) { |
|
tmpComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
} |
|
|
|
$$ = new OperatorDeclaration (Operator.OpType.Explicit, (FullNamedExpression) $3, loc); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); |
|
} |
|
| IMPLICIT error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; |
|
$$ = new OperatorDeclaration (Operator.OpType.Implicit, null, GetLocation ($1)); |
|
} |
|
| EXPLICIT error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; |
|
$$ = new OperatorDeclaration (Operator.OpType.Explicit, null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
constructor_declaration |
|
: constructor_declarator |
|
constructor_body |
|
{ |
|
Constructor c = (Constructor) $1; |
|
c.Block = (ToplevelBlock) $2; |
|
|
|
if (doc_support) |
|
c.DocComment = ConsumeStoredComment (); |
|
|
|
current_local_parameters = null; |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
; |
|
|
|
constructor_declarator |
|
: opt_attributes |
|
opt_modifiers |
|
IDENTIFIER |
|
{ |
|
if (doc_support) { |
|
tmpComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
valid_param_mod = ParameterModifierType.All; |
|
} |
|
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
valid_param_mod = 0; |
|
current_local_parameters = (ParametersCompiled) $6; |
|
|
|
var lt = (Tokenizer.LocatedToken) $3; |
|
var mods = (Modifiers) $2; |
|
var c = new Constructor (current_type, lt.Value, mods, (Attributes) $1, current_local_parameters, lt.Location); |
|
|
|
if (lt.Value != current_container.MemberName.Name) { |
|
report.Error (1520, c.Location, "Class, struct, or interface method must have a return type"); |
|
} else if ((mods & Modifiers.STATIC) != 0) { |
|
if ((mods & Modifiers.AccessibilityMask) != 0){ |
|
report.Error (515, c.Location, |
|
"`{0}': static constructor cannot have an access modifier", |
|
c.GetSignatureForError ()); |
|
} |
|
} |
|
|
|
current_type.AddConstructor (c); |
|
lbag.AddMember (c, GetModifierLocations (), GetLocation ($5), GetLocation ($7)); |
|
$$ = c; |
|
|
|
// |
|
// start block here, so possible anonymous methods inside |
|
// constructor initializer can get correct parent block |
|
// |
|
start_block (lexer.Location); |
|
} |
|
opt_constructor_initializer |
|
{ |
|
if ($9 != null) { |
|
var c = (Constructor) $8; |
|
c.Initializer = (ConstructorInitializer) $9; |
|
|
|
if (c.IsStatic) { |
|
report.Error (514, c.Location, |
|
"`{0}': static constructor cannot have an explicit `this' or `base' constructor call", |
|
c.GetSignatureForError ()); |
|
} |
|
} |
|
|
|
$$ = $8; |
|
} |
|
; |
|
|
|
constructor_body |
|
: block_prepared |
|
| SEMICOLON { current_block = null; $$ = null; } |
|
; |
|
|
|
opt_constructor_initializer |
|
: /* Empty */ |
|
| constructor_initializer |
|
; |
|
|
|
constructor_initializer |
|
: COLON BASE OPEN_PARENS |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
opt_argument_list CLOSE_PARENS |
|
{ |
|
--lexer.parsing_block; |
|
$$ = new ConstructorBaseInitializer ((Arguments) $5, GetLocation ($2)); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); |
|
} |
|
| COLON THIS OPEN_PARENS |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
opt_argument_list CLOSE_PARENS |
|
{ |
|
--lexer.parsing_block; |
|
$$ = new ConstructorThisInitializer ((Arguments) $5, GetLocation ($2)); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); |
|
} |
|
| COLON error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new ConstructorThisInitializer (null, GetLocation ($2)); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = null; |
|
} |
|
; |
|
|
|
destructor_declaration |
|
: opt_attributes opt_modifiers TILDE |
|
{ |
|
if (doc_support) { |
|
tmpComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
} |
|
|
|
current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; |
|
} |
|
IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $5; |
|
if (lt.Value != current_container.MemberName.Name){ |
|
report.Error (574, lt.Location, "Name of destructor must match name of class"); |
|
} else if (current_container.Kind != MemberKind.Class){ |
|
report.Error (575, lt.Location, "Only class types can contain destructor"); |
|
} |
|
|
|
Destructor d = new Destructor (current_type, (Modifiers) $2, |
|
ParametersCompiled.EmptyReadOnlyParameters, (Attributes) $1, lt.Location); |
|
d.Identifier = lt.Value; |
|
if (doc_support) |
|
d.DocComment = ConsumeStoredComment (); |
|
|
|
d.Block = (ToplevelBlock) $8; |
|
current_type.AddMember (d); |
|
lbag.AddMember (d, GetModifierLocations (), GetLocation ($3), GetLocation ($6), GetLocation ($7)); |
|
|
|
current_local_parameters = null; |
|
} |
|
; |
|
|
|
event_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
EVENT type member_declaration_name |
|
{ |
|
current_event_field = new EventField (current_type, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); |
|
current_type.AddMember (current_event_field); |
|
|
|
if (current_event_field.MemberName.ExplicitInterface != null) { |
|
report.Error (71, current_event_field.Location, "`{0}': An explicit interface implementation of an event must use property syntax", |
|
current_event_field.GetSignatureForError ()); |
|
} |
|
|
|
$$ = current_event_field; |
|
} |
|
opt_event_initializer |
|
opt_event_declarators |
|
SEMICOLON |
|
{ |
|
if (doc_support) { |
|
current_event_field.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
lbag.AddMember (current_event_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); |
|
current_event_field = null; |
|
} |
|
| opt_attributes |
|
opt_modifiers |
|
EVENT type member_declaration_name |
|
OPEN_BRACE |
|
{ |
|
current_event = new EventProperty (current_type, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); |
|
current_type.AddMember (current_event); |
|
lbag.AddMember (current_event, GetModifierLocations (), GetLocation ($3), GetLocation ($6)); |
|
|
|
lexer.EventParsing = true; |
|
} |
|
event_accessor_declarations |
|
{ |
|
if (current_container.Kind == MemberKind.Interface) |
|
report.Error (69, GetLocation ($6), "Event in interface cannot have add or remove accessors"); |
|
|
|
lexer.EventParsing = false; |
|
} |
|
CLOSE_BRACE |
|
{ |
|
if (doc_support) { |
|
current_event.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
lbag.AppendToMember (current_event, GetLocation ($9)); |
|
current_event = null; |
|
current_local_parameters = null; |
|
} |
|
; |
|
|
|
opt_event_initializer |
|
: /* empty */ |
|
| ASSIGN |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
event_variable_initializer |
|
{ |
|
--lexer.parsing_block; |
|
current_event_field.Initializer = (Expression) $3; |
|
} |
|
; |
|
|
|
opt_event_declarators |
|
: /* empty */ |
|
| event_declarators |
|
; |
|
|
|
event_declarators |
|
: event_declarator |
|
{ |
|
current_event_field.AddDeclarator ((FieldDeclarator) $1); |
|
} |
|
| event_declarators event_declarator |
|
{ |
|
current_event_field.AddDeclarator ((FieldDeclarator) $2); |
|
} |
|
; |
|
|
|
event_declarator |
|
: COMMA IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
| COMMA IDENTIFIER ASSIGN |
|
{ |
|
++lexer.parsing_block; |
|
} |
|
event_variable_initializer |
|
{ |
|
--lexer.parsing_block; |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); |
|
} |
|
; |
|
|
|
event_variable_initializer |
|
: { |
|
if (current_container.Kind == MemberKind.Interface) { |
|
report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", |
|
current_event_field.GetSignatureForError ()); |
|
} |
|
|
|
if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) { |
|
report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer", |
|
current_event_field.GetSignatureForError ()); |
|
} |
|
} |
|
variable_initializer |
|
{ |
|
$$ = $2; |
|
} |
|
; |
|
|
|
event_accessor_declarations |
|
: add_accessor_declaration remove_accessor_declaration |
|
| remove_accessor_declaration add_accessor_declaration |
|
| add_accessor_declaration |
|
{ |
|
report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", |
|
current_event.GetSignatureForError ()); |
|
} |
|
| remove_accessor_declaration |
|
{ |
|
report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", |
|
current_event.GetSignatureForError ()); |
|
} |
|
| error |
|
{ |
|
report.Error (1055, GetLocation ($1), "An add or remove accessor expected"); |
|
$$ = null; |
|
} |
|
; |
|
|
|
add_accessor_declaration |
|
: opt_attributes opt_modifiers ADD |
|
{ |
|
if ($2 != ModifierNone) { |
|
report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); |
|
} |
|
|
|
current_event.Add = new EventProperty.AddDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); |
|
current_local_parameters = current_event.Add.ParameterInfo; |
|
|
|
lbag.AddMember (current_event.Add, GetModifierLocations ()); |
|
lexer.EventParsing = false; |
|
} |
|
event_accessor_block |
|
{ |
|
lexer.EventParsing = true; |
|
|
|
current_event.Add.Block = (ToplevelBlock) $5; |
|
|
|
if (current_container.Kind == MemberKind.Interface) { |
|
report.Error (531, current_event.Add.Block.StartLocation, |
|
"`{0}': interface members cannot have a definition", current_event.Add.GetSignatureForError ()); |
|
} |
|
|
|
current_local_parameters = null; |
|
} |
|
; |
|
|
|
remove_accessor_declaration |
|
: opt_attributes opt_modifiers REMOVE |
|
{ |
|
if ($2 != ModifierNone) { |
|
report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); |
|
} |
|
|
|
current_event.Remove = new EventProperty.RemoveDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); |
|
current_local_parameters = current_event.Remove.ParameterInfo; |
|
|
|
lbag.AddMember (current_event.Remove, GetModifierLocations ()); |
|
lexer.EventParsing = false; |
|
} |
|
event_accessor_block |
|
{ |
|
lexer.EventParsing = true; |
|
|
|
current_event.Remove.Block = (ToplevelBlock) $5; |
|
|
|
if (current_container.Kind == MemberKind.Interface) { |
|
report.Error (531, current_event.Remove.Block.StartLocation, |
|
"`{0}': interface members cannot have a definition", current_event.Remove.GetSignatureForError ()); |
|
} |
|
|
|
current_local_parameters = null; |
|
} |
|
; |
|
|
|
event_accessor_block |
|
: opt_semicolon |
|
{ |
|
report.Error (73, lexer.Location, "An add or remove accessor must have a body"); |
|
$$ = null; |
|
} |
|
| block; |
|
; |
|
|
|
attributes_without_members |
|
: attribute_sections CLOSE_BRACE |
|
{ |
|
current_type.UnattachedAttributes = (Attributes) $1; |
|
report.Error (1519, GetLocation ($1), "An attribute is missing member declaration"); |
|
lexer.putback ('}'); |
|
} |
|
; |
|
|
|
enum_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
ENUM |
|
type_declaration_name |
|
opt_enum_base |
|
{ |
|
if (doc_support) |
|
enumTypeComment = Lexer.consume_doc_comment (); |
|
} |
|
OPEN_BRACE |
|
{ |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
|
|
MemberName name = (MemberName) $4; |
|
if (name.IsGeneric) { |
|
report.Error (1675, name.Location, "Enums cannot have type parameters"); |
|
} |
|
|
|
push_current_container (new Enum (current_container, (FullNamedExpression) $5, (Modifiers) $2, name, (Attributes) $1), null); |
|
if ($5 != null) { |
|
lbag.AddMember (current_container, GetModifierLocations (), GetLocation ($3), savedLocation, GetLocation ($7)); |
|
} else { |
|
lbag.AddMember (current_container, GetModifierLocations (), GetLocation ($3), GetLocation ($7)); |
|
} |
|
} |
|
opt_enum_member_declarations |
|
{ |
|
// here will be evaluated after CLOSE_BLACE is consumed. |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
CLOSE_BRACE opt_semicolon |
|
{ |
|
lbag.AppendToMember (current_container, GetLocation ($11)); |
|
if ($12 != null) { |
|
lbag.AppendToMember (current_container, GetLocation ($12)); |
|
} |
|
if (doc_support) |
|
current_container.DocComment = enumTypeComment; |
|
|
|
--lexer.parsing_declaration; |
|
|
|
// if (doc_support) |
|
// em.DocComment = ev.DocComment; |
|
|
|
$$ = pop_current_class (); |
|
} |
|
; |
|
|
|
opt_enum_base |
|
: /* empty */ |
|
| COLON type |
|
{ |
|
savedLocation = GetLocation ($1); |
|
$$ = $2; |
|
} |
|
| COLON error |
|
{ |
|
Error_TypeExpected (GetLocation ($1)); |
|
$$ = null; |
|
} |
|
; |
|
|
|
opt_enum_member_declarations |
|
: /* empty */ |
|
| enum_member_declarations |
|
| enum_member_declarations COMMA |
|
{ |
|
lbag.AppendToMember (current_container, GetLocation ($2)); |
|
} |
|
; |
|
|
|
enum_member_declarations |
|
: enum_member_declaration |
|
| enum_member_declarations COMMA enum_member_declaration |
|
{ |
|
lbag.AppendToMember (current_container, GetLocation ($2)); |
|
$$ = $3; |
|
} |
|
; |
|
|
|
enum_member_declaration |
|
: opt_attributes IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var em = new EnumMember ((Enum) current_type, new MemberName (lt.Value, lt.Location), (Attributes) $1); |
|
((Enum) current_type).AddEnumMember (em); |
|
|
|
if (doc_support) { |
|
em.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
$$ = em; |
|
} |
|
| opt_attributes IDENTIFIER |
|
{ |
|
++lexer.parsing_block; |
|
if (doc_support) { |
|
tmpComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.NotAllowed; |
|
} |
|
} |
|
ASSIGN constant_expression |
|
{ |
|
--lexer.parsing_block; |
|
|
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var em = new EnumMember ((Enum) current_type, new MemberName (lt.Value, lt.Location), (Attributes) $1); |
|
em.Initializer = new ConstInitializer (em, (Expression) $5, GetLocation ($4)); |
|
((Enum) current_type).AddEnumMember (em); |
|
|
|
if (doc_support) |
|
em.DocComment = ConsumeStoredComment (); |
|
|
|
$$ = em; |
|
} |
|
| opt_attributes IDENTIFIER error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var em = new EnumMember ((Enum) current_type, new MemberName (lt.Value, lt.Location), (Attributes) $1); |
|
((Enum) current_type).AddEnumMember (em); |
|
|
|
if (doc_support) { |
|
em.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
$$ = em; |
|
} |
|
| attributes_without_members |
|
; |
|
|
|
delegate_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
DELEGATE |
|
member_type type_declaration_name |
|
OPEN_PARENS |
|
{ |
|
valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; |
|
} |
|
opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
valid_param_mod = 0; |
|
|
|
ParametersCompiled p = (ParametersCompiled) $8; |
|
|
|
Delegate del = new Delegate (current_container, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, p, (Attributes) $1); |
|
|
|
p.CheckParameters (del); |
|
|
|
current_container.AddTypeContainer (del); |
|
|
|
current_delegate = del; |
|
lexer.ConstraintsParsing = true; |
|
} |
|
opt_type_parameter_constraints_clauses |
|
{ |
|
lexer.ConstraintsParsing = false; |
|
} |
|
SEMICOLON |
|
{ |
|
if (doc_support) { |
|
current_delegate.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
if ($11 != null) |
|
current_delegate.SetConstraints ((List<Constraints>) $11); |
|
lbag.AddMember (current_delegate, GetModifierLocations (), GetLocation ($3), GetLocation ($6), GetLocation ($9), GetLocation ($13)); |
|
|
|
$$ = current_delegate; |
|
|
|
current_delegate = null; |
|
} |
|
; |
|
|
|
opt_nullable |
|
: /* empty */ |
|
| INTERR_NULLABLE |
|
{ |
|
if (lang_version < LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "nullable types"); |
|
|
|
$$ = ComposedTypeSpecifier.CreateNullable (GetLocation ($1)); |
|
} |
|
; |
|
|
|
namespace_or_type_expr |
|
: member_name |
|
| qualified_alias_member IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt1 = (Tokenizer.LocatedToken) $1; |
|
var lt2 = (Tokenizer.LocatedToken) $2; |
|
|
|
$$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
member_name |
|
: simple_name_expr |
|
| namespace_or_type_expr DOT IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
simple_name_expr |
|
: IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new SimpleName (lt.Value, (TypeArguments)$2, lt.Location); |
|
} |
|
; |
|
|
|
// |
|
// Generics arguments (any type, without attributes) |
|
// |
|
opt_type_argument_list |
|
: /* empty */ |
|
| OP_GENERICS_LT type_arguments OP_GENERICS_GT |
|
{ |
|
if (lang_version < LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "generics"); |
|
var list = locationListStack.Pop (); |
|
list.Add (GetLocation ($1)); |
|
list.Add (GetLocation ($2)); |
|
lbag.AddLocation ($2, list); |
|
|
|
$$ = $2;; |
|
} |
|
| OP_GENERICS_LT error |
|
{ |
|
Error_TypeExpected (lexer.Location); |
|
$$ = new TypeArguments (); |
|
} |
|
; |
|
|
|
type_arguments |
|
: type |
|
{ |
|
TypeArguments type_args = new TypeArguments (); |
|
type_args.Add ((FullNamedExpression) $1); |
|
$$ = type_args; |
|
locationListStack.Push (new List<Location> ()); |
|
} |
|
| type_arguments COMMA type |
|
{ |
|
TypeArguments type_args = (TypeArguments) $1; |
|
type_args.Add ((FullNamedExpression) $3); |
|
$$ = type_args; |
|
locationListStack.Peek ().Add (GetLocation ($2)); |
|
} |
|
; |
|
|
|
// |
|
// Generics parameters (identifiers only, with attributes), used in type or method declarations |
|
// |
|
type_declaration_name |
|
: IDENTIFIER |
|
{ |
|
lexer.parsing_generic_declaration = true; |
|
} |
|
opt_type_parameter_list |
|
{ |
|
lexer.parsing_generic_declaration = false; |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new MemberName (lt.Value, (TypeParameters)$3, lt.Location); |
|
} |
|
; |
|
|
|
member_declaration_name |
|
: method_declaration_name |
|
{ |
|
MemberName mn = (MemberName)$1; |
|
if (mn.TypeParameters != null) |
|
syntax_error (mn.Location, string.Format ("Member `{0}' cannot declare type arguments", |
|
mn.GetSignatureForError ())); |
|
} |
|
; |
|
|
|
method_declaration_name |
|
: type_declaration_name |
|
| explicit_interface IDENTIFIER opt_type_parameter_list |
|
{ |
|
lexer.parsing_generic_declaration = false; |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new MemberName (lt.Value, (TypeParameters) $3, (ATypeNameExpression) $1, lt.Location); |
|
} |
|
; |
|
|
|
indexer_declaration_name |
|
: THIS |
|
{ |
|
lexer.parsing_generic_declaration = false; |
|
$$ = new MemberName (TypeDefinition.DefaultIndexerName, GetLocation ($1)); |
|
} |
|
| explicit_interface THIS |
|
{ |
|
lexer.parsing_generic_declaration = false; |
|
$$ = new MemberName (TypeDefinition.DefaultIndexerName, null, (ATypeNameExpression) $1, GetLocation ($2)); |
|
} |
|
; |
|
|
|
explicit_interface |
|
: IDENTIFIER opt_type_argument_list DOT |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new SimpleName (lt.Value, (TypeArguments) $2, lt.Location); |
|
lbag.AddLocation ($$, GetLocation ($3)); |
|
} |
|
| qualified_alias_member IDENTIFIER opt_type_argument_list DOT |
|
{ |
|
var lt1 = (Tokenizer.LocatedToken) $1; |
|
var lt2 = (Tokenizer.LocatedToken) $2; |
|
|
|
$$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); |
|
lbag.AddLocation ($$, GetLocation ($4)); |
|
} |
|
| explicit_interface IDENTIFIER opt_type_argument_list DOT |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new MemberAccess ((ATypeNameExpression) $1, lt.Value, (TypeArguments) $3, lt.Location); |
|
lbag.AddLocation ($$, GetLocation ($4)); |
|
} |
|
; |
|
|
|
opt_type_parameter_list |
|
: /* empty */ |
|
| OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT |
|
{ |
|
if (lang_version < LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "generics"); |
|
|
|
$$ = $2; |
|
var list = locationListStack.Pop (); |
|
list.Add (GetLocation ($1)); |
|
list.Add (GetLocation ($2)); |
|
lbag.AddLocation ($2, list); |
|
} |
|
; |
|
|
|
type_parameters |
|
: type_parameter |
|
{ |
|
var tparams = new TypeParameters (); |
|
tparams.Add ((TypeParameter)$1); |
|
$$ = tparams; |
|
locationListStack.Push (new List<Location> ()); |
|
} |
|
| type_parameters COMMA type_parameter |
|
{ |
|
var tparams = (TypeParameters) $1; |
|
tparams.Add ((TypeParameter)$3); |
|
$$ = tparams; |
|
locationListStack.Peek ().Add (GetLocation ($2)); |
|
} |
|
; |
|
|
|
type_parameter |
|
: opt_attributes opt_type_parameter_variance IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken)$3; |
|
$$ = new TypeParameter (new MemberName (lt.Value, lt.Location), (Attributes)$1, (Variance) $2); |
|
} |
|
| error |
|
{ |
|
if (GetTokenName (yyToken) == "type") |
|
report.Error (81, GetLocation ($1), "Type parameter declaration must be an identifier not a type"); |
|
else |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new TypeParameter (MemberName.Null, null, Variance.None); |
|
} |
|
; |
|
|
|
// |
|
// All types where void is allowed |
|
// |
|
type_and_void |
|
: type_expression_or_array |
|
| VOID |
|
{ |
|
$$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); |
|
} |
|
; |
|
|
|
member_type |
|
: type_and_void |
|
{ |
|
lexer.parsing_generic_declaration = true; |
|
} |
|
; |
|
|
|
// |
|
// A type which does not allow `void' to be used |
|
// |
|
type |
|
: type_expression_or_array |
|
| VOID |
|
{ |
|
Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); |
|
$$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); |
|
} |
|
; |
|
|
|
simple_type |
|
: type_expression |
|
| VOID |
|
{ |
|
Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); |
|
$$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); |
|
} |
|
; |
|
|
|
parameter_type |
|
: type_expression_or_array |
|
| VOID |
|
{ |
|
report.Error (1536, GetLocation ($1), "Invalid parameter type `void'"); |
|
$$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); |
|
} |
|
; |
|
|
|
type_expression_or_array |
|
: type_expression |
|
| type_expression rank_specifiers |
|
{ |
|
$$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); |
|
} |
|
; |
|
|
|
type_expression |
|
: namespace_or_type_expr opt_nullable |
|
{ |
|
if ($2 != null) { |
|
$$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2); |
|
} else { |
|
var sn = $1 as SimpleName; |
|
if (sn != null && sn.Name == "var") |
|
$$ = new VarExpr (sn.Location); |
|
else |
|
$$ = $1; |
|
} |
|
} |
|
| namespace_or_type_expr pointer_stars |
|
{ |
|
$$ = new ComposedCast ((ATypeNameExpression) $1, (ComposedTypeSpecifier) $2); |
|
} |
|
| builtin_types opt_nullable |
|
{ |
|
if ($2 != null) |
|
$$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); |
|
} |
|
| builtin_types pointer_stars |
|
{ |
|
$$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); |
|
} |
|
| VOID pointer_stars |
|
{ |
|
$$ = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)), (ComposedTypeSpecifier) $2); |
|
} |
|
; |
|
|
|
type_list |
|
: base_type_name |
|
{ |
|
var types = new List<FullNamedExpression> (2); |
|
types.Add ((FullNamedExpression) $1); |
|
$$ = types; |
|
} |
|
| type_list COMMA base_type_name |
|
{ |
|
var types = (List<FullNamedExpression>) $1; |
|
types.Add ((FullNamedExpression) $3); |
|
lbag.AppendTo (types, GetLocation ($2)); |
|
$$ = types; |
|
} |
|
; |
|
|
|
base_type_name |
|
: type |
|
{ |
|
if ($1 is ComposedCast) { |
|
report.Error (1521, GetLocation ($1), "Invalid base type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); |
|
} |
|
$$ = $1; |
|
} |
|
; |
|
|
|
/* |
|
* replaces all the productions for isolating the various |
|
* simple types, but we need this to reuse it easily in variable_type |
|
*/ |
|
builtin_types |
|
: OBJECT { $$ = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation ($1)); } |
|
| STRING { $$ = new TypeExpression (compiler.BuiltinTypes.String, GetLocation ($1)); } |
|
| BOOL { $$ = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation ($1)); } |
|
| DECIMAL { $$ = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation ($1)); } |
|
| FLOAT { $$ = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation ($1)); } |
|
| DOUBLE { $$ = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation ($1)); } |
|
| integral_type |
|
; |
|
|
|
integral_type |
|
: SBYTE { $$ = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation ($1)); } |
|
| BYTE { $$ = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation ($1)); } |
|
| SHORT { $$ = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation ($1)); } |
|
| USHORT { $$ = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation ($1)); } |
|
| INT { $$ = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation ($1)); } |
|
| UINT { $$ = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation ($1)); } |
|
| LONG { $$ = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation ($1)); } |
|
| ULONG { $$ = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation ($1)); } |
|
| CHAR { $$ = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation ($1)); } |
|
; |
|
|
|
// |
|
// Expressions, section 7.5 |
|
// |
|
|
|
|
|
primary_expression |
|
: primary_expression_or_type |
|
| literal |
|
| array_creation_expression |
|
| parenthesized_expression |
|
| default_value_expression |
|
| invocation_expression |
|
| element_access |
|
| this_access |
|
| base_access |
|
| post_increment_expression |
|
| post_decrement_expression |
|
| object_or_delegate_creation_expression |
|
| anonymous_type_expression |
|
| typeof_expression |
|
| sizeof_expression |
|
| checked_expression |
|
| unchecked_expression |
|
| pointer_member_access |
|
| anonymous_method_expression |
|
| undocumented_expressions |
|
; |
|
|
|
primary_expression_or_type |
|
: IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new SimpleName (lt.Value, (TypeArguments)$2, lt.Location); |
|
} |
|
| IDENTIFIER GENERATE_COMPLETION { |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location); |
|
} |
|
| member_access |
|
; |
|
|
|
literal |
|
: boolean_literal |
|
| LITERAL |
|
| NULL { $$ = new NullLiteral (GetLocation ($1)); } |
|
; |
|
|
|
boolean_literal |
|
: TRUE { $$ = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation ($1)); } |
|
| FALSE { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); } |
|
; |
|
|
|
|
|
// |
|
// Here is the trick, tokenizer may think that parens is a special but |
|
// parser is interested in open parens only, so we merge them. |
|
// Consider: if (a)foo (); |
|
// |
|
open_parens_any |
|
: OPEN_PARENS |
|
| OPEN_PARENS_CAST |
|
; |
|
|
|
// |
|
// Use this production to accept closing parenthesis or |
|
// performing completion |
|
// |
|
close_parens |
|
: CLOSE_PARENS |
|
| COMPLETE_COMPLETION |
|
; |
|
|
|
|
|
parenthesized_expression |
|
: OPEN_PARENS expression CLOSE_PARENS |
|
{ |
|
$$ = new ParenthesizedExpression ((Expression) $2); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); |
|
} |
|
| OPEN_PARENS expression COMPLETE_COMPLETION |
|
{ |
|
$$ = new ParenthesizedExpression ((Expression) $2); |
|
} |
|
; |
|
|
|
member_access |
|
: primary_expression DOT IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location) { |
|
DotLocation = GetLocation ($2) |
|
}; |
|
} |
|
| builtin_types DOT IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location) { |
|
DotLocation = GetLocation ($2) |
|
}; |
|
} |
|
| BASE DOT IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location) { |
|
DotLocation = GetLocation ($2) |
|
}; |
|
} |
|
| qualified_alias_member IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt1 = (Tokenizer.LocatedToken) $1; |
|
var lt2 = (Tokenizer.LocatedToken) $2; |
|
|
|
$$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| primary_expression DOT GENERATE_COMPLETION { |
|
$$ = new CompletionMemberAccess ((Expression) $1, null,GetLocation ($3)); |
|
} |
|
| primary_expression DOT IDENTIFIER GENERATE_COMPLETION { |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); |
|
} |
|
| builtin_types DOT GENERATE_COMPLETION |
|
{ |
|
$$ = new CompletionMemberAccess ((Expression) $1, null, lexer.Location); |
|
} |
|
| builtin_types DOT IDENTIFIER GENERATE_COMPLETION { |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); |
|
} |
|
; |
|
|
|
invocation_expression |
|
: primary_expression open_parens_any opt_argument_list close_parens |
|
{ |
|
$$ = new Invocation ((Expression) $1, (Arguments) $3); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| primary_expression open_parens_any argument_list error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new Invocation ((Expression) $1, (Arguments) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
|
|
; |
|
|
|
opt_object_or_collection_initializer |
|
: /* empty */ { $$ = null; } |
|
| object_or_collection_initializer |
|
; |
|
|
|
object_or_collection_initializer |
|
: OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion |
|
{ |
|
if ($2 == null) { |
|
$$ = new CollectionOrObjectInitializers (new List<Expression> (), GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); |
|
} else { |
|
$$ = new CollectionOrObjectInitializers ((List<Expression>) $2, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); |
|
} |
|
} |
|
| OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE |
|
{ |
|
$$ = new CollectionOrObjectInitializers ((List<Expression>) $2, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($4)); |
|
} |
|
; |
|
|
|
opt_member_initializer_list |
|
: /* empty */ { $$ = null; } |
|
| member_initializer_list |
|
{ |
|
$$ = $1; |
|
} |
|
; |
|
|
|
member_initializer_list |
|
: member_initializer |
|
{ |
|
var a = new List<Expression> (); |
|
a.Add ((Expression) $1); |
|
$$ = a; |
|
} |
|
| member_initializer_list COMMA member_initializer |
|
{ |
|
var a = (List<Expression>)$1; |
|
a.Add ((Expression) $3); |
|
lbag.AppendTo (a, GetLocation ($2)); |
|
$$ = a; |
|
} |
|
| member_initializer_list error { |
|
Error_SyntaxError (yyToken); |
|
$$ = $1; |
|
} |
|
; |
|
|
|
member_initializer |
|
: IDENTIFIER ASSIGN initializer_value |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| GENERATE_COMPLETION |
|
{ |
|
$$ = new CompletionElementInitializer (null, GetLocation ($1)); |
|
} |
|
| non_assignment_expression opt_COMPLETE_COMPLETION { |
|
CompletionSimpleName csn = $1 as CompletionSimpleName; |
|
if (csn == null) |
|
$$ = new CollectionElementInitializer ((Expression)$1); |
|
else |
|
$$ = new CompletionElementInitializer (csn.Prefix, csn.Location); |
|
} |
|
| OPEN_BRACE expression_list CLOSE_BRACE |
|
{ |
|
if ($2 == null) |
|
$$ = null; |
|
else { |
|
$$ = new CollectionElementInitializer ((List<Expression>)$2, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
} |
|
| OPEN_BRACE CLOSE_BRACE |
|
{ |
|
report.Error (1920, GetLocation ($1), "An element initializer cannot be empty"); |
|
$$ = new CollectionElementInitializer (new List<Expression> (), GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
initializer_value |
|
: expression |
|
| object_or_collection_initializer |
|
; |
|
|
|
opt_argument_list |
|
: /* empty */ { $$ = null; } |
|
| argument_list |
|
; |
|
|
|
argument_list |
|
: argument_or_named_argument |
|
{ |
|
Arguments list = new Arguments (4); |
|
list.Add ((Argument) $1); |
|
$$ = list; |
|
} |
|
| argument_list COMMA argument |
|
{ |
|
Arguments list = (Arguments) $1; |
|
if (list [list.Count - 1] is NamedArgument) |
|
Error_NamedArgumentExpected ((NamedArgument) list [list.Count - 1]); |
|
|
|
list.Add ((Argument) $3); |
|
lbag.AppendTo (list, GetLocation ($2)); |
|
$$ = list; |
|
} |
|
| argument_list COMMA named_argument |
|
{ |
|
Arguments list = (Arguments) $1; |
|
NamedArgument a = (NamedArgument) $3; |
|
for (int i = 0; i < list.Count; ++i) { |
|
NamedArgument na = list [i] as NamedArgument; |
|
if (na != null && na.Name == a.Name) |
|
report.Error (1740, na.Location, "Named argument `{0}' specified multiple times", |
|
na.Name); |
|
} |
|
|
|
list.Add (a); |
|
lbag.AppendTo (list, GetLocation ($2)); |
|
$$ = list; |
|
} |
|
| argument_list COMMA error |
|
{ |
|
lexer.putback (')'); // TODO: Wrong but what can I do |
|
Error_SyntaxError (yyToken); |
|
$$ = $1; |
|
} |
|
| COMMA error |
|
{ |
|
report.Error (839, GetLocation ($1), "An argument is missing"); |
|
$$ = null; |
|
} |
|
; |
|
|
|
argument |
|
: expression |
|
{ |
|
$$ = new Argument ((Expression) $1); |
|
} |
|
| non_simple_argument |
|
; |
|
|
|
argument_or_named_argument |
|
: argument |
|
| named_argument |
|
; |
|
|
|
non_simple_argument |
|
: REF variable_reference |
|
{ |
|
$$ = new Argument ((Expression) $2, Argument.AType.Ref); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
| OUT variable_reference |
|
{ |
|
$$ = new Argument ((Expression) $2, Argument.AType.Out); |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
| ARGLIST OPEN_PARENS argument_list CLOSE_PARENS |
|
{ |
|
$$ = new Argument (new Arglist ((Arguments) $3, GetLocation ($1))); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| ARGLIST OPEN_PARENS CLOSE_PARENS |
|
{ |
|
$$ = new Argument (new Arglist (GetLocation ($1))); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); |
|
} |
|
; |
|
|
|
variable_reference |
|
: expression |
|
; |
|
|
|
element_access |
|
: primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET |
|
{ |
|
$$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2)); |
|
lbag.AddLocation ($$, GetLocation ($4)); |
|
} |
|
| primary_expression OPEN_BRACKET_EXPR expression_list_arguments error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2)); |
|
} |
|
| primary_expression OPEN_BRACKET_EXPR error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new ElementAccess ((Expression) $1, null, GetLocation ($2)); |
|
} |
|
; |
|
|
|
expression_list |
|
: expression |
|
{ |
|
var list = new List<Expression> (4); |
|
list.Add ((Expression) $1); |
|
$$ = list; |
|
} |
|
| expression_list COMMA expression |
|
{ |
|
var list = (List<Expression>) $1; |
|
list.Add ((Expression) $3); |
|
lbag.AppendTo (list, GetLocation ($2)); |
|
$$ = list; |
|
} |
|
| expression_list error { |
|
Error_SyntaxError (yyToken); |
|
$$ = $1; |
|
} |
|
; |
|
|
|
expression_list_arguments |
|
: expression_list_argument |
|
{ |
|
Arguments args = new Arguments (4); |
|
args.Add ((Argument) $1); |
|
$$ = args; |
|
} |
|
| expression_list_arguments COMMA expression_list_argument |
|
{ |
|
Arguments args = (Arguments) $1; |
|
if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) |
|
Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); |
|
|
|
args.Add ((Argument) $3); |
|
lbag.AppendTo (args, GetLocation ($2)); |
|
$$ = args; |
|
} |
|
; |
|
|
|
expression_list_argument |
|
: expression |
|
{ |
|
$$ = new Argument ((Expression) $1); |
|
} |
|
| named_argument |
|
; |
|
|
|
this_access |
|
: THIS |
|
{ |
|
$$ = new This (GetLocation ($1)); |
|
} |
|
; |
|
|
|
base_access |
|
: BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET |
|
{ |
|
$$ = new ElementAccess (new BaseThis (GetLocation ($1)), (Arguments) $3, GetLocation ($2)); |
|
lbag.AddLocation ($$, GetLocation ($4)); |
|
} |
|
| BASE OPEN_BRACKET error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new ElementAccess (null, null, GetLocation ($2)); |
|
} |
|
; |
|
|
|
post_increment_expression |
|
: primary_expression OP_INC |
|
{ |
|
$$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) $1, GetLocation ($2)); |
|
} |
|
; |
|
|
|
post_decrement_expression |
|
: primary_expression OP_DEC |
|
{ |
|
$$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) $1, GetLocation ($2)); |
|
} |
|
; |
|
|
|
object_or_delegate_creation_expression |
|
: NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer |
|
{ |
|
if ($6 != null) { |
|
if (lang_version <= LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "object initializers"); |
|
|
|
$$ = new NewInitialize ((FullNamedExpression) $2, (Arguments) $4, (CollectionOrObjectInitializers) $6, GetLocation ($1)); |
|
} else { |
|
$$ = new New ((FullNamedExpression) $2, (Arguments) $4, GetLocation ($1)); |
|
} |
|
|
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); |
|
} |
|
| NEW new_expr_type object_or_collection_initializer |
|
{ |
|
if (lang_version <= LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "collection initializers"); |
|
|
|
$$ = new NewInitialize ((FullNamedExpression) $2, null, (CollectionOrObjectInitializers) $3, GetLocation ($1)); |
|
} |
|
; |
|
|
|
array_creation_expression |
|
: NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET |
|
opt_rank_specifier |
|
opt_array_initializer |
|
{ |
|
$$ = new ArrayCreation ((FullNamedExpression) $2, (List<Expression>) $4, |
|
new ComposedTypeSpecifier (((List<Expression>) $4).Count, GetLocation ($3)) { |
|
Next = (ComposedTypeSpecifier) $6 |
|
}, (ArrayInitializer) $7, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); |
|
} |
|
| NEW new_expr_type rank_specifiers opt_array_initializer |
|
{ |
|
if ($4 == null) |
|
report.Error (1586, GetLocation ($1), "Array creation must have array size or array initializer"); |
|
|
|
$$ = new ArrayCreation ((FullNamedExpression) $2, (ComposedTypeSpecifier) $3, (ArrayInitializer) $4, GetLocation ($1)); |
|
} |
|
| NEW rank_specifier array_initializer |
|
{ |
|
if (lang_version <= LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "implicitly typed arrays"); |
|
|
|
$$ = new ImplicitlyTypedArrayCreation ((ComposedTypeSpecifier) $2, (ArrayInitializer) $3, GetLocation ($1)); |
|
} |
|
| NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET |
|
{ |
|
report.Error (178, GetLocation ($6), "Invalid rank specifier, expecting `,' or `]'"); |
|
$$ = new ArrayCreation ((FullNamedExpression) $2, null, GetLocation ($1)); |
|
} |
|
| NEW new_expr_type error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
// It can be any of new expression, create the most common one |
|
$$ = new New ((FullNamedExpression) $2, null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
new_expr_type |
|
: { |
|
++lexer.parsing_type; |
|
} |
|
simple_type |
|
{ |
|
--lexer.parsing_type; |
|
$$ = $2; |
|
} |
|
; |
|
|
|
anonymous_type_expression |
|
: NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE |
|
{ |
|
if (lang_version <= LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "anonymous types"); |
|
|
|
$$ = new NewAnonymousType ((List<AnonymousTypeParameter>) $3, current_container, GetLocation ($1)); |
|
|
|
// TODO: lbag comma location |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
; |
|
|
|
anonymous_type_parameters_opt_comma |
|
: anonymous_type_parameters_opt |
|
| anonymous_type_parameters COMMA |
|
; |
|
|
|
anonymous_type_parameters_opt |
|
: { $$ = null; } |
|
| anonymous_type_parameters |
|
; |
|
|
|
anonymous_type_parameters |
|
: anonymous_type_parameter |
|
{ |
|
var a = new List<AnonymousTypeParameter> (4); |
|
a.Add ((AnonymousTypeParameter) $1); |
|
$$ = a; |
|
} |
|
| anonymous_type_parameters COMMA anonymous_type_parameter |
|
{ |
|
var a = (List<AnonymousTypeParameter>) $1; |
|
a.Add ((AnonymousTypeParameter) $3); |
|
lbag.AppendTo (a, GetLocation ($2)); |
|
|
|
$$ = a; |
|
} |
|
; |
|
|
|
anonymous_type_parameter |
|
: IDENTIFIER ASSIGN variable_initializer |
|
{ |
|
var lt = (Tokenizer.LocatedToken)$1; |
|
$$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken)$1; |
|
$$ = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), |
|
lt.Value, lt.Location); |
|
} |
|
| member_access |
|
{ |
|
MemberAccess ma = (MemberAccess) $1; |
|
$$ = new AnonymousTypeParameter (ma, ma.Name, ma.Location); |
|
} |
|
| error |
|
{ |
|
report.Error (746, lexer.Location, |
|
"Invalid anonymous type member declarator. Anonymous type members must be a member assignment, simple name or member access expression"); |
|
$$ = null; |
|
} |
|
; |
|
|
|
opt_rank_specifier |
|
: /* empty */ |
|
| rank_specifiers |
|
; |
|
|
|
rank_specifiers |
|
: rank_specifier |
|
| rank_specifier rank_specifiers |
|
{ |
|
((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; |
|
$$ = $1; |
|
} |
|
; |
|
|
|
rank_specifier |
|
: OPEN_BRACKET CLOSE_BRACKET |
|
{ |
|
$$ = ComposedTypeSpecifier.CreateArrayDimension (1, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| OPEN_BRACKET dim_separators CLOSE_BRACKET |
|
{ |
|
$$ = ComposedTypeSpecifier.CreateArrayDimension ((int)$2, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3)); |
|
} |
|
; |
|
|
|
dim_separators |
|
: COMMA |
|
{ |
|
$$ = 2; |
|
} |
|
| dim_separators COMMA |
|
{ |
|
$$ = ((int) $1) + 1; |
|
} |
|
; |
|
|
|
opt_array_initializer |
|
: /* empty */ |
|
{ |
|
$$ = null; |
|
} |
|
| array_initializer |
|
{ |
|
$$ = $1; |
|
} |
|
; |
|
|
|
array_initializer |
|
: OPEN_BRACE CLOSE_BRACE |
|
{ |
|
var ai = new ArrayInitializer (0, GetLocation ($1)); |
|
ai.VariableDeclaration = current_variable; |
|
lbag.AddLocation (ai, GetLocation ($2)); |
|
$$ = ai; |
|
} |
|
| OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE |
|
{ |
|
var ai = new ArrayInitializer ((List<Expression>) $2, GetLocation ($1)); |
|
ai.VariableDeclaration = current_variable; |
|
if ($3 != null) { |
|
lbag.AddLocation (ai, GetLocation ($3), GetLocation ($4)); |
|
} else { |
|
lbag.AddLocation (ai, GetLocation ($4)); |
|
} |
|
$$ = ai; |
|
} |
|
; |
|
|
|
variable_initializer_list |
|
: variable_initializer |
|
{ |
|
var list = new List<Expression> (4); |
|
list.Add ((Expression) $1); |
|
$$ = list; |
|
} |
|
| variable_initializer_list COMMA variable_initializer |
|
{ |
|
var list = (List<Expression>) $1; |
|
list.Add ((Expression) $3); |
|
lbag.AppendTo (list, GetLocation ($2)); |
|
$$ = list; |
|
} |
|
; |
|
|
|
typeof_expression |
|
: TYPEOF |
|
{ |
|
lexer.TypeOfParsing = true; |
|
} |
|
open_parens_any typeof_type_expression CLOSE_PARENS |
|
{ |
|
lexer.TypeOfParsing = false; |
|
$$ = new TypeOf ((FullNamedExpression) $4, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); |
|
} |
|
; |
|
|
|
typeof_type_expression |
|
: type_and_void |
|
| unbound_type_name |
|
| error |
|
{ |
|
Error_TypeExpected (lexer.Location); |
|
$$ = null; |
|
} |
|
; |
|
|
|
unbound_type_name |
|
: identifier_inside_body generic_dimension |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
|
|
$$ = new SimpleName (lt.Value, (int) $2, lt.Location); |
|
} |
|
| qualified_alias_member identifier_inside_body generic_dimension |
|
{ |
|
var lt1 = (Tokenizer.LocatedToken) $1; |
|
var lt2 = (Tokenizer.LocatedToken) $2; |
|
|
|
$$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) $3, lt1.Location); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| unbound_type_name DOT identifier_inside_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
|
|
$$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location) { |
|
DotLocation = GetLocation ($2) |
|
}; |
|
} |
|
| unbound_type_name DOT identifier_inside_body generic_dimension |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
|
|
$$ = new MemberAccess ((Expression) $1, lt.Value, (int) $4, lt.Location) { |
|
DotLocation = GetLocation ($2) |
|
}; |
|
} |
|
| namespace_or_type_expr DOT identifier_inside_body generic_dimension |
|
{ |
|
var tne = (ATypeNameExpression) $1; |
|
if (tne.HasTypeArguments) |
|
Error_TypeExpected (GetLocation ($4)); |
|
|
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberAccess (tne, lt.Value, (int) $4, lt.Location) { |
|
DotLocation = GetLocation ($2) |
|
}; |
|
} |
|
; |
|
|
|
generic_dimension |
|
: GENERIC_DIMENSION |
|
{ |
|
if (lang_version < LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "generics"); |
|
|
|
$$ = $1; |
|
} |
|
; |
|
|
|
qualified_alias_member |
|
: IDENTIFIER DOUBLE_COLON |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
if (lang_version == LanguageVersion.ISO_1) |
|
FeatureIsNotAvailable (lt.Location, "namespace alias qualifier"); |
|
|
|
$$ = lt; |
|
} |
|
; |
|
|
|
sizeof_expression |
|
: SIZEOF open_parens_any type CLOSE_PARENS |
|
{ |
|
$$ = new SizeOf ((Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
; |
|
|
|
checked_expression |
|
: CHECKED open_parens_any expression CLOSE_PARENS |
|
{ |
|
$$ = new CheckedExpr ((Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
; |
|
|
|
unchecked_expression |
|
: UNCHECKED open_parens_any expression CLOSE_PARENS |
|
{ |
|
$$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
; |
|
|
|
pointer_member_access |
|
: primary_expression OP_PTR IDENTIFIER opt_type_argument_list |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberAccess (new Indirection ((Expression) $1, GetLocation ($2)), lt.Value, (TypeArguments) $4, lt.Location); |
|
} |
|
; |
|
|
|
anonymous_method_expression |
|
: DELEGATE opt_anonymous_method_signature |
|
{ |
|
start_anonymous (false, (ParametersCompiled) $2, false, GetLocation ($1)); |
|
} |
|
block |
|
{ |
|
$$ = end_anonymous ((ParametersBlock) $4); |
|
if ((ParametersCompiled) $2 != ParametersCompiled.Undefined) { |
|
lbag.AddLocation ($$, GetLocation ($1), savedOpenLocation, savedCloseLocation); |
|
} else { |
|
lbag.AddLocation ($$, GetLocation ($1)); |
|
} |
|
} |
|
| ASYNC DELEGATE opt_anonymous_method_signature |
|
{ |
|
start_anonymous (false, (ParametersCompiled) $3, true, GetLocation ($1)); |
|
} |
|
block |
|
{ |
|
$$ = end_anonymous ((ParametersBlock) $5); |
|
|
|
if ((ParametersCompiled) $3 != ParametersCompiled.Undefined) { |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), savedOpenLocation, savedCloseLocation); |
|
} else { |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2)); |
|
} |
|
} |
|
; |
|
|
|
opt_anonymous_method_signature |
|
: |
|
{ |
|
$$ = ParametersCompiled.Undefined; |
|
} |
|
| anonymous_method_signature |
|
; |
|
|
|
anonymous_method_signature |
|
: OPEN_PARENS |
|
{ |
|
valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; |
|
} |
|
opt_formal_parameter_list CLOSE_PARENS |
|
{ |
|
valid_param_mod = 0; |
|
$$ = $3; |
|
savedOpenLocation = GetLocation ($1); |
|
savedCloseLocation = GetLocation ($2); |
|
} |
|
; |
|
|
|
default_value_expression |
|
: DEFAULT open_parens_any type CLOSE_PARENS |
|
{ |
|
if (lang_version < LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($1), "default value expression"); |
|
|
|
$$ = new DefaultValueExpression ((Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
; |
|
|
|
unary_expression |
|
: primary_expression |
|
| BANG prefixed_unary_expression |
|
{ |
|
$$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, GetLocation ($1)); |
|
} |
|
| TILDE prefixed_unary_expression |
|
{ |
|
$$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, GetLocation ($1)); |
|
} |
|
| OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression |
|
{ |
|
$$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3)); |
|
} |
|
| AWAIT prefixed_unary_expression |
|
{ |
|
if (!async_block) { |
|
if (current_anonymous_method is LambdaExpression) { |
|
report.Error (4034, GetLocation ($1), |
|
"The `await' operator can only be used when its containing lambda expression is marked with the `async' modifier"); |
|
} else if (current_anonymous_method is AnonymousMethodExpression) { |
|
report.Error (4035, GetLocation ($1), |
|
"The `await' operator can only be used when its containing anonymous method is marked with the `async' modifier"); |
|
} else { |
|
report.Error (4033, GetLocation ($1), |
|
"The `await' operator can only be used when its containing method is marked with the `async' modifier"); |
|
} |
|
} else { |
|
current_block.Explicit.RegisterAsyncAwait (); |
|
} |
|
|
|
$$ = new Await ((Expression) $2, GetLocation ($1)); |
|
} |
|
; |
|
|
|
// |
|
// The idea to split this out is from Rhys' grammar |
|
// to solve the problem with casts. |
|
// |
|
prefixed_unary_expression |
|
: unary_expression |
|
| PLUS prefixed_unary_expression |
|
{ |
|
$$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, GetLocation ($1)); |
|
} |
|
| MINUS prefixed_unary_expression |
|
{ |
|
$$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, GetLocation ($1)); |
|
} |
|
| OP_INC prefixed_unary_expression |
|
{ |
|
$$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) $2, GetLocation ($1)); |
|
} |
|
| OP_DEC prefixed_unary_expression |
|
{ |
|
$$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) $2, GetLocation ($1)); |
|
} |
|
| STAR prefixed_unary_expression |
|
{ |
|
$$ = new Indirection ((Expression) $2, GetLocation ($1)); |
|
} |
|
| BITWISE_AND prefixed_unary_expression |
|
{ |
|
$$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, GetLocation ($1)); |
|
} |
|
; |
|
|
|
multiplicative_expression |
|
: prefixed_unary_expression |
|
| multiplicative_expression STAR prefixed_unary_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.Multiply, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| multiplicative_expression DIV prefixed_unary_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.Division, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| multiplicative_expression PERCENT prefixed_unary_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.Modulus, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
additive_expression |
|
: multiplicative_expression |
|
| additive_expression PLUS multiplicative_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.Addition, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| additive_expression MINUS multiplicative_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| additive_expression AS type |
|
{ |
|
$$ = new As ((Expression) $1, (Expression) $3, GetLocation ($2)); |
|
} |
|
| additive_expression IS type |
|
{ |
|
$$ = new Is ((Expression) $1, (Expression) $3, GetLocation ($2)); |
|
} |
|
; |
|
|
|
shift_expression |
|
: additive_expression |
|
| shift_expression OP_SHIFT_LEFT additive_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.LeftShift, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| shift_expression OP_SHIFT_RIGHT additive_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.RightShift, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
relational_expression |
|
: shift_expression |
|
| relational_expression OP_LT shift_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.LessThan, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| relational_expression OP_GT shift_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.GreaterThan, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| relational_expression OP_LE shift_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.LessThanOrEqual, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| relational_expression OP_GE shift_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.GreaterThanOrEqual, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
equality_expression |
|
: relational_expression |
|
| equality_expression OP_EQ relational_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.Equality, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| equality_expression OP_NE relational_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.Inequality, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
and_expression |
|
: equality_expression |
|
| and_expression BITWISE_AND equality_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
exclusive_or_expression |
|
: and_expression |
|
| exclusive_or_expression CARRET and_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
inclusive_or_expression |
|
: exclusive_or_expression |
|
| inclusive_or_expression BITWISE_OR exclusive_or_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
conditional_and_expression |
|
: inclusive_or_expression |
|
| conditional_and_expression OP_AND inclusive_or_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.LogicalAnd, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
conditional_or_expression |
|
: conditional_and_expression |
|
| conditional_or_expression OP_OR conditional_and_expression |
|
{ |
|
$$ = new Binary (Binary.Operator.LogicalOr, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
null_coalescing_expression |
|
: conditional_or_expression |
|
| conditional_or_expression OP_COALESCING null_coalescing_expression |
|
{ |
|
if (lang_version < LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (GetLocation ($2), "null coalescing operator"); |
|
|
|
$$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
conditional_expression |
|
: null_coalescing_expression |
|
| null_coalescing_expression INTERR expression COLON expression_or_error |
|
{ |
|
$$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2)); |
|
lbag.AddLocation ($$, GetLocation ($4)); |
|
} |
|
| null_coalescing_expression INTERR expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); |
|
} |
|
; |
|
|
|
assignment_expression |
|
: prefixed_unary_expression ASSIGN expression |
|
{ |
|
$$ = new SimpleAssign ((Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_MULT_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.Multiply, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_DIV_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.Division, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_MOD_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.Modulus, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_ADD_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.Addition, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_SUB_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.LeftShift, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.RightShift, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_AND_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_OR_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| prefixed_unary_expression OP_XOR_ASSIGN expression |
|
{ |
|
$$ = new CompoundAssign (Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
lambda_parameter_list |
|
: lambda_parameter |
|
{ |
|
var pars = new List<Parameter> (4); |
|
pars.Add ((Parameter) $1); |
|
parameterListCommas.Clear (); |
|
$$ = pars; |
|
} |
|
| lambda_parameter_list COMMA lambda_parameter |
|
{ |
|
var pars = (List<Parameter>) $1; |
|
Parameter p = (Parameter)$3; |
|
if (pars[0].GetType () != p.GetType ()) { |
|
report.Error (748, p.Location, "All lambda parameters must be typed either explicitly or implicitly"); |
|
} |
|
|
|
pars.Add (p); |
|
parameterListCommas.Add (GetLocation ($2)); |
|
|
|
$$ = pars; |
|
} |
|
; |
|
|
|
lambda_parameter |
|
: parameter_modifier parameter_type identifier_inside_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
|
|
$$ = new Parameter ((FullNamedExpression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location); |
|
} |
|
| parameter_type identifier_inside_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
|
|
$$ = new Parameter ((FullNamedExpression) $1, lt.Value, Parameter.Modifier.NONE, null, lt.Location); |
|
} |
|
| IDENTIFIER |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
$$ = new ImplicitLambdaParameter (lt.Value, lt.Location); |
|
} |
|
; |
|
|
|
opt_lambda_parameter_list |
|
: /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } |
|
| lambda_parameter_list { |
|
var pars_list = (List<Parameter>) $1; |
|
$$ = new ParametersCompiled (pars_list.ToArray ()); |
|
lbag.AddLocation ($$, parameterListCommas); |
|
} |
|
; |
|
|
|
lambda_expression_body |
|
: lambda_expression_body_simple |
|
| block |
|
; |
|
|
|
lambda_expression_body_simple |
|
: { |
|
start_block (Location.Null); |
|
} |
|
expression_or_error // Have to close block when error occurs |
|
{ |
|
Block b = end_block (Location.Null); |
|
b.IsCompilerGenerated = true; |
|
b.AddStatement (new ContextualReturn ((Expression) $2)); |
|
$$ = b; |
|
} |
|
; |
|
|
|
expression_or_error |
|
: expression |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = EmptyExpression.Null; |
|
} |
|
; |
|
|
|
lambda_expression |
|
: IDENTIFIER ARROW |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); |
|
start_anonymous (true, new ParametersCompiled (p), false, lt.Location); |
|
} |
|
lambda_expression_body |
|
{ |
|
$$ = end_anonymous ((ParametersBlock) $4); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| ASYNC identifier_inside_body ARROW |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); |
|
start_anonymous (true, new ParametersCompiled (p), true, lt.Location); |
|
} |
|
lambda_expression_body |
|
{ |
|
$$ = end_anonymous ((ParametersBlock) $5); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); |
|
} |
|
| OPEN_PARENS_LAMBDA |
|
{ |
|
valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; |
|
} |
|
opt_lambda_parameter_list CLOSE_PARENS ARROW |
|
{ |
|
valid_param_mod = 0; |
|
start_anonymous (true, (ParametersCompiled) $3, false, GetLocation ($1)); |
|
} |
|
lambda_expression_body |
|
{ |
|
$$ = end_anonymous ((ParametersBlock) $7); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($4), GetLocation ($5)); |
|
} |
|
| ASYNC OPEN_PARENS_LAMBDA |
|
{ |
|
valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; |
|
} |
|
opt_lambda_parameter_list CLOSE_PARENS ARROW |
|
{ |
|
valid_param_mod = 0; |
|
start_anonymous (true, (ParametersCompiled) $4, true, GetLocation ($1)); |
|
} |
|
lambda_expression_body |
|
{ |
|
$$ = end_anonymous ((ParametersBlock) $8); |
|
lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($5), GetLocation ($6)); |
|
} |
|
; |
|
|
|
expression |
|
: assignment_expression |
|
| non_assignment_expression |
|
; |
|
|
|
non_assignment_expression |
|
: conditional_expression |
|
| lambda_expression |
|
| query_expression |
|
| ARGLIST |
|
{ |
|
$$ = new ArglistAccess (GetLocation ($1)); |
|
} |
|
; |
|
|
|
undocumented_expressions |
|
: REFVALUE OPEN_PARENS non_assignment_expression COMMA type CLOSE_PARENS |
|
{ |
|
$$ = new RefValueExpr ((Expression) $3, (FullNamedExpression) $5, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); |
|
} |
|
| REFTYPE open_parens_any expression CLOSE_PARENS |
|
{ |
|
$$ = new RefTypeExpr ((Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| MAKEREF open_parens_any expression CLOSE_PARENS |
|
{ |
|
$$ = new MakeRefExpr ((Expression) $3, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
; |
|
|
|
constant_expression |
|
: expression |
|
; |
|
|
|
boolean_expression |
|
: expression |
|
{ |
|
$$ = new BooleanExpression ((Expression) $1); |
|
} |
|
; |
|
|
|
// |
|
// 10 classes |
|
// |
|
class_declaration |
|
: opt_attributes |
|
opt_modifiers |
|
opt_partial |
|
CLASS |
|
{ |
|
lexer.ConstraintsParsing = true; |
|
} |
|
type_declaration_name |
|
{ |
|
Class c = new Class (current_container, (MemberName) $6, (Modifiers) $2, (Attributes) $1); |
|
if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { |
|
FeatureIsNotAvailable (c.Location, "static classes"); |
|
} |
|
|
|
push_current_container (c, $3); |
|
lbag.AddMember (current_container, GetModifierLocations (), GetLocation ($4)); |
|
} |
|
opt_class_base |
|
opt_type_parameter_constraints_clauses |
|
{ |
|
lexer.ConstraintsParsing = false; |
|
|
|
if ($9 != null) |
|
current_container.SetConstraints ((List<Constraints>) $9); |
|
|
|
if (doc_support) { |
|
current_container.PartialContainer.DocComment = Lexer.consume_doc_comment (); |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
|
|
lexer.parsing_modifiers = true; |
|
} |
|
OPEN_BRACE opt_class_member_declarations CLOSE_BRACE |
|
{ |
|
--lexer.parsing_declaration; |
|
if (doc_support) |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
} |
|
opt_semicolon |
|
{ |
|
if ($15 == null) { |
|
lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13)); |
|
} else { |
|
lbag.AppendToMember (current_container, GetLocation ($11), GetLocation ($13), GetLocation ($15)); |
|
} |
|
$$ = pop_current_class (); |
|
} |
|
; |
|
|
|
opt_partial |
|
: /* empty */ |
|
{ $$ = null; } |
|
| PARTIAL |
|
{ $$ = $1; StoreModifierLocation (Modifiers.PARTIAL, GetLocation ($1)); } // location |
|
; |
|
|
|
opt_modifiers |
|
: /* empty */ |
|
{ |
|
mod_locations = null; |
|
$$ = ModifierNone; |
|
lexer.parsing_modifiers = false; |
|
} |
|
| modifiers |
|
{ |
|
lexer.parsing_modifiers = false; |
|
} |
|
; |
|
|
|
modifiers |
|
: modifier |
|
| modifiers modifier |
|
{ |
|
var m1 = (Modifiers) $1; |
|
var m2 = (Modifiers) $2; |
|
|
|
if ((m1 & m2) != 0) { |
|
report.Error (1004, lexer.Location - ModifiersExtensions.Name (m2).Length, |
|
"Duplicate `{0}' modifier", ModifiersExtensions.Name (m2)); |
|
} else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0 && |
|
((m2 | m1 & Modifiers.AccessibilityMask) != (Modifiers.PROTECTED | Modifiers.INTERNAL))) { |
|
report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, |
|
"More than one protection modifier specified"); |
|
} |
|
|
|
$$ = m1 | m2; |
|
} |
|
; |
|
|
|
modifier |
|
: NEW |
|
{ |
|
$$ = Modifiers.NEW; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
|
|
if (current_container.Kind == MemberKind.Namespace) |
|
report.Error (1530, GetLocation ($1), "Keyword `new' is not allowed on namespace elements"); |
|
} |
|
| PUBLIC |
|
{ |
|
$$ = Modifiers.PUBLIC; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| PROTECTED |
|
{ |
|
$$ = Modifiers.PROTECTED; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| INTERNAL |
|
{ |
|
$$ = Modifiers.INTERNAL; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| PRIVATE |
|
{ |
|
$$ = Modifiers.PRIVATE; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| ABSTRACT |
|
{ |
|
$$ = Modifiers.ABSTRACT; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| SEALED |
|
{ |
|
$$ = Modifiers.SEALED; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| STATIC |
|
{ |
|
$$ = Modifiers.STATIC; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| READONLY |
|
{ |
|
$$ = Modifiers.READONLY; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| VIRTUAL |
|
{ |
|
$$ = Modifiers.VIRTUAL; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| OVERRIDE |
|
{ |
|
$$ = Modifiers.OVERRIDE; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| EXTERN |
|
{ |
|
$$ = Modifiers.EXTERN; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| VOLATILE |
|
{ |
|
$$ = Modifiers.VOLATILE; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
| UNSAFE |
|
{ |
|
$$ = Modifiers.UNSAFE; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
if (!settings.Unsafe) |
|
Error_UnsafeCodeNotAllowed (GetLocation ($1)); |
|
} |
|
| ASYNC |
|
{ |
|
$$ = Modifiers.ASYNC; |
|
StoreModifierLocation ($$, GetLocation ($1)); |
|
} |
|
; |
|
|
|
opt_class_base |
|
: /* empty */ |
|
| COLON type_list |
|
{ |
|
current_type.AddBasesForPart ((List<FullNamedExpression>) $2); |
|
lbag.AppendToMember (current_type, GetLocation ($1)); |
|
} |
|
| COLON type_list error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
current_type.AddBasesForPart ((List<FullNamedExpression>) $2); |
|
} |
|
; |
|
|
|
opt_type_parameter_constraints_clauses |
|
: /* empty */ |
|
| type_parameter_constraints_clauses |
|
{ |
|
$$ = $1; |
|
} |
|
; |
|
|
|
type_parameter_constraints_clauses |
|
: type_parameter_constraints_clause |
|
{ |
|
var constraints = new List<Constraints> (1); |
|
constraints.Add ((Constraints) $1); |
|
$$ = constraints; |
|
} |
|
| type_parameter_constraints_clauses type_parameter_constraints_clause |
|
{ |
|
var constraints = (List<Constraints>) $1; |
|
Constraints new_constraint = (Constraints)$2; |
|
|
|
foreach (Constraints c in constraints) { |
|
if (new_constraint.TypeParameter.Value == c.TypeParameter.Value) { |
|
report.Error (409, new_constraint.Location, |
|
"A constraint clause has already been specified for type parameter `{0}'", |
|
new_constraint.TypeParameter.Value); |
|
} |
|
} |
|
|
|
constraints.Add (new_constraint); |
|
$$ = constraints; |
|
} |
|
; |
|
|
|
type_parameter_constraints_clause |
|
: WHERE IDENTIFIER COLON type_parameter_constraints |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List<FullNamedExpression>) $4, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3)); |
|
} |
|
| WHERE IDENTIFIER error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new Constraints (new SimpleMemberName (lt.Value, lt.Location), null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
type_parameter_constraints |
|
: type_parameter_constraint |
|
{ |
|
var constraints = new List<FullNamedExpression> (1); |
|
constraints.Add ((FullNamedExpression) $1); |
|
$$ = constraints; |
|
} |
|
| type_parameter_constraints COMMA type_parameter_constraint |
|
{ |
|
var constraints = (List<FullNamedExpression>) $1; |
|
var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; |
|
if (prev != null && (prev.Constraint & SpecialConstraint.Constructor) != 0) { |
|
report.Error (401, GetLocation ($2), "The `new()' constraint must be the last constraint specified"); |
|
} |
|
|
|
prev = $3 as SpecialContraintExpr; |
|
if (prev != null) { |
|
if ((prev.Constraint & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) { |
|
report.Error (449, prev.Location, "The `class' or `struct' constraint must be the first constraint specified"); |
|
} else { |
|
prev = constraints [0] as SpecialContraintExpr; |
|
if (prev != null && (prev.Constraint & SpecialConstraint.Struct) != 0) { |
|
report.Error (451, GetLocation ($3), "The `new()' constraint cannot be used with the `struct' constraint"); |
|
} |
|
} |
|
} |
|
|
|
constraints.Add ((FullNamedExpression) $3); |
|
lbag.AppendTo (constraints, GetLocation ($2)); |
|
$$ = constraints; |
|
} |
|
; |
|
|
|
type_parameter_constraint |
|
: type |
|
{ |
|
if ($1 is ComposedCast) |
|
report.Error (706, GetLocation ($1), "Invalid constraint type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); |
|
|
|
$$ = $1; |
|
} |
|
| NEW OPEN_PARENS CLOSE_PARENS |
|
{ |
|
$$ = new SpecialContraintExpr (SpecialConstraint.Constructor, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); |
|
} |
|
| CLASS |
|
{ |
|
$$ = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation ($1)); |
|
} |
|
| STRUCT |
|
{ |
|
$$ = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation ($1)); |
|
} |
|
; |
|
|
|
opt_type_parameter_variance |
|
: /* empty */ |
|
{ |
|
$$ = Variance.None; |
|
} |
|
| type_parameter_variance |
|
{ |
|
if (lang_version <= LanguageVersion.V_3) |
|
FeatureIsNotAvailable (lexer.Location, "generic type variance"); |
|
|
|
$$ = $1; |
|
} |
|
; |
|
|
|
type_parameter_variance |
|
: OUT |
|
{ |
|
$$ = Variance.Covariant; |
|
savedLocation = GetLocation ($1); |
|
} |
|
| IN |
|
{ |
|
$$ = Variance.Contravariant; |
|
savedLocation = GetLocation ($1); |
|
} |
|
; |
|
|
|
// |
|
// 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 |
|
{ |
|
++lexer.parsing_block; |
|
start_block (GetLocation ($1)); |
|
} |
|
opt_statement_list block_end |
|
{ |
|
$$ = $4; |
|
} |
|
; |
|
|
|
block_end |
|
: CLOSE_BRACE |
|
{ |
|
--lexer.parsing_block; |
|
$$ = end_block (GetLocation ($1)); |
|
} |
|
| COMPLETE_COMPLETION |
|
{ |
|
--lexer.parsing_block; |
|
$$ = end_block (lexer.Location); |
|
} |
|
; |
|
|
|
|
|
block_prepared |
|
: OPEN_BRACE |
|
{ |
|
++lexer.parsing_block; |
|
current_block.StartLocation = GetLocation ($1); |
|
} |
|
opt_statement_list CLOSE_BRACE |
|
{ |
|
--lexer.parsing_block; |
|
$$ = end_block (GetLocation ($4)); |
|
} | CLOSE_BRACE |
|
{ |
|
report.Error (1525, GetLocation ($1), "Unexpected symbol '}', expected '{'"); |
|
lexer.putback ('}'); |
|
$$ = end_block (GetLocation ($1)); |
|
} |
|
; |
|
|
|
opt_statement_list |
|
: /* empty */ |
|
| statement_list |
|
; |
|
|
|
statement_list |
|
: statement |
|
| statement_list statement |
|
; |
|
|
|
statement |
|
: block_variable_declaration |
|
{ |
|
current_block.AddStatement ((Statement) $1); |
|
} |
|
| valid_declaration_statement |
|
{ |
|
current_block.AddStatement ((Statement) $1); |
|
} |
|
| labeled_statement |
|
// WORKAROUND:Remove that rule, if it is >really< fixed. |
|
| IDENTIFIER error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
var lt =(Tokenizer.LocatedToken) $1; |
|
var sn = new SimpleName (lt.Value, lt.Location); |
|
current_block.AddStatement(new StatementErrorExpression (sn)); |
|
$$ = null; |
|
} |
|
//////// |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = null; |
|
} |
|
; |
|
|
|
// |
|
// The interactive_statement and its derivatives are only |
|
// used to provide a special version of `expression_statement' |
|
// that has a side effect of assigning the expression to |
|
// $retval |
|
// |
|
interactive_statement_list |
|
: interactive_statement |
|
| interactive_statement_list interactive_statement |
|
; |
|
|
|
interactive_statement |
|
: block_variable_declaration |
|
{ |
|
current_block.AddStatement ((Statement) $1); |
|
} |
|
| interactive_valid_declaration_statement |
|
{ |
|
current_block.AddStatement ((Statement) $1); |
|
} |
|
| labeled_statement |
|
; |
|
|
|
valid_declaration_statement |
|
: block |
|
| empty_statement |
|
| expression_statement |
|
| selection_statement |
|
| iteration_statement |
|
| jump_statement |
|
| try_statement |
|
| checked_statement |
|
| unchecked_statement |
|
| lock_statement |
|
| using_statement |
|
| unsafe_statement |
|
| fixed_statement |
|
; |
|
|
|
interactive_valid_declaration_statement |
|
: block |
|
| empty_statement |
|
| interactive_expression_statement |
|
| selection_statement |
|
| iteration_statement |
|
| jump_statement |
|
| try_statement |
|
| checked_statement |
|
| unchecked_statement |
|
| lock_statement |
|
| using_statement |
|
| unsafe_statement |
|
| fixed_statement |
|
; |
|
|
|
embedded_statement |
|
: valid_declaration_statement |
|
| block_variable_declaration |
|
{ |
|
report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); |
|
$$ = null; |
|
} |
|
| labeled_statement |
|
{ |
|
report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); |
|
$$ = null; |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new EmptyStatement (GetLocation ($1)); |
|
} |
|
; |
|
|
|
empty_statement |
|
: SEMICOLON |
|
{ |
|
// Uses lexer.Location because semicolon location is not kept in quick mode |
|
$$ = new EmptyStatement (lexer.Location); |
|
} |
|
; |
|
|
|
labeled_statement |
|
: identifier_inside_body COLON |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); |
|
lbag.AddLocation (labeled, GetLocation ($2)); |
|
current_block.AddLabel (labeled); |
|
current_block.AddStatement (labeled); |
|
} |
|
statement |
|
; |
|
|
|
variable_type |
|
: variable_type_simple |
|
| variable_type_simple rank_specifiers |
|
{ |
|
if ($1 is VarExpr) |
|
$1 = new SimpleName ("var", ((VarExpr) $1).Location); |
|
|
|
$$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); |
|
} |
|
; |
|
|
|
/* |
|
* 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. |
|
*/ |
|
variable_type_simple |
|
: primary_expression_or_type opt_nullable |
|
{ |
|
// 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 namespace_or_type_name (which is all we need |
|
// really) two shift/reduces appear. |
|
// |
|
|
|
// So the super-trick is that primary_expression |
|
// can only be either a SimpleName or a MemberAccess. |
|
// The MemberAccess case arises when you have a fully qualified type-name like : |
|
// Foo.Bar.Blah i; |
|
// SimpleName is when you have |
|
// Blah i; |
|
|
|
Expression expr = (Expression) $1; |
|
if ($2 == null) { |
|
SimpleName sn = expr as SimpleName; |
|
if (sn != null && sn.Name == "var") |
|
$$ = new VarExpr (sn.Location); |
|
else |
|
$$ = $1; |
|
} else if (expr is ATypeNameExpression) { |
|
$$ = new ComposedCast ((ATypeNameExpression)expr, (ComposedTypeSpecifier) $2); |
|
} else { |
|
Error_ExpectingTypeName (expr); |
|
$$ = null; |
|
} |
|
} |
|
| primary_expression_or_type pointer_stars |
|
{ |
|
ATypeNameExpression expr = $1 as ATypeNameExpression; |
|
|
|
if (expr != null) { |
|
$$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); |
|
} else { |
|
Error_ExpectingTypeName ((Expression)$1); |
|
$$ = expr; |
|
} |
|
} |
|
| builtin_types opt_nullable |
|
{ |
|
if ($2 == null) |
|
$$ = $1; |
|
else |
|
$$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); |
|
} |
|
| builtin_types pointer_stars |
|
{ |
|
$$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); |
|
} |
|
| VOID pointer_stars |
|
{ |
|
$$ = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)), (ComposedTypeSpecifier) $2); |
|
} |
|
| VOID |
|
{ |
|
Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); |
|
$$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); |
|
} |
|
; |
|
|
|
pointer_stars |
|
: pointer_star |
|
| pointer_star pointer_stars |
|
{ |
|
((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; |
|
$$ = $1; |
|
} |
|
; |
|
|
|
pointer_star |
|
: STAR |
|
{ |
|
$$ = ComposedTypeSpecifier.CreatePointer (GetLocation ($1)); |
|
} |
|
; |
|
|
|
identifier_inside_body |
|
: IDENTIFIER |
|
| AWAIT |
|
{ |
|
if (async_block) { |
|
report.Error (4003, GetLocation ($1), "`await' cannot be used as an identifier within an async method or lambda expression"); |
|
$$ = new Tokenizer.LocatedToken ("await", GetLocation ($1)); |
|
} |
|
} |
|
; |
|
|
|
block_variable_declaration |
|
: variable_type identifier_inside_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var li = new LocalVariable (current_block, lt.Value, lt.Location); |
|
current_block.AddLocalName (li); |
|
current_variable = new BlockVariableDeclaration ((FullNamedExpression) $1, li); |
|
} |
|
opt_local_variable_initializer opt_variable_declarators semicolon_or_handle_error_close_brace |
|
{ |
|
$$ = current_variable; |
|
current_variable = null; |
|
lbag.AppendTo ($$, GetLocation ($6)); |
|
} |
|
| CONST variable_type identifier_inside_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); |
|
current_block.AddLocalName (li); |
|
current_variable = new BlockConstantDeclaration ((FullNamedExpression) $2, li); |
|
} |
|
const_variable_initializer opt_const_declarators SEMICOLON |
|
{ |
|
if (current_variable.Initializer != null) { |
|
lbag.AddLocation (current_variable, GetLocation ($1), savedLocation, GetLocation ($7)); |
|
} else { |
|
lbag.AddLocation (current_variable, GetLocation ($1), GetLocation ($7)); |
|
} |
|
$$ = current_variable;; |
|
current_variable = null; |
|
} |
|
; |
|
|
|
semicolon_or_handle_error_close_brace |
|
: SEMICOLON |
|
| CLOSE_BRACE { |
|
// Redundant, but wont regress |
|
report.Error (1525, lexer.Location, "Unexpected symbol }"); |
|
lexer.putback ('}'); |
|
$$ = $1; |
|
} |
|
; |
|
|
|
opt_local_variable_initializer |
|
: /* empty */ |
|
| ASSIGN block_variable_initializer |
|
{ |
|
current_variable.Initializer = (Expression) $2; |
|
lbag.AppendTo (current_variable, GetLocation ($1)); |
|
} |
|
| ASSIGN error |
|
{ |
|
if (yyToken == Token.OPEN_BRACKET_EXPR) { |
|
report.Error (650, lexer.Location, |
|
"Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type"); |
|
current_variable.Initializer = ErrorExpression.Create (650, lexer.Location, |
|
"Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type"); |
|
} else { |
|
Error_SyntaxError (yyToken); |
|
current_variable.Initializer = ErrorExpression.Create (0, lexer.Location, |
|
"Syntax error"); |
|
} |
|
lbag.AppendTo (current_variable, GetLocation ($1)); |
|
} |
|
| error |
|
{ |
|
if (yyToken == Token.OPEN_BRACKET_EXPR) { |
|
report.Error (650, lexer.Location, |
|
"Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type"); |
|
} else { |
|
Error_SyntaxError (yyToken); |
|
} |
|
} |
|
; |
|
|
|
opt_variable_declarators |
|
: /* empty */ |
|
| variable_declarators |
|
; |
|
|
|
opt_using_or_fixed_variable_declarators |
|
: /* empty */ |
|
| variable_declarators |
|
{ |
|
foreach (var d in current_variable.Declarators) { |
|
if (d.Initializer == null) |
|
Error_MissingInitializer (d.Variable.Location); |
|
} |
|
} |
|
; |
|
|
|
variable_declarators |
|
: variable_declarator |
|
| variable_declarators variable_declarator |
|
; |
|
|
|
variable_declarator |
|
: COMMA identifier_inside_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); |
|
var d = new BlockVariableDeclaration.Declarator (li, null); |
|
current_variable.AddDeclarator (d); |
|
current_block.AddLocalName (li); |
|
lbag.AddLocation (d, GetLocation ($1)); |
|
} |
|
| COMMA identifier_inside_body ASSIGN block_variable_initializer |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); |
|
var d = new BlockVariableDeclaration.Declarator (li, (Expression) $4); |
|
current_variable.AddDeclarator (d); |
|
current_block.AddLocalName (li); |
|
lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); |
|
} |
|
; |
|
|
|
const_variable_initializer |
|
: /* empty */ |
|
{ |
|
report.Error (145, lexer.Location, "A const field requires a value to be provided"); |
|
} |
|
| ASSIGN constant_initializer_expr |
|
{ |
|
savedLocation = GetLocation ($1); |
|
current_variable.Initializer = (Expression) $2; |
|
} |
|
; |
|
|
|
opt_const_declarators |
|
: /* empty */ |
|
| const_declarators |
|
; |
|
|
|
const_declarators |
|
: const_declarator |
|
| const_declarators const_declarator |
|
; |
|
|
|
const_declarator |
|
: COMMA identifier_inside_body ASSIGN constant_initializer_expr |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); |
|
var d = new BlockVariableDeclaration.Declarator (li, (Expression) $4); |
|
current_variable.AddDeclarator (d); |
|
current_block.AddLocalName (li); |
|
lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); |
|
} |
|
; |
|
|
|
block_variable_initializer |
|
: variable_initializer |
|
| STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET |
|
{ |
|
$$ = new StackAlloc ((Expression) $2, (Expression) $4, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); |
|
} |
|
| STACKALLOC simple_type |
|
{ |
|
report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type"); |
|
$$ = new StackAlloc ((Expression) $2, null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
expression_statement |
|
: statement_expression SEMICOLON |
|
{ |
|
$$ = $1; |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
| statement_expression COMPLETE_COMPLETION { $$ = $1; } |
|
| statement_expression CLOSE_BRACE |
|
{ |
|
$$ = $1; |
|
report.Error (1002, GetLocation ($2), "; expected"); |
|
lexer.putback ('}'); |
|
} |
|
; |
|
|
|
interactive_expression_statement |
|
: interactive_statement_expression SEMICOLON { $$ = $1; } |
|
| interactive_statement_expression COMPLETE_COMPLETION { $$ = $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 |
|
: expression |
|
{ |
|
ExpressionStatement s = $1 as ExpressionStatement; |
|
if (s == null) { |
|
Expression.Error_InvalidExpressionStatement (report, GetLocation ($1)); |
|
$$ = new StatementErrorExpression ($1 as Expression); |
|
} else { |
|
$$ = new StatementExpression (s); |
|
} |
|
} |
|
; |
|
|
|
interactive_statement_expression |
|
: expression |
|
{ |
|
Expression expr = (Expression) $1; |
|
ExpressionStatement s; |
|
|
|
s = new OptionalAssign (new SimpleName ("$retval", lexer.Location), expr, lexer.Location); |
|
$$ = new StatementExpression (s); |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new EmptyStatement (GetLocation ($1)); |
|
} |
|
; |
|
|
|
selection_statement |
|
: if_statement |
|
| switch_statement |
|
; |
|
|
|
if_statement |
|
: IF open_parens_any boolean_expression CLOSE_PARENS |
|
embedded_statement |
|
{ |
|
if ($5 is EmptyStatement) |
|
Warning_EmptyStatement (GetLocation ($5)); |
|
|
|
$$ = new If ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| IF open_parens_any boolean_expression CLOSE_PARENS |
|
embedded_statement ELSE embedded_statement |
|
{ |
|
$$ = new If ((BooleanExpression) $3, (Statement) $5, (Statement) $7, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); |
|
|
|
if ($5 is EmptyStatement) |
|
Warning_EmptyStatement (GetLocation ($5)); |
|
if ($7 is EmptyStatement) |
|
Warning_EmptyStatement (GetLocation ($7)); |
|
} |
|
| IF open_parens_any boolean_expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new If ((BooleanExpression) $3, null, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
switch_statement |
|
: SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE |
|
{ |
|
start_block (GetLocation ($5)); |
|
} |
|
opt_switch_sections CLOSE_BRACE |
|
{ |
|
$$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, (List<SwitchSection>) $7, GetLocation ($1)); |
|
end_block (GetLocation ($8)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4), GetLocation ($5), GetLocation ($8)); |
|
} |
|
| SWITCH open_parens_any expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new Switch ((Expression) $3, null, null, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
opt_switch_sections |
|
: /* empty */ |
|
{ |
|
report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); |
|
$$ = new List<SwitchSection> (); |
|
} |
|
| switch_sections |
|
; |
|
|
|
switch_sections |
|
: switch_section |
|
{ |
|
var sections = new List<SwitchSection> (4); |
|
|
|
sections.Add ((SwitchSection) $1); |
|
$$ = sections; |
|
} |
|
| switch_sections switch_section |
|
{ |
|
var sections = (List<SwitchSection>) $1; |
|
|
|
sections.Add ((SwitchSection) $2); |
|
$$ = sections; |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new List<SwitchSection> (); |
|
} |
|
; |
|
|
|
switch_section |
|
: switch_labels |
|
{ |
|
current_block = current_block.CreateSwitchBlock (lexer.Location); |
|
} |
|
statement_list |
|
{ |
|
$$ = new SwitchSection ((List<SwitchLabel>) $1, current_block); |
|
} |
|
; |
|
|
|
switch_labels |
|
: switch_label |
|
{ |
|
var labels = new List<SwitchLabel> (2); |
|
|
|
labels.Add ((SwitchLabel) $1); |
|
$$ = labels; |
|
} |
|
| switch_labels switch_label |
|
{ |
|
var labels = (List<SwitchLabel>) ($1); |
|
labels.Add ((SwitchLabel) $2); |
|
|
|
$$ = labels; |
|
} |
|
; |
|
|
|
switch_label |
|
: CASE constant_expression COLON |
|
{ |
|
$$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3)); |
|
} |
|
| CASE constant_expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); |
|
} |
|
| DEFAULT_COLON |
|
{ |
|
$$ = new SwitchLabel (null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
iteration_statement |
|
: while_statement |
|
| do_statement |
|
| for_statement |
|
| foreach_statement |
|
; |
|
|
|
while_statement |
|
: WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement |
|
{ |
|
if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) |
|
Warning_EmptyStatement (GetLocation ($5)); |
|
|
|
$$ = new While ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| WHILE open_parens_any boolean_expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new While ((BooleanExpression) $3, null, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
do_statement |
|
: DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON |
|
{ |
|
$$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1), GetLocation ($3)); |
|
lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4), GetLocation ($6), GetLocation ($7)); |
|
} |
|
| DO embedded_statement error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new Do ((Statement) $2, null, GetLocation ($1), Location.Null); |
|
} |
|
| DO embedded_statement WHILE open_parens_any boolean_expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1), GetLocation ($3)); |
|
lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4)); |
|
} |
|
; |
|
|
|
for_statement |
|
: FOR open_parens_any |
|
{ |
|
start_block (GetLocation ($2)); |
|
current_block.IsCompilerGenerated = true; |
|
For f = new For (GetLocation ($1)); |
|
current_block.AddStatement (f); |
|
lbag.AddStatement (f, current_block.StartLocation); |
|
$$ = f; |
|
} |
|
for_statement_cont |
|
{ |
|
$$ = $4; |
|
} |
|
; |
|
|
|
// Has to use be extra rule to recover started block |
|
for_statement_cont |
|
: opt_for_initializer SEMICOLON |
|
{ |
|
For f = (For) $0; |
|
f.Initializer = (Statement) $1; |
|
lbag.AppendTo (f, GetLocation ($2)); |
|
$$ = f; |
|
} |
|
for_statement_condition |
|
{ |
|
$$ = $4; |
|
} |
|
| opt_for_initializer CLOSE_PARENS { |
|
report.Error (1525, GetLocation ($2), "Unexpected symbol ')', expected ';'"); |
|
For f = (For) $0; |
|
f.Initializer = (Statement) $1; |
|
lbag.AppendTo (f, GetLocation ($2)); |
|
$$ = end_block (GetLocation ($2)); |
|
} |
|
; |
|
|
|
for_statement_condition |
|
: opt_for_condition SEMICOLON |
|
{ |
|
For f = (For) $0; |
|
f.Condition = (BooleanExpression) $1; |
|
lbag.AppendTo (f, GetLocation ($2)); |
|
$$ = f; |
|
} |
|
for_statement_end |
|
{ |
|
$$ = $4; |
|
} |
|
|
|
| boolean_expression CLOSE_PARENS { |
|
report.Error (1525, GetLocation ($2), "Unexpected symbol ')', expected ';'"); |
|
For f = (For) $0; |
|
f.Condition = (BooleanExpression) $1; |
|
lbag.AppendTo (f, GetLocation ($2)); |
|
$$ = end_block (GetLocation ($2)); |
|
} |
|
; |
|
|
|
for_statement_end |
|
: opt_for_iterator CLOSE_PARENS |
|
embedded_statement |
|
{ |
|
For f = (For) $0; |
|
f.Iterator = (Statement) $1; |
|
|
|
if ($3 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) |
|
Warning_EmptyStatement (GetLocation ($3)); |
|
|
|
f.Statement = (Statement) $3; |
|
lbag.AppendTo (f, GetLocation ($2)); |
|
|
|
$$ = end_block (GetLocation ($2)); |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = end_block (current_block.StartLocation); |
|
} |
|
; |
|
|
|
opt_for_initializer |
|
: /* empty */ { $$ = new EmptyStatement (lexer.Location); } |
|
| for_initializer |
|
; |
|
|
|
for_initializer |
|
: variable_type identifier_inside_body |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var li = new LocalVariable (current_block, lt.Value, lt.Location); |
|
current_block.AddLocalName (li); |
|
current_variable = new BlockVariableDeclaration ((FullNamedExpression) $1, li); |
|
} |
|
opt_local_variable_initializer opt_variable_declarators |
|
{ |
|
$$ = current_variable; |
|
current_variable = null; |
|
} |
|
| statement_expression_list |
|
; |
|
|
|
opt_for_condition |
|
: /* empty */ { $$ = null; } |
|
| boolean_expression |
|
; |
|
|
|
opt_for_iterator |
|
: /* empty */ { $$ = new EmptyStatement (lexer.Location); } |
|
| for_iterator |
|
; |
|
|
|
for_iterator |
|
: statement_expression_list |
|
; |
|
|
|
statement_expression_list |
|
: statement_expression |
|
| statement_expression_list COMMA statement_expression |
|
{ |
|
var sl = $1 as StatementList; |
|
if (sl == null) { |
|
sl = new StatementList ((Statement) $1, (Statement) $3); |
|
lbag.AddStatement (sl, GetLocation ($2)); |
|
} else { |
|
sl.Add ((Statement) $3); |
|
lbag.AppendTo (sl, GetLocation ($2)); |
|
|
|
} |
|
|
|
$$ = sl; |
|
} |
|
; |
|
|
|
foreach_statement |
|
: FOREACH open_parens_any type error |
|
{ |
|
report.Error (230, GetLocation ($1), "Type and identifier are both required in a foreach statement"); |
|
|
|
start_block (GetLocation ($2)); |
|
current_block.IsCompilerGenerated = true; |
|
|
|
Foreach f = new Foreach ((Expression) $3, null, null, null, null, GetLocation ($1)); |
|
current_block.AddStatement (f); |
|
|
|
lbag.AddStatement (f, GetLocation ($2)); |
|
$$ = end_block (GetLocation ($4)); |
|
} |
|
| FOREACH open_parens_any type identifier_inside_body error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
start_block (GetLocation ($2)); |
|
current_block.IsCompilerGenerated = true; |
|
|
|
var lt = (Tokenizer.LocatedToken) $4; |
|
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); |
|
current_block.AddLocalName (li); |
|
|
|
Foreach f = new Foreach ((Expression) $3, li, null, null, null, GetLocation ($1)); |
|
current_block.AddStatement (f); |
|
|
|
lbag.AddStatement (f, GetLocation ($2)); |
|
$$ = end_block (GetLocation ($5)); |
|
} |
|
| FOREACH open_parens_any type identifier_inside_body IN expression CLOSE_PARENS |
|
{ |
|
start_block (GetLocation ($2)); |
|
current_block.IsCompilerGenerated = true; |
|
var lt = (Tokenizer.LocatedToken) $4; |
|
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); |
|
current_block.AddLocalName (li); |
|
$$ = li; |
|
} |
|
embedded_statement |
|
{ |
|
if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) |
|
Warning_EmptyStatement (GetLocation ($9)); |
|
|
|
Foreach f = new Foreach ((Expression) $3, (LocalVariable) $8, (Expression) $6, (Statement) $9, current_block, GetLocation ($1)); |
|
lbag.AddStatement (f, GetLocation ($2), GetLocation ($5), GetLocation ($7)); |
|
end_block (GetLocation ($7)); |
|
|
|
$$ = f; |
|
} |
|
| FOREACH open_parens_any type identifier_inside_body error |
|
{ |
|
start_block (GetLocation ($2)); |
|
current_block.IsCompilerGenerated = true; |
|
var lt = $4 as Tokenizer.LocatedToken; |
|
var li = lt != null ? new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location) : null; |
|
|
|
Foreach f = new Foreach ((Expression) $3, li, null, null, null, GetLocation ($1)); |
|
current_block.AddStatement (f); |
|
|
|
lbag.AddStatement (f, GetLocation ($2)); |
|
$$ = end_block (GetLocation ($5)); |
|
} |
|
| FOREACH open_parens_any type error |
|
{ |
|
Foreach f = new Foreach ((Expression) $3, null, null, null, null, GetLocation ($1)); |
|
current_block.AddStatement (f); |
|
|
|
lbag.AddStatement (f, GetLocation ($2)); |
|
$$ = f; |
|
} |
|
; |
|
|
|
jump_statement |
|
: break_statement |
|
| continue_statement |
|
| goto_statement |
|
| return_statement |
|
| throw_statement |
|
| yield_statement |
|
; |
|
|
|
break_statement |
|
: BREAK SEMICOLON |
|
{ |
|
$$ = new Break (GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
continue_statement |
|
: CONTINUE SEMICOLON |
|
{ |
|
$$ = new Continue (GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
| CONTINUE error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new Continue (GetLocation ($1)); |
|
} |
|
; |
|
|
|
goto_statement |
|
: GOTO identifier_inside_body SEMICOLON |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
$$ = new Goto (lt.Value, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); |
|
} |
|
| GOTO CASE constant_expression SEMICOLON |
|
{ |
|
$$ = new GotoCase ((Expression) $3, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| GOTO DEFAULT SEMICOLON |
|
{ |
|
$$ = new GotoDefault (GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); |
|
} |
|
; |
|
|
|
return_statement |
|
: RETURN opt_expression SEMICOLON |
|
{ |
|
$$ = new Return ((Expression) $2, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($3)); |
|
} |
|
| RETURN expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new Return ((Expression) $2, GetLocation ($1)); |
|
} |
|
| RETURN error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new Return (null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
throw_statement |
|
: THROW opt_expression SEMICOLON |
|
{ |
|
$$ = new Throw ((Expression) $2, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($3)); |
|
} |
|
| THROW error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = new Throw (null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
yield_statement |
|
: identifier_inside_body RETURN opt_expression SEMICOLON |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
string s = lt.Value; |
|
if (s != "yield"){ |
|
report.Error (1003, lt.Location, "; expected"); |
|
} else if ($3 == null) { |
|
report.Error (1627, GetLocation ($4), "Expression expected after yield return"); |
|
} else if (lang_version == LanguageVersion.ISO_1){ |
|
FeatureIsNotAvailable (lt.Location, "iterators"); |
|
} |
|
|
|
current_block.Explicit.RegisterIteratorYield (); |
|
$$ = new Yield ((Expression) $3, lt.Location); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| identifier_inside_body RETURN expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
var lt = (Tokenizer.LocatedToken) $1; |
|
string s = lt.Value; |
|
if (s != "yield"){ |
|
report.Error (1003, lt.Location, "; expected"); |
|
} else if ($3 == null) { |
|
report.Error (1627, GetLocation ($4), "Expression expected after yield return"); |
|
} else if (lang_version == LanguageVersion.ISO_1){ |
|
FeatureIsNotAvailable (lt.Location, "iterators"); |
|
} |
|
|
|
current_block.Explicit.RegisterIteratorYield (); |
|
$$ = new Yield ((Expression) $3, lt.Location); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
| identifier_inside_body BREAK SEMICOLON |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $1; |
|
string s = lt.Value; |
|
if (s != "yield"){ |
|
report.Error (1003, lt.Location, "; expected"); |
|
} else if (lang_version == LanguageVersion.ISO_1){ |
|
FeatureIsNotAvailable (lt.Location, "iterators"); |
|
} |
|
|
|
current_block.Explicit.RegisterIteratorYield (); |
|
$$ = new YieldBreak (lt.Location); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); |
|
} |
|
; |
|
|
|
opt_expression |
|
: /* empty */ |
|
| expression |
|
; |
|
|
|
try_statement |
|
: TRY block catch_clauses |
|
{ |
|
$$ = new TryCatch ((Block) $2, (List<Catch>) $3, GetLocation ($1), false); |
|
} |
|
| TRY block FINALLY block |
|
{ |
|
$$ = new TryFinally ((Statement) $2, (Block) $4, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($3)); |
|
} |
|
| TRY block catch_clauses FINALLY block |
|
{ |
|
var loc = GetLocation ($1); |
|
$$ = new TryFinally (new TryCatch ((Block) $2, (List<Catch>) $3, loc, true), (Block) $5, loc); |
|
lbag.AddStatement ($$, GetLocation ($4)); |
|
} |
|
| TRY block error |
|
{ |
|
Error_SyntaxError (1524, yyToken); |
|
$$ = new TryCatch ((Block) $2, null, GetLocation ($1), false); |
|
} |
|
; |
|
|
|
catch_clauses |
|
: catch_clause |
|
{ |
|
var l = new List<Catch> (2); |
|
|
|
l.Add ((Catch) $1); |
|
$$ = l; |
|
} |
|
| catch_clauses catch_clause |
|
{ |
|
var l = (List<Catch>) $1; |
|
|
|
Catch c = (Catch) $2; |
|
if (l [l.Count - 1].IsGeneral) { |
|
report.Error (1017, c.loc, "Try statement already has an empty catch block"); |
|
} |
|
|
|
l.Add (c); |
|
$$ = l; |
|
} |
|
; |
|
|
|
opt_identifier |
|
: /* empty */ |
|
| identifier_inside_body |
|
; |
|
|
|
catch_clause |
|
: CATCH block |
|
{ |
|
$$ = new Catch ((Block) $2, GetLocation ($1)); |
|
} |
|
| CATCH open_parens_any type opt_identifier CLOSE_PARENS |
|
{ |
|
start_block (GetLocation ($2)); |
|
var c = new Catch (current_block, GetLocation ($1)); |
|
c.TypeExpression = (FullNamedExpression) $3; |
|
|
|
if ($4 != null) { |
|
var lt = (Tokenizer.LocatedToken) $4; |
|
c.Variable = new LocalVariable (current_block, lt.Value, lt.Location); |
|
current_block.AddLocalName (c.Variable); |
|
} |
|
|
|
lbag.AddLocation (c, GetLocation ($2), GetLocation ($5)); |
|
$$ = c; |
|
} |
|
block_prepared |
|
{ |
|
$$ = $6; |
|
} |
|
| CATCH open_parens_any error |
|
{ |
|
if (yyToken == Token.CLOSE_PARENS) { |
|
report.Error (1015, lexer.Location, |
|
"A type that derives from `System.Exception', `object', or `string' expected"); |
|
} else { |
|
Error_SyntaxError (yyToken); |
|
} |
|
|
|
$$ = new Catch (null, GetLocation ($1)); |
|
} |
|
; |
|
|
|
checked_statement |
|
: CHECKED block |
|
{ |
|
$$ = new Checked ((Block) $2, GetLocation ($1)); |
|
} |
|
; |
|
|
|
unchecked_statement |
|
: UNCHECKED block |
|
{ |
|
$$ = new Unchecked ((Block) $2, GetLocation ($1)); |
|
} |
|
; |
|
|
|
unsafe_statement |
|
: UNSAFE |
|
{ |
|
if (!settings.Unsafe) |
|
Error_UnsafeCodeNotAllowed (GetLocation ($1)); |
|
} block { |
|
$$ = new Unsafe ((Block) $3, GetLocation ($1)); |
|
} |
|
; |
|
|
|
lock_statement |
|
: LOCK open_parens_any expression CLOSE_PARENS embedded_statement |
|
{ |
|
if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) |
|
Warning_EmptyStatement (GetLocation ($5)); |
|
|
|
$$ = new Lock ((Expression) $3, (Statement) $5, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| LOCK open_parens_any expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new Lock ((Expression) $3, null, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
fixed_statement |
|
: FIXED open_parens_any variable_type identifier_inside_body |
|
{ |
|
start_block (GetLocation ($2)); |
|
|
|
current_block.IsCompilerGenerated = true; |
|
var lt = (Tokenizer.LocatedToken) $4; |
|
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.FixedVariable | LocalVariable.Flags.Used, lt.Location); |
|
current_block.AddLocalName (li); |
|
current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) $3, li); |
|
} |
|
using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS |
|
{ |
|
$$ = current_variable; |
|
current_variable = null; |
|
} |
|
embedded_statement |
|
{ |
|
if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) |
|
Warning_EmptyStatement (GetLocation ($10)); |
|
|
|
Fixed f = new Fixed ((Fixed.VariableDeclaration) $9, (Statement) $10, GetLocation ($1)); |
|
current_block.AddStatement (f); |
|
lbag.AddStatement (f, GetLocation ($2), GetLocation ($8)); |
|
$$ = end_block (GetLocation ($8)); |
|
} |
|
; |
|
|
|
using_statement |
|
: USING open_parens_any variable_type identifier_inside_body |
|
{ |
|
start_block (GetLocation ($2)); |
|
|
|
current_block.IsCompilerGenerated = true; |
|
var lt = (Tokenizer.LocatedToken) $4; |
|
var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.UsingVariable | LocalVariable.Flags.Used, lt.Location); |
|
current_block.AddLocalName (li); |
|
current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li); |
|
} |
|
using_initialization CLOSE_PARENS |
|
{ |
|
$$ = current_variable; |
|
current_variable = null; |
|
} |
|
embedded_statement |
|
{ |
|
if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) |
|
Warning_EmptyStatement (GetLocation ($9)); |
|
|
|
Using u = new Using ((Using.VariableDeclaration) $8, (Statement) $9, GetLocation ($1)); |
|
lbag.AddStatement (u, GetLocation ($2), GetLocation ($7)); |
|
current_block.AddStatement (u); |
|
$$ = end_block (GetLocation ($7)); |
|
} |
|
| USING open_parens_any expression CLOSE_PARENS embedded_statement |
|
{ |
|
if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) |
|
Warning_EmptyStatement (GetLocation ($5)); |
|
|
|
$$ = new Using ((Expression) $3, (Statement) $5, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); |
|
} |
|
| USING open_parens_any expression error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
|
|
$$ = new Using ((Expression) $3, null, GetLocation ($1)); |
|
lbag.AddStatement ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
using_initialization |
|
: using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators |
|
| error |
|
{ |
|
// It has to be here for the parent to safely restore artificial block |
|
Error_SyntaxError (yyToken); |
|
} |
|
; |
|
|
|
using_or_fixed_variable_initializer |
|
: /* empty */ |
|
{ |
|
Error_MissingInitializer (lexer.Location); |
|
} |
|
| ASSIGN variable_initializer |
|
{ |
|
current_variable.Initializer = (Expression) $2; |
|
lbag.AppendTo (current_variable, GetLocation ($1)); |
|
$$ = current_variable; |
|
} |
|
; |
|
|
|
|
|
// LINQ |
|
|
|
query_expression |
|
: first_from_clause query_body |
|
{ |
|
lexer.query_parsing = false; |
|
|
|
Linq.AQueryClause from = $1 as Linq.AQueryClause; |
|
|
|
from.Tail.Next = (Linq.AQueryClause)$2; |
|
$$ = from; |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
} |
|
| nested_from_clause query_body |
|
{ |
|
Linq.AQueryClause from = $1 as Linq.AQueryClause; |
|
|
|
from.Tail.Next = (Linq.AQueryClause)$2; |
|
$$ = from; |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
} |
|
|
|
// Bubble up COMPLETE_COMPLETION productions |
|
| first_from_clause COMPLETE_COMPLETION { |
|
lexer.query_parsing = false; |
|
$$ = $1; |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
} |
|
| nested_from_clause COMPLETE_COMPLETION { |
|
$$ = $1; |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
} |
|
; |
|
|
|
first_from_clause |
|
: FROM_FIRST identifier_inside_body IN expression |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
|
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var rv = new Linq.RangeVariable (lt.Value, lt.Location); |
|
var start = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)); |
|
lbag.AddLocation (start, GetLocation ($3)); |
|
$$ = new Linq.QueryExpression (start); |
|
} |
|
| FROM_FIRST type identifier_inside_body IN expression |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
|
|
var lt = (Tokenizer.LocatedToken) $3; |
|
var rv = new Linq.RangeVariable (lt.Value, lt.Location); |
|
var start = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { |
|
IdentifierType = (FullNamedExpression)$2 |
|
}; |
|
lbag.AddLocation (start, GetLocation ($4)); |
|
$$ = new Linq.QueryExpression (start); |
|
} |
|
; |
|
|
|
nested_from_clause |
|
: FROM identifier_inside_body IN expression |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
|
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var rv = new Linq.RangeVariable (lt.Value, lt.Location); |
|
var start = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$4, rv, GetLocation ($1)); |
|
lbag.AddLocation (start, GetLocation ($3)); |
|
$$ = new Linq.QueryExpression (start); |
|
} |
|
| FROM type identifier_inside_body IN expression |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
|
|
var lt = (Tokenizer.LocatedToken) $3; |
|
var rv = new Linq.RangeVariable (lt.Value, lt.Location); |
|
var start = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { |
|
IdentifierType = (FullNamedExpression)$2 |
|
}; |
|
lbag.AddLocation (start, GetLocation ($4)); |
|
$$ = new Linq.QueryExpression (start); |
|
} |
|
; |
|
|
|
from_clause |
|
: FROM identifier_inside_body IN |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
expression_or_error |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var sn = new Linq.RangeVariable (lt.Value, lt.Location); |
|
$$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$5, GetLocation ($1)); |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
((Linq.QueryBlock)current_block).AddRangeVariable (sn); |
|
|
|
lbag.AddLocation ($$, GetLocation ($3)); |
|
} |
|
| FROM type identifier_inside_body IN |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
expression_or_error |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
var sn = new Linq.RangeVariable (lt.Value, lt.Location); |
|
|
|
$$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$6, GetLocation ($1)) { |
|
IdentifierType = (FullNamedExpression)$2 |
|
}; |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
((Linq.QueryBlock)current_block).AddRangeVariable (sn); |
|
|
|
lbag.AddLocation ($$, GetLocation ($4)); |
|
} |
|
; |
|
|
|
query_body |
|
: query_body_clauses select_or_group_clause opt_query_continuation |
|
{ |
|
Linq.AQueryClause head = (Linq.AQueryClause)$2; |
|
|
|
if ($3 != null) |
|
head.Next = (Linq.AQueryClause)$3; |
|
|
|
if ($1 != null) { |
|
Linq.AQueryClause clause = (Linq.AQueryClause)$1; |
|
clause.Tail.Next = head; |
|
head = clause; |
|
} |
|
|
|
$$ = head; |
|
} |
|
| select_or_group_clause opt_query_continuation |
|
{ |
|
Linq.AQueryClause head = (Linq.AQueryClause)$2; |
|
|
|
if ($1 != null) { |
|
Linq.AQueryClause clause = (Linq.AQueryClause)$1; |
|
clause.Tail.Next = head; |
|
head = clause; |
|
} |
|
|
|
$$ = head; |
|
} |
|
| query_body_clauses COMPLETE_COMPLETION |
|
| query_body_clauses error |
|
{ |
|
report.Error (742, GetLocation ($2), "Unexpected symbol `{0}'. A query body must end with select or group clause", GetSymbolName (yyToken)); |
|
$$ = $1; |
|
} |
|
| error |
|
{ |
|
Error_SyntaxError (yyToken); |
|
$$ = null; |
|
} |
|
; |
|
|
|
select_or_group_clause |
|
: SELECT |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
expression_or_error |
|
{ |
|
$$ = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
} |
|
| GROUP |
|
{ |
|
if (linq_clause_blocks == null) |
|
linq_clause_blocks = new Stack<Linq.QueryBlock> (); |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
linq_clause_blocks.Push ((Linq.QueryBlock)current_block); |
|
} |
|
expression_or_error |
|
{ |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
BY expression_or_error |
|
{ |
|
$$ = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)$3, linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($5)); |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
} |
|
; |
|
|
|
query_body_clauses |
|
: query_body_clause |
|
| query_body_clauses query_body_clause |
|
{ |
|
((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$2; |
|
$$ = $1; |
|
} |
|
; |
|
|
|
query_body_clause |
|
: from_clause |
|
| let_clause |
|
| where_clause |
|
| join_clause |
|
| orderby_clause |
|
; |
|
|
|
let_clause |
|
: LET identifier_inside_body ASSIGN |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
expression_or_error |
|
{ |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var sn = new Linq.RangeVariable (lt.Value, lt.Location); |
|
$$ = new Linq.Let ((Linq.QueryBlock) current_block, sn, (Expression)$5, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3)); |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
((Linq.QueryBlock)current_block).AddRangeVariable (sn); |
|
} |
|
; |
|
|
|
where_clause |
|
: WHERE |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
expression_or_error |
|
{ |
|
$$ = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); |
|
|
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
} |
|
; |
|
|
|
join_clause |
|
: JOIN identifier_inside_body IN |
|
{ |
|
if (linq_clause_blocks == null) |
|
linq_clause_blocks = new Stack<Linq.QueryBlock> (); |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
linq_clause_blocks.Push ((Linq.QueryBlock) current_block); |
|
} |
|
expression_or_error ON |
|
{ |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
linq_clause_blocks.Push ((Linq.QueryBlock) current_block); |
|
} |
|
expression_or_error EQUALS |
|
{ |
|
current_block.AddStatement (new ContextualReturn ((Expression) $8)); |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
expression_or_error opt_join_into |
|
{ |
|
current_block.AddStatement (new ContextualReturn ((Expression) $11)); |
|
current_block.SetEndLocation (lexer.Location); |
|
|
|
var outer_selector = linq_clause_blocks.Pop (); |
|
var block = linq_clause_blocks.Pop (); |
|
|
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var sn = new Linq.RangeVariable (lt.Value, lt.Location); |
|
Linq.RangeVariable into; |
|
|
|
if ($12 == null) { |
|
into = sn; |
|
$$ = new Linq.Join (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9)); |
|
} else { |
|
// |
|
// Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions |
|
// |
|
var parent = block.Parent; |
|
while (parent is Linq.QueryBlock) { |
|
parent = parent.Parent; |
|
} |
|
current_block.Parent = parent; |
|
|
|
((Linq.QueryBlock)current_block).AddRangeVariable (sn); |
|
|
|
lt = (Tokenizer.LocatedToken) $12; |
|
into = new Linq.RangeVariable (lt.Value, lt.Location); |
|
|
|
$$ = new Linq.GroupJoin (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)); |
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9), opt_intoStack.Pop ()); |
|
} |
|
|
|
current_block = block.Parent; |
|
((Linq.QueryBlock)current_block).AddRangeVariable (into); |
|
} |
|
| JOIN type identifier_inside_body IN |
|
{ |
|
if (linq_clause_blocks == null) |
|
linq_clause_blocks = new Stack<Linq.QueryBlock> (); |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
linq_clause_blocks.Push ((Linq.QueryBlock) current_block); |
|
} |
|
expression_or_error ON |
|
{ |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
linq_clause_blocks.Push ((Linq.QueryBlock) current_block); |
|
} |
|
expression_or_error EQUALS |
|
{ |
|
current_block.AddStatement (new ContextualReturn ((Expression) $9)); |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
expression_or_error opt_join_into |
|
{ |
|
current_block.AddStatement (new ContextualReturn ((Expression) $12)); |
|
current_block.SetEndLocation (lexer.Location); |
|
|
|
var outer_selector = linq_clause_blocks.Pop (); |
|
var block = linq_clause_blocks.Pop (); |
|
|
|
var lt = (Tokenizer.LocatedToken) $3; |
|
var sn = new Linq.RangeVariable (lt.Value, lt.Location); |
|
Linq.RangeVariable into; |
|
|
|
if ($13 == null) { |
|
into = sn; |
|
$$ = new Linq.Join (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)) { |
|
IdentifierType = (FullNamedExpression)$2 |
|
}; |
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9)); |
|
} else { |
|
// |
|
// Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions |
|
// |
|
var parent = block.Parent; |
|
while (parent is Linq.QueryBlock) { |
|
parent = parent.Parent; |
|
} |
|
current_block.Parent = parent; |
|
|
|
((Linq.QueryBlock)current_block).AddRangeVariable (sn); |
|
|
|
lt = (Tokenizer.LocatedToken) $13; |
|
into = new Linq.RangeVariable (lt.Value, lt.Location); // TODO: |
|
|
|
$$ = new Linq.GroupJoin (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)) { |
|
IdentifierType = (FullNamedExpression)$2 |
|
}; |
|
lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9), opt_intoStack.Pop ()); |
|
} |
|
|
|
current_block = block.Parent; |
|
((Linq.QueryBlock)current_block).AddRangeVariable (into); |
|
} |
|
; |
|
|
|
opt_join_into |
|
: /* empty */ |
|
| INTO identifier_inside_body |
|
{ |
|
opt_intoStack.Push (GetLocation ($1)); |
|
$$ = $2; |
|
} |
|
; |
|
|
|
orderby_clause |
|
: ORDERBY |
|
{ |
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
orderings |
|
{ |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
$$ = $3; |
|
} |
|
; |
|
|
|
orderings |
|
: order_by |
|
| order_by COMMA |
|
{ |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
} |
|
orderings_then_by |
|
{ |
|
((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$4; |
|
$$ = $1; |
|
} |
|
; |
|
|
|
orderings_then_by |
|
: then_by |
|
| orderings_then_by COMMA |
|
{ |
|
current_block.SetEndLocation (lexer.Location); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock ((Linq.QueryBlock) current_block, lexer.Location); |
|
} |
|
then_by |
|
{ |
|
((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$4; |
|
$$ = $1; |
|
} |
|
; |
|
|
|
order_by |
|
: expression |
|
{ |
|
$$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); |
|
} |
|
| expression ASCENDING |
|
{ |
|
$$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| expression DESCENDING |
|
{ |
|
$$ = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)$1); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
then_by |
|
: expression |
|
{ |
|
$$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); |
|
} |
|
| expression ASCENDING |
|
{ |
|
$$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
| expression DESCENDING |
|
{ |
|
$$ = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)$1); |
|
lbag.AddLocation ($$, GetLocation ($2)); |
|
} |
|
; |
|
|
|
|
|
opt_query_continuation |
|
: /* empty */ |
|
| INTO identifier_inside_body |
|
{ |
|
// query continuation block is not linked with query block but with block |
|
// before. This means each query can use same range variable names for |
|
// different identifiers. |
|
|
|
current_block.SetEndLocation (GetLocation ($1)); |
|
current_block = current_block.Parent; |
|
|
|
current_block = new Linq.QueryBlock (current_block, lexer.Location); |
|
|
|
if (linq_clause_blocks == null) |
|
linq_clause_blocks = new Stack<Linq.QueryBlock> (); |
|
|
|
linq_clause_blocks.Push ((Linq.QueryBlock) current_block); |
|
} |
|
query_body |
|
{ |
|
var current_block = linq_clause_blocks.Pop (); |
|
var lt = (Tokenizer.LocatedToken) $2; |
|
var rv = new Linq.RangeVariable (lt.Value, lt.Location); |
|
$$ = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, null, rv, GetLocation ($1)) { |
|
next = (Linq.AQueryClause)$4 |
|
}; |
|
} |
|
; |
|
|
|
// |
|
// Support for using the compiler as an interactive parser |
|
// |
|
// The INTERACTIVE_PARSER token is first sent to parse our |
|
// productions; If the result is a Statement, the parsing |
|
// is repeated, this time with INTERACTIVE_PARSE_WITH_BLOCK |
|
// to setup the blocks in advance. |
|
// |
|
// This setup is here so that in the future we can add |
|
// support for other constructs (type parsing, namespaces, etc) |
|
// that do not require a block to be setup in advance |
|
// |
|
|
|
interactive_parsing |
|
: EVAL_STATEMENT_PARSER EOF |
|
| EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives opt_COMPLETE_COMPLETION |
|
| EVAL_STATEMENT_PARSER |
|
{ |
|
current_container = current_type = new Class (current_container, new MemberName ("<InteractiveExpressionClass>"), Modifiers.PUBLIC, null); |
|
|
|
// (ref object retval) |
|
Parameter [] mpar = new Parameter [1]; |
|
mpar [0] = new Parameter (new TypeExpression (compiler.BuiltinTypes.Object, Location.Null), "$retval", Parameter.Modifier.REF, null, Location.Null); |
|
|
|
ParametersCompiled pars = new ParametersCompiled (mpar); |
|
var mods = Modifiers.PUBLIC | Modifiers.STATIC; |
|
if (settings.Unsafe) |
|
mods |= Modifiers.UNSAFE; |
|
|
|
current_local_parameters = pars; |
|
Method method = new Method ( |
|
current_type, |
|
new TypeExpression (compiler.BuiltinTypes.Void, Location.Null), |
|
mods, |
|
new MemberName ("Host"), |
|
pars, |
|
null /* attributes */); |
|
|
|
current_type.AddMember (method); |
|
|
|
oob_stack.Push (method); |
|
++lexer.parsing_block; |
|
start_block (lexer.Location); |
|
} |
|
interactive_statement_list opt_COMPLETE_COMPLETION |
|
{ |
|
--lexer.parsing_block; |
|
Method method = (Method) oob_stack.Pop (); |
|
|
|
method.Block = (ToplevelBlock) end_block(lexer.Location); |
|
|
|
InteractiveResult = (Class) pop_current_class (); |
|
current_local_parameters = null; |
|
} |
|
| EVAL_COMPILATION_UNIT_PARSER interactive_compilation_unit |
|
; |
|
|
|
interactive_compilation_unit |
|
: opt_extern_alias_directives opt_using_directives |
|
| opt_extern_alias_directives opt_using_directives namespace_or_type_declarations |
|
; |
|
|
|
opt_COMPLETE_COMPLETION |
|
: /* nothing */ |
|
| COMPLETE_COMPLETION |
|
; |
|
|
|
close_brace_or_complete_completion |
|
: CLOSE_BRACE |
|
| COMPLETE_COMPLETION |
|
; |
|
|
|
// |
|
// XML documentation code references micro parser |
|
// |
|
documentation_parsing |
|
: DOC_SEE doc_cref |
|
{ |
|
module.DocumentationBuilder.ParsedName = (MemberName) $2; |
|
} |
|
; |
|
|
|
doc_cref |
|
: doc_type_declaration_name opt_doc_method_sig |
|
{ |
|
module.DocumentationBuilder.ParsedParameters = (List<DocumentationParameter>)$2; |
|
} |
|
| builtin_types opt_doc_method_sig |
|
{ |
|
module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; |
|
module.DocumentationBuilder.ParsedParameters = (List<DocumentationParameter>)$2; |
|
$$ = null; |
|
} |
|
| builtin_types DOT IDENTIFIER opt_doc_method_sig |
|
{ |
|
module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; |
|
module.DocumentationBuilder.ParsedParameters = (List<DocumentationParameter>)$4; |
|
var lt = (Tokenizer.LocatedToken) $3; |
|
$$ = new MemberName (lt.Value); |
|
} |
|
| doc_type_declaration_name DOT THIS |
|
{ |
|
$$ = new MemberName ((MemberName) $1, MemberCache.IndexerNameAlias, Location.Null); |
|
} |
|
| doc_type_declaration_name DOT THIS OPEN_BRACKET |
|
{ |
|
valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; |
|
} |
|
opt_doc_parameters CLOSE_BRACKET |
|
{ |
|
module.DocumentationBuilder.ParsedParameters = (List<DocumentationParameter>)$6; |
|
$$ = new MemberName ((MemberName) $1, MemberCache.IndexerNameAlias, Location.Null); |
|
} |
|
| EXPLICIT OPERATOR type opt_doc_method_sig |
|
{ |
|
var p = (List<DocumentationParameter>)$4 ?? new List<DocumentationParameter> (1); |
|
p.Add (new DocumentationParameter ((FullNamedExpression) $3)); |
|
module.DocumentationBuilder.ParsedParameters = p; |
|
module.DocumentationBuilder.ParsedOperator = Operator.OpType.Explicit; |
|
$$ = null; |
|
} |
|
| IMPLICIT OPERATOR type opt_doc_method_sig |
|
{ |
|
var p = (List<DocumentationParameter>)$4 ?? new List<DocumentationParameter> (1); |
|
p.Add (new DocumentationParameter ((FullNamedExpression) $3)); |
|
module.DocumentationBuilder.ParsedParameters = p; |
|
module.DocumentationBuilder.ParsedOperator = Operator.OpType.Implicit; |
|
$$ = null; |
|
} |
|
| OPERATOR overloadable_operator opt_doc_method_sig |
|
{ |
|
var p = (List<DocumentationParameter>)$3 ?? new List<DocumentationParameter> (1); |
|
module.DocumentationBuilder.ParsedParameters = p; |
|
module.DocumentationBuilder.ParsedOperator = (Operator.OpType) $2; |
|
$$ = null; |
|
} |
|
; |
|
|
|
doc_type_declaration_name |
|
: type_declaration_name |
|
| doc_type_declaration_name DOT type_declaration_name |
|
{ |
|
$$ = new MemberName (((MemberName) $1), (MemberName) $3); |
|
} |
|
; |
|
|
|
opt_doc_method_sig |
|
: /* empty */ |
|
| OPEN_PARENS |
|
{ |
|
valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; |
|
} |
|
opt_doc_parameters CLOSE_PARENS |
|
{ |
|
$$ = $3; |
|
} |
|
; |
|
|
|
opt_doc_parameters |
|
: /* empty */ |
|
{ |
|
$$ = new List<DocumentationParameter> (0); |
|
} |
|
| doc_parameters |
|
; |
|
|
|
doc_parameters |
|
: doc_parameter |
|
{ |
|
var parameters = new List<DocumentationParameter> (); |
|
parameters.Add ((DocumentationParameter) $1); |
|
$$ = parameters; |
|
} |
|
| doc_parameters COMMA doc_parameter |
|
{ |
|
var parameters = $1 as List<DocumentationParameter>; |
|
parameters.Add ((DocumentationParameter) $3); |
|
$$ = parameters; |
|
} |
|
; |
|
|
|
doc_parameter |
|
: opt_parameter_modifier parameter_type |
|
{ |
|
if ($1 != null) |
|
$$ = new DocumentationParameter ((Parameter.Modifier) $1, (FullNamedExpression) $2); |
|
else |
|
$$ = new DocumentationParameter ((FullNamedExpression) $2); |
|
} |
|
; |
|
|
|
%% |
|
|
|
// <summary> |
|
// A class used to hold info about an operator declarator |
|
// </summary> |
|
class OperatorDeclaration { |
|
public readonly Operator.OpType optype; |
|
public readonly FullNamedExpression ret_type; |
|
public readonly Location location; |
|
|
|
public OperatorDeclaration (Operator.OpType op, FullNamedExpression ret_type, Location location) |
|
{ |
|
optype = op; |
|
this.ret_type = ret_type; |
|
this.location = location; |
|
} |
|
} |
|
|
|
void Error_ExpectingTypeName (Expression expr) |
|
{ |
|
if (expr is Invocation){ |
|
report.Error (1002, expr.Location, "Expecting `;'"); |
|
} else { |
|
Expression.Error_InvalidExpressionStatement (report, expr.Location); |
|
} |
|
} |
|
|
|
void Error_ParameterModifierNotValid (string modifier, Location loc) |
|
{ |
|
report.Error (631, loc, "The parameter modifier `{0}' is not valid in this context", |
|
modifier); |
|
} |
|
|
|
void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod) |
|
{ |
|
report.Error (1107, loc, "Duplicate parameter modifier `{0}'", |
|
Parameter.GetModifierSignature (mod)); |
|
} |
|
|
|
void Error_TypeExpected (Location loc) |
|
{ |
|
report.Error (1031, loc, "Type expected"); |
|
} |
|
|
|
void Error_UnsafeCodeNotAllowed (Location loc) |
|
{ |
|
report.Error (227, loc, "Unsafe code requires the `unsafe' command line option to be specified"); |
|
} |
|
|
|
void Warning_EmptyStatement (Location loc) |
|
{ |
|
report.Warning (642, 3, loc, "Possible mistaken empty statement"); |
|
} |
|
|
|
void Error_NamedArgumentExpected (NamedArgument a) |
|
{ |
|
report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); |
|
} |
|
|
|
void Error_MissingInitializer (Location loc) |
|
{ |
|
report.Error (210, loc, "You must provide an initializer in a fixed or using statement declaration"); |
|
} |
|
|
|
void push_current_container (TypeDefinition tc, object partial_token) |
|
{ |
|
if (module.Evaluator != null){ |
|
tc.Definition.Modifiers = tc.ModFlags = (tc.ModFlags & ~Modifiers.AccessibilityMask) | Modifiers.PUBLIC; |
|
if (undo == null) |
|
undo = new Undo (); |
|
|
|
undo.AddTypeContainer (current_container, tc); |
|
} |
|
|
|
if (partial_token != null) |
|
current_container.AddPartial (tc); |
|
else |
|
current_container.AddTypeContainer (tc); |
|
|
|
++lexer.parsing_declaration; |
|
current_container = tc; |
|
current_type = tc; |
|
} |
|
|
|
TypeContainer pop_current_class () |
|
{ |
|
var retval = current_container; |
|
|
|
current_container = current_container.Parent; |
|
current_type = current_type.Parent as TypeDefinition; |
|
|
|
return retval; |
|
} |
|
|
|
[System.Diagnostics.Conditional ("FULL_AST")] |
|
void StoreModifierLocation (object token, Location loc) |
|
{ |
|
if (lbag == null) |
|
return; |
|
|
|
if (mod_locations == null) |
|
mod_locations = new List<Tuple<Modifiers, Location>> (); |
|
|
|
mod_locations.Add (Tuple.Create ((Modifiers) token, loc)); |
|
} |
|
|
|
List<Tuple<Modifiers, Location>> GetModifierLocations () |
|
{ |
|
var result = mod_locations; |
|
mod_locations = null; |
|
return result; |
|
} |
|
|
|
string CheckAttributeTarget (string a, Location l) |
|
{ |
|
switch (a) { |
|
case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" : |
|
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; |
|
} |
|
|
|
static bool IsUnaryOperator (Operator.OpType op) |
|
{ |
|
switch (op) { |
|
|
|
case Operator.OpType.LogicalNot: |
|
case Operator.OpType.OnesComplement: |
|
case Operator.OpType.Increment: |
|
case Operator.OpType.Decrement: |
|
case Operator.OpType.True: |
|
case Operator.OpType.False: |
|
case Operator.OpType.UnaryPlus: |
|
case Operator.OpType.UnaryNegation: |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
void syntax_error (Location l, string msg) |
|
{ |
|
report.Error (1003, l, "Syntax error, " + msg); |
|
} |
|
|
|
Tokenizer lexer; |
|
|
|
public Tokenizer Lexer { |
|
get { |
|
return lexer; |
|
} |
|
} |
|
|
|
public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, ParserSession session) |
|
: this (reader, file, file.Compiler.Report, session) |
|
{ |
|
} |
|
|
|
public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, Report report, ParserSession session) |
|
{ |
|
this.file = file; |
|
current_container = current_namespace = file; |
|
|
|
this.module = file.Module; |
|
this.compiler = file.Compiler; |
|
this.settings = compiler.Settings; |
|
this.report = report; |
|
|
|
lang_version = settings.Version; |
|
yacc_verbose_flag = settings.VerboseParserFlag; |
|
doc_support = settings.DocumentationFile != null; |
|
lexer = new Tokenizer (reader, file, session); |
|
oob_stack = new Stack<object> (); |
|
lbag = session.LocationsBag; |
|
use_global_stacks = session.UseJayGlobalArrays; |
|
parameters_bucket = session.ParametersStack; |
|
} |
|
|
|
public void parse () |
|
{ |
|
eof_token = Token.EOF; |
|
|
|
try { |
|
if (yacc_verbose_flag > 1) |
|
yyparse (lexer, new yydebug.yyDebugSimple ()); |
|
else |
|
yyparse (lexer); |
|
|
|
Tokenizer tokenizer = lexer as Tokenizer; |
|
tokenizer.cleanup (); |
|
} catch (Exception e){ |
|
if (e is yyParser.yyUnexpectedEof) { |
|
Error_SyntaxError (yyToken); |
|
UnexpectedEOF = true; |
|
return; |
|
} |
|
|
|
if (e is yyParser.yyException) { |
|
report.Error (-25, lexer.Location, "Parsing error"); |
|
} else { |
|
// Used by compiler-tester to test internal errors |
|
if (yacc_verbose_flag > 0 || e is FatalException) |
|
throw; |
|
|
|
report.Error (589, lexer.Location, "Internal compiler error during parsing" + e); |
|
} |
|
} |
|
} |
|
|
|
void CheckToken (int error, int yyToken, string msg, Location loc) |
|
{ |
|
if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD) |
|
report.Error (error, loc, "{0}: `{1}' is a keyword", msg, GetTokenName (yyToken)); |
|
else |
|
report.Error (error, loc, msg); |
|
} |
|
|
|
string ConsumeStoredComment () |
|
{ |
|
string s = tmpComment; |
|
tmpComment = null; |
|
Lexer.doc_state = XmlCommentState.Allowed; |
|
return s; |
|
} |
|
|
|
void FeatureIsNotAvailable (Location loc, string feature) |
|
{ |
|
report.FeatureIsNotAvailable (compiler, loc, feature); |
|
} |
|
|
|
Location GetLocation (object obj) |
|
{ |
|
var lt = obj as Tokenizer.LocatedToken; |
|
if (lt != null) |
|
return lt.Location; |
|
|
|
var mn = obj as MemberName; |
|
if (mn != null) |
|
return mn.Location; |
|
|
|
var expr = obj as Expression; |
|
if (expr != null) |
|
return expr.Location; |
|
|
|
return lexer.Location; |
|
} |
|
|
|
void start_block (Location loc) |
|
{ |
|
if (current_block == null) { |
|
current_block = new ToplevelBlock (compiler, current_local_parameters, loc); |
|
parsing_anonymous_method = false; |
|
} else if (parsing_anonymous_method) { |
|
current_block = new ParametersBlock (current_block, current_local_parameters, 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 isLambda, ParametersCompiled parameters, bool isAsync, Location loc) |
|
{ |
|
oob_stack.Push (current_anonymous_method); |
|
oob_stack.Push (current_local_parameters); |
|
oob_stack.Push (current_variable); |
|
oob_stack.Push (async_block); |
|
|
|
current_local_parameters = parameters; |
|
if (isLambda) { |
|
if (lang_version <= LanguageVersion.ISO_2) |
|
FeatureIsNotAvailable (loc, "lambda expressions"); |
|
|
|
current_anonymous_method = new LambdaExpression (loc); |
|
} else { |
|
if (lang_version == LanguageVersion.ISO_1) |
|
FeatureIsNotAvailable (loc, "anonymous methods"); |
|
|
|
current_anonymous_method = new AnonymousMethodExpression (loc); |
|
} |
|
current_anonymous_method.IsAsync = isAsync; |
|
|
|
async_block = isAsync; |
|
// 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 (ParametersBlock anon_block) |
|
{ |
|
AnonymousMethodExpression retval; |
|
|
|
if (async_block) |
|
anon_block.IsAsync = true; |
|
|
|
current_anonymous_method.Block = anon_block; |
|
retval = current_anonymous_method; |
|
|
|
async_block = (bool) oob_stack.Pop (); |
|
current_variable = (BlockVariableDeclaration) oob_stack.Pop (); |
|
current_local_parameters = (ParametersCompiled) oob_stack.Pop (); |
|
current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); |
|
|
|
return retval; |
|
} |
|
|
|
void Error_SyntaxError (int token) |
|
{ |
|
Error_SyntaxError (0, token); |
|
} |
|
|
|
void Error_SyntaxError (int error_code, int token) |
|
{ |
|
Error_SyntaxError (error_code, token, "Unexpected symbol"); |
|
} |
|
|
|
void Error_SyntaxError (int error_code, int token, string msg) |
|
{ |
|
Lexer.CompleteOnEOF = false; |
|
|
|
// An error message has been reported by tokenizer |
|
if (token == Token.ERROR) |
|
return; |
|
|
|
string symbol = GetSymbolName (token); |
|
string expecting = GetExpecting (); |
|
var loc = lexer.Location - symbol.Length; |
|
|
|
if (error_code == 0) { |
|
if (expecting == "`identifier'") { |
|
if (token > Token.FIRST_KEYWORD && token < Token.LAST_KEYWORD) { |
|
report.Error (1041, loc, "Identifier expected, `{0}' is a keyword", symbol); |
|
return; |
|
} |
|
|
|
error_code = 1001; |
|
expecting = "identifier"; |
|
} else if (expecting == "`)'") { |
|
error_code = 1026; |
|
} else { |
|
error_code = 1525; |
|
} |
|
} |
|
|
|
if (string.IsNullOrEmpty (expecting)) |
|
report.Error (error_code, loc, "{1} `{0}'", symbol, msg); |
|
else |
|
report.Error (error_code, loc, "{2} `{0}', expecting {1}", symbol, expecting, msg); |
|
} |
|
|
|
string GetExpecting () |
|
{ |
|
int [] tokens = yyExpectingTokens (yyExpectingState); |
|
var names = new List<string> (tokens.Length); |
|
bool has_type = false; |
|
bool has_identifier = false; |
|
for (int i = 0; i < tokens.Length; i++){ |
|
int token = tokens [i]; |
|
has_identifier |= token == Token.IDENTIFIER; |
|
|
|
string name = GetTokenName (token); |
|
if (name == "<internal>") |
|
continue; |
|
|
|
has_type |= name == "type"; |
|
if (names.Contains (name)) |
|
continue; |
|
|
|
names.Add (name); |
|
} |
|
|
|
// |
|
// Too many tokens to enumerate |
|
// |
|
if (names.Count > 8) |
|
return null; |
|
|
|
if (has_type && has_identifier) |
|
names.Remove ("identifier"); |
|
|
|
if (names.Count == 1) |
|
return "`" + GetTokenName (tokens [0]) + "'"; |
|
|
|
StringBuilder sb = new StringBuilder (); |
|
names.Sort (); |
|
int count = names.Count; |
|
for (int i = 0; i < count; i++){ |
|
bool last = i + 1 == count; |
|
if (last) |
|
sb.Append ("or "); |
|
sb.Append ('`'); |
|
sb.Append (names [i]); |
|
sb.Append (last ? "'" : count < 3 ? "' " : "', "); |
|
} |
|
return sb.ToString (); |
|
} |
|
|
|
|
|
string GetSymbolName (int token) |
|
{ |
|
switch (token){ |
|
case Token.LITERAL: |
|
return ((Constant)lexer.Value).GetValue ().ToString (); |
|
case Token.IDENTIFIER: |
|
return ((Tokenizer.LocatedToken)lexer.Value).Value; |
|
|
|
case Token.BOOL: |
|
return "bool"; |
|
case Token.BYTE: |
|
return "byte"; |
|
case Token.CHAR: |
|
return "char"; |
|
case Token.VOID: |
|
return "void"; |
|
case Token.DECIMAL: |
|
return "decimal"; |
|
case Token.DOUBLE: |
|
return "double"; |
|
case Token.FLOAT: |
|
return "float"; |
|
case Token.INT: |
|
return "int"; |
|
case Token.LONG: |
|
return "long"; |
|
case Token.SBYTE: |
|
return "sbyte"; |
|
case Token.SHORT: |
|
return "short"; |
|
case Token.STRING: |
|
return "string"; |
|
case Token.UINT: |
|
return "uint"; |
|
case Token.ULONG: |
|
return "ulong"; |
|
case Token.USHORT: |
|
return "ushort"; |
|
case Token.OBJECT: |
|
return "object"; |
|
|
|
case Token.PLUS: |
|
return "+"; |
|
case Token.UMINUS: |
|
case Token.MINUS: |
|
return "-"; |
|
case Token.BANG: |
|
return "!"; |
|
case Token.BITWISE_AND: |
|
return "&"; |
|
case Token.BITWISE_OR: |
|
return "|"; |
|
case Token.STAR: |
|
return "*"; |
|
case Token.PERCENT: |
|
return "%"; |
|
case Token.DIV: |
|
return "/"; |
|
case Token.CARRET: |
|
return "^"; |
|
case Token.OP_INC: |
|
return "++"; |
|
case Token.OP_DEC: |
|
return "--"; |
|
case Token.OP_SHIFT_LEFT: |
|
return "<<"; |
|
case Token.OP_SHIFT_RIGHT: |
|
return ">>"; |
|
case Token.OP_LT: |
|
return "<"; |
|
case Token.OP_GT: |
|
return ">"; |
|
case Token.OP_LE: |
|
return "<="; |
|
case Token.OP_GE: |
|
return ">="; |
|
case Token.OP_EQ: |
|
return "=="; |
|
case Token.OP_NE: |
|
return "!="; |
|
case Token.OP_AND: |
|
return "&&"; |
|
case Token.OP_OR: |
|
return "||"; |
|
case Token.OP_PTR: |
|
return "->"; |
|
case Token.OP_COALESCING: |
|
return "??"; |
|
case Token.OP_MULT_ASSIGN: |
|
return "*="; |
|
case Token.OP_DIV_ASSIGN: |
|
return "/="; |
|
case Token.OP_MOD_ASSIGN: |
|
return "%="; |
|
case Token.OP_ADD_ASSIGN: |
|
return "+="; |
|
case Token.OP_SUB_ASSIGN: |
|
return "-="; |
|
case Token.OP_SHIFT_LEFT_ASSIGN: |
|
return "<<="; |
|
case Token.OP_SHIFT_RIGHT_ASSIGN: |
|
return ">>="; |
|
case Token.OP_AND_ASSIGN: |
|
return "&="; |
|
case Token.OP_XOR_ASSIGN: |
|
return "^="; |
|
case Token.OP_OR_ASSIGN: |
|
return "|="; |
|
} |
|
|
|
return GetTokenName (token); |
|
} |
|
|
|
static string GetTokenName (int token) |
|
{ |
|
switch (token){ |
|
case Token.ABSTRACT: |
|
return "abstract"; |
|
case Token.AS: |
|
return "as"; |
|
case Token.ADD: |
|
return "add"; |
|
case Token.ASYNC: |
|
return "async"; |
|
case Token.BASE: |
|
return "base"; |
|
case Token.BREAK: |
|
return "break"; |
|
case Token.CASE: |
|
return "case"; |
|
case Token.CATCH: |
|
return "catch"; |
|
case Token.CHECKED: |
|
return "checked"; |
|
case Token.CLASS: |
|
return "class"; |
|
case Token.CONST: |
|
return "const"; |
|
case Token.CONTINUE: |
|
return "continue"; |
|
case Token.DEFAULT: |
|
return "default"; |
|
case Token.DELEGATE: |
|
return "delegate"; |
|
case Token.DO: |
|
return "do"; |
|
case Token.ELSE: |
|
return "else"; |
|
case Token.ENUM: |
|
return "enum"; |
|
case Token.EVENT: |
|
return "event"; |
|
case Token.EXPLICIT: |
|
return "explicit"; |
|
case Token.EXTERN: |
|
case Token.EXTERN_ALIAS: |
|
return "extern"; |
|
case Token.FALSE: |
|
return "false"; |
|
case Token.FINALLY: |
|
return "finally"; |
|
case Token.FIXED: |
|
return "fixed"; |
|
case Token.FOR: |
|
return "for"; |
|
case Token.FOREACH: |
|
return "foreach"; |
|
case Token.GOTO: |
|
return "goto"; |
|
case Token.IF: |
|
return "if"; |
|
case Token.IMPLICIT: |
|
return "implicit"; |
|
case Token.IN: |
|
return "in"; |
|
case Token.INTERFACE: |
|
return "interface"; |
|
case Token.INTERNAL: |
|
return "internal"; |
|
case Token.IS: |
|
return "is"; |
|
case Token.LOCK: |
|
return "lock"; |
|
case Token.NAMESPACE: |
|
return "namespace"; |
|
case Token.NEW: |
|
return "new"; |
|
case Token.NULL: |
|
return "null"; |
|
case Token.OPERATOR: |
|
return "operator"; |
|
case Token.OUT: |
|
return "out"; |
|
case Token.OVERRIDE: |
|
return "override"; |
|
case Token.PARAMS: |
|
return "params"; |
|
case Token.PRIVATE: |
|
return "private"; |
|
case Token.PROTECTED: |
|
return "protected"; |
|
case Token.PUBLIC: |
|
return "public"; |
|
case Token.READONLY: |
|
return "readonly"; |
|
case Token.REF: |
|
return "ref"; |
|
case Token.RETURN: |
|
return "return"; |
|
case Token.REMOVE: |
|
return "remove"; |
|
case Token.SEALED: |
|
return "sealed"; |
|
case Token.SIZEOF: |
|
return "sizeof"; |
|
case Token.STACKALLOC: |
|
return "stackalloc"; |
|
case Token.STATIC: |
|
return "static"; |
|
case Token.STRUCT: |
|
return "struct"; |
|
case Token.SWITCH: |
|
return "switch"; |
|
case Token.THIS: |
|
return "this"; |
|
case Token.THROW: |
|
return "throw"; |
|
case Token.TRUE: |
|
return "true"; |
|
case Token.TRY: |
|
return "try"; |
|
case Token.TYPEOF: |
|
return "typeof"; |
|
case Token.UNCHECKED: |
|
return "unchecked"; |
|
case Token.UNSAFE: |
|
return "unsafe"; |
|
case Token.USING: |
|
return "using"; |
|
case Token.VIRTUAL: |
|
return "virtual"; |
|
case Token.VOLATILE: |
|
return "volatile"; |
|
case Token.WHERE: |
|
return "where"; |
|
case Token.WHILE: |
|
return "while"; |
|
case Token.ARGLIST: |
|
return "__arglist"; |
|
case Token.REFVALUE: |
|
return "__refvalue"; |
|
case Token.REFTYPE: |
|
return "__reftype"; |
|
case Token.MAKEREF: |
|
return "__makeref"; |
|
case Token.PARTIAL: |
|
return "partial"; |
|
case Token.ARROW: |
|
return "=>"; |
|
case Token.FROM: |
|
case Token.FROM_FIRST: |
|
return "from"; |
|
case Token.JOIN: |
|
return "join"; |
|
case Token.ON: |
|
return "on"; |
|
case Token.EQUALS: |
|
return "equals"; |
|
case Token.SELECT: |
|
return "select"; |
|
case Token.GROUP: |
|
return "group"; |
|
case Token.BY: |
|
return "by"; |
|
case Token.LET: |
|
return "let"; |
|
case Token.ORDERBY: |
|
return "orderby"; |
|
case Token.ASCENDING: |
|
return "ascending"; |
|
case Token.DESCENDING: |
|
return "descending"; |
|
case Token.INTO: |
|
return "into"; |
|
case Token.GET: |
|
return "get"; |
|
case Token.SET: |
|
return "set"; |
|
case Token.OPEN_BRACE: |
|
return "{"; |
|
case Token.CLOSE_BRACE: |
|
return "}"; |
|
case Token.OPEN_BRACKET: |
|
case Token.OPEN_BRACKET_EXPR: |
|
return "["; |
|
case Token.CLOSE_BRACKET: |
|
return "]"; |
|
case Token.OPEN_PARENS_CAST: |
|
case Token.OPEN_PARENS_LAMBDA: |
|
case Token.OPEN_PARENS: |
|
return "("; |
|
case Token.CLOSE_PARENS: |
|
return ")"; |
|
case Token.DOT: |
|
return "."; |
|
case Token.COMMA: |
|
return ","; |
|
case Token.DEFAULT_COLON: |
|
return "default:"; |
|
case Token.COLON: |
|
return ":"; |
|
case Token.SEMICOLON: |
|
return ";"; |
|
case Token.TILDE: |
|
return "~"; |
|
|
|
case Token.PLUS: |
|
case Token.UMINUS: |
|
case Token.MINUS: |
|
case Token.BANG: |
|
case Token.OP_LT: |
|
case Token.OP_GT: |
|
case Token.BITWISE_AND: |
|
case Token.BITWISE_OR: |
|
case Token.STAR: |
|
case Token.PERCENT: |
|
case Token.DIV: |
|
case Token.CARRET: |
|
case Token.OP_INC: |
|
case Token.OP_DEC: |
|
case Token.OP_SHIFT_LEFT: |
|
case Token.OP_SHIFT_RIGHT: |
|
case Token.OP_LE: |
|
case Token.OP_GE: |
|
case Token.OP_EQ: |
|
case Token.OP_NE: |
|
case Token.OP_AND: |
|
case Token.OP_OR: |
|
case Token.OP_PTR: |
|
case Token.OP_COALESCING: |
|
case Token.OP_MULT_ASSIGN: |
|
case Token.OP_DIV_ASSIGN: |
|
case Token.OP_MOD_ASSIGN: |
|
case Token.OP_ADD_ASSIGN: |
|
case Token.OP_SUB_ASSIGN: |
|
case Token.OP_SHIFT_LEFT_ASSIGN: |
|
case Token.OP_SHIFT_RIGHT_ASSIGN: |
|
case Token.OP_AND_ASSIGN: |
|
case Token.OP_XOR_ASSIGN: |
|
case Token.OP_OR_ASSIGN: |
|
return "<operator>"; |
|
|
|
case Token.BOOL: |
|
case Token.BYTE: |
|
case Token.CHAR: |
|
case Token.VOID: |
|
case Token.DECIMAL: |
|
case Token.DOUBLE: |
|
case Token.FLOAT: |
|
case Token.INT: |
|
case Token.LONG: |
|
case Token.SBYTE: |
|
case Token.SHORT: |
|
case Token.STRING: |
|
case Token.UINT: |
|
case Token.ULONG: |
|
case Token.USHORT: |
|
case Token.OBJECT: |
|
return "type"; |
|
|
|
case Token.ASSIGN: |
|
return "="; |
|
case Token.OP_GENERICS_LT: |
|
case Token.GENERIC_DIMENSION: |
|
return "<"; |
|
case Token.OP_GENERICS_GT: |
|
return ">"; |
|
case Token.INTERR: |
|
case Token.INTERR_NULLABLE: |
|
return "?"; |
|
case Token.DOUBLE_COLON: |
|
return "::"; |
|
case Token.LITERAL: |
|
return "value"; |
|
case Token.IDENTIFIER: |
|
case Token.AWAIT: |
|
return "identifier"; |
|
|
|
case Token.EOF: |
|
return "end-of-file"; |
|
|
|
// All of these are internal. |
|
case Token.NONE: |
|
case Token.ERROR: |
|
case Token.FIRST_KEYWORD: |
|
case Token.EVAL_COMPILATION_UNIT_PARSER: |
|
case Token.EVAL_USING_DECLARATIONS_UNIT_PARSER: |
|
case Token.EVAL_STATEMENT_PARSER: |
|
case Token.LAST_KEYWORD: |
|
case Token.GENERATE_COMPLETION: |
|
case Token.COMPLETE_COMPLETION: |
|
return "<internal>"; |
|
|
|
// A bit more robust. |
|
default: |
|
return yyNames [token]; |
|
} |
|
} |
|
|
|
/* end end end */ |
|
}
|
|
|