%{
//
// cs-parser.jay: The Parser for the C# compiler
//
// Authors: Miguel de Icaza (miguel@gnu.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 Novell, Inc
//
// TODO:
// (1) Figure out why error productions dont work. `type-declaration' is a
// great spot to put an `error' because you can reproduce it with this input:
// "public X { }"
//
using System.Text;
using System.IO;
using System;
using System.Collections.Generic;
namespace Mono.CSharp
{
///
/// The C# Parser
///
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
}
NamespaceEntry current_namespace;
TypeContainer current_container;
DeclSpace current_class;
///
/// Current block is used to add statements as we find
/// them.
///
Block current_block;
Delegate current_delegate;
GenericMethod current_generic_method;
AnonymousMethodExpression current_anonymous_method;
///
/// This is used by the unary_expression code to resolve
/// a name against a parameter.
///
// 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;
///
/// Using during property parsing to describe the implicit
/// value parameter that is passed to the "set" and "get"accesor
/// methods (properties and indexers).
///
FullNamedExpression implicit_value_parameter_type;
ParametersCompiled indexer_parameters;
///
/// Used to determine if we are parsing the get/set pair
/// of an indexer or a property
///
bool parsing_indexer;
bool parsing_anonymous_method;
///
/// An out-of-band stack.
///
static Stack oob_stack;
///
/// Switch stack.
///
Stack switch_stack;
///
/// Controls the verbosity of the errors produced by the parser
///
static public 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.
///
CompilationUnit 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;
/// assembly and module attribute definitions are enabled
bool global_attrs_enabled = true;
bool has_get, has_set;
ParameterModifierType valid_param_mod;
bool default_parameter_used;
/// When using the interactive parser, this holds the
/// resulting expression
public object InteractiveResult;
//
// Keeps track of global data changes to undo on parser error
//
public Undo undo;
Stack linq_clause_blocks;
// A counter to create new class names in interactive mode
static int class_count;
CompilerContext compiler;
//
// Instead of allocating carrier array everytime we
// share the bucket for very common constructs which can never
// be recursive
//
static List parameters_bucket = new List (6);
static List variables_bucket = new List (6);
%}
%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
/* Generics <,> tokens */
%token OP_GENERICS_LT
%token OP_GENERICS_LT_DECL
%token OP_GENERICS_GT
/* 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
%token LITERAL
%token IDENTIFIER
%token OPEN_PARENS_LAMBDA
%token OPEN_PARENS_CAST
%token GENERIC_DIMENSION
%token DEFAULT_COLON
// 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
//
// 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_declarations opt_EOF
| outer_declarations global_attributes opt_EOF
| global_attributes opt_EOF
| opt_EOF /* allow empty files */
| interactive_parsing { Lexer.CompleteOnEOF = false; } opt_EOF
;
opt_EOF
: /* empty */
{
Lexer.check_incorrect_doc_comment ();
}
| EOF
{
Lexer.check_incorrect_doc_comment ();
}
;
outer_declarations
: outer_declaration
| outer_declarations outer_declaration
;
outer_declaration
: extern_alias_directive
| using_directive
| namespace_member_declaration
;
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 (RootContext.Version == LanguageVersion.ISO_1) {
Report.FeatureIsNotAvailable (lt.Location, "external alias");
} else {
lt = (Tokenizer.LocatedToken) $3;
current_namespace.AddUsingExternalAlias (lt.Value, lt.Location, Report);
}
}
| EXTERN_ALIAS error
{
syntax_error (GetLocation ($1), "`alias' expected"); // TODO: better
}
;
using_directives
: using_directive
| using_directives using_directive
;
using_directive
: using_alias_directive
{
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
| using_namespace_directive
{
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
;
using_alias_directive
: USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON
{
var lt = (Tokenizer.LocatedToken) $2;
current_namespace.AddUsingAlias (lt.Value, (MemberName) $4, GetLocation ($1));
}
| USING error {
CheckIdentifierToken (yyToken, GetLocation ($2));
$$ = null;
}
;
using_namespace_directive
: USING namespace_name SEMICOLON
{
current_namespace.AddUsing ((MemberName) $2, GetLocation ($1));
}
;
//
// 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 qualified_identifier
{
MemberName name = (MemberName) $3;
if ($1 != null) {
Report.Error(1671, name.Location, "A namespace declaration cannot have modifiers or attributes");
}
current_namespace = new NamespaceEntry (
current_namespace, file, name.GetName ());
current_class = current_namespace.SlaveDeclSpace;
current_container = current_class.PartialContainer;
}
namespace_body opt_semicolon
{
current_namespace = current_namespace.Parent;
current_class = current_namespace.SlaveDeclSpace;
current_container = current_class.PartialContainer;
}
;
qualified_identifier
: IDENTIFIER
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new MemberName (lt.Value, lt.Location);
}
| qualified_identifier DOT IDENTIFIER
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new MemberName ((MemberName) $1, lt.Value, lt.Location);
}
| error
{
syntax_error (lexer.Location, "`.' expected");
$$ = new MemberName ("", lexer.Location);
}
;
opt_semicolon
: /* empty */
| SEMICOLON
;
opt_comma
: /* empty */
| COMMA
;
namespace_name
: namespace_or_type_name
{
MemberName name = (MemberName) $1;
if (name.TypeArguments != null)
syntax_error (lexer.Location, "namespace name expected");
$$ = name;
}
;
namespace_body
: OPEN_BRACE
{
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
namespace_body_body
;
namespace_body_body
: opt_extern_alias_directives
opt_using_directives
opt_namespace_member_declarations
CLOSE_BRACE
| error
{
Report.Error (1518, lexer.Location, "Expected `class', `delegate', `enum', `interface', or `struct'");
}
CLOSE_BRACE
| opt_extern_alias_directives
opt_using_directives
opt_namespace_member_declarations
EOF
{
Report.Error (1513, lexer.Location, "Expected `}'");
}
;
opt_using_directives
: /* empty */
| using_directives
;
opt_extern_alias_directives
: /* empty */
| extern_alias_directives
;
opt_namespace_member_declarations
: /* empty */
| namespace_member_declarations
;
namespace_member_declarations
: namespace_member_declaration
| namespace_member_declarations namespace_member_declaration
;
namespace_member_declaration
: type_declaration
{
if ($1 != null) {
DeclSpace ds = (DeclSpace)$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");
}
}
current_namespace.DeclarationFound = true;
}
| namespace_declaration {
current_namespace.DeclarationFound = true;
}
| field_declaration {
Report.Error (116, ((MemberCore) $1).Location, "A namespace can only contain types and namespace declarations");
}
| method_declaration {
Report.Error (116, ((MemberCore) $1).Location, "A namespace can only contain types and namespace declarations");
}
;
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 17.2
//
global_attributes
: attribute_sections
{
if ($1 != null) {
Attributes attrs = (Attributes)$1;
if (global_attrs_enabled) {
CodeGen.Assembly.AddAttributes (attrs.Attrs, current_namespace);
} else {
foreach (Attribute a in attrs.Attrs) {
Report.Error (1730, a.Location, "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations");
}
}
}
$$ = $1;
}
;
opt_attributes
: /* empty */
{
global_attrs_enabled = false;
$$ = null;
}
| attribute_sections
{
global_attrs_enabled = false;
$$ = $1;
}
;
attribute_sections
: attribute_section
{
if (current_attr_target != String.Empty) {
var sect = (List) $1;
if (global_attrs_enabled) {
if (current_attr_target == "module") {
current_container.Module.Compiled.AddAttributes (sect);
$$ = null;
} else if (current_attr_target != null && current_attr_target.Length > 0) {
CodeGen.Assembly.AddAttributes (sect, current_namespace);
$$ = null;
} else {
$$ = new Attributes (sect);
}
if ($$ == null) {
if (RootContext.Documentation != null) {
Lexer.check_incorrect_doc_comment ();
Lexer.doc_state =
XmlCommentState.Allowed;
}
}
} else {
$$ = new Attributes (sect);
}
}
else
$$ = null;
current_attr_target = null;
}
| attribute_sections attribute_section
{
if (current_attr_target != String.Empty) {
Attributes attrs = $1 as Attributes;
var sect = (List) $2;
if (global_attrs_enabled) {
if (current_attr_target == "module") {
current_container.Module.Compiled.AddAttributes (sect);
$$ = null;
} else if (current_attr_target == "assembly") {
CodeGen.Assembly.AddAttributes (sect, current_namespace);
$$ = null;
} else {
if (attrs == null)
attrs = new Attributes (sect);
else
attrs.AddAttributes (sect);
}
} else {
if (attrs == null)
attrs = new Attributes (sect);
else
attrs.AddAttributes (sect);
}
$$ = attrs;
}
else
$$ = null;
current_attr_target = null;
}
;
attribute_section
: OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
{
$$ = $3;
}
| OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
{
$$ = $2;
}
;
attribute_target_specifier
: attribute_target COLON
{
current_attr_target = (string)$1;
$$ = $1;
}
;
attribute_target
: IDENTIFIER
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = CheckAttributeTarget (lt.Value, lt.Location);
}
| EVENT { $$ = "event"; }
| RETURN { $$ = "return"; }
| error
{
string name = GetTokenName (yyToken);
$$ = CheckAttributeTarget (name, GetLocation ($1));
}
;
attribute_list
: attribute
{
$$ = new List (4) { (Attribute) $1 };
}
| attribute_list COMMA attribute
{
var attrs = (List) $1;
attrs.Add ((Attribute) $3);
$$ = attrs;
}
;
attribute
: attribute_name
{
++lexer.parsing_block;
}
opt_attribute_arguments
{
--lexer.parsing_block;
MemberName mname = (MemberName) $1;
if (mname.IsGeneric) {
Report.Error (404, lexer.Location,
"'<' unexpected: attributes cannot be generic");
}
Arguments [] arguments = (Arguments []) $3;
ATypeNameExpression expr = mname.GetTypeExpression ();
if (current_attr_target == String.Empty)
$$ = null;
else if (global_attrs_enabled && (current_attr_target == "assembly" || current_attr_target == "module"))
// FIXME: supply "nameEscaped" parameter here.
$$ = new GlobalAttribute (current_namespace, current_attr_target,
expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
else
$$ = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
}
;
attribute_name
: namespace_or_type_name { /* reserved attribute name or identifier: 17.4 */ }
;
opt_attribute_arguments
: /* empty */ { $$ = null; }
| OPEN_PARENS attribute_arguments CLOSE_PARENS
{
$$ = $2;
}
;
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);
}
| 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);
}
;
positional_or_named_argument
: expression
{
$$ = new Argument ((Expression) $1);
}
| named_argument
;
named_attribute_argument
: IDENTIFIER ASSIGN expression
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new NamedArgument (lt.Value, lt.Location, (Expression) $3);
}
;
named_argument
: IDENTIFIER COLON opt_named_modifier expression
{
if (RootContext.Version <= LanguageVersion.V_3)
Report.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);
}
;
opt_named_modifier
: /* empty */ { $$ = null; }
| REF
{
$$ = Argument.AType.Ref;
}
| OUT
{
$$ = Argument.AType.Out;
}
;
class_body
: OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
;
opt_class_member_declarations
: /* empty */
| class_member_declarations
;
class_member_declarations
: class_member_declaration
| class_member_declarations
class_member_declaration
;
class_member_declaration
: constant_declaration // done
| field_declaration // done
| method_declaration // done
| property_declaration // done
| event_declaration // done
| indexer_declaration // done
| operator_declaration // done
| constructor_declaration // done
| destructor_declaration // done
| type_declaration
| 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
{
MemberName name = MakeName ((MemberName) $6);
push_current_class (new Struct (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3);
}
opt_class_base
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
current_class.SetParameterInfo ((List) $9);
if (RootContext.Documentation != null)
current_container.DocComment = Lexer.consume_doc_comment ();
}
struct_body
{
--lexer.parsing_declaration;
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
opt_semicolon
{
$$ = pop_current_class ();
}
| opt_attributes opt_modifiers opt_partial STRUCT error {
CheckIdentifierToken (yyToken, GetLocation ($5));
}
;
struct_body
: OPEN_BRACE
{
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
opt_struct_member_declarations CLOSE_BRACE
;
opt_struct_member_declarations
: /* empty */
| struct_member_declarations
;
struct_member_declarations
: struct_member_declaration
| struct_member_declarations struct_member_declaration
;
struct_member_declaration
: constant_declaration
| field_declaration
| method_declaration
| property_declaration
| event_declaration
| indexer_declaration
| operator_declaration
| constructor_declaration
| type_declaration
/*
* This is only included so we can flag error 575:
* destructors only allowed on class types
*/
| destructor_declaration
;
constant_declaration
: opt_attributes
opt_modifiers
CONST
type
constant_declarators
SEMICOLON
{
var modflags = (Modifiers) $2;
foreach (VariableDeclaration constant in (List) $5){
Location l = constant.Location;
if ((modflags & Modifiers.STATIC) != 0) {
Report.Error (504, l, "The constant `{0}' cannot be marked static", current_container.GetSignatureForError () + "." + (string) constant.identifier);
continue;
}
Const c = new Const (
current_class, (FullNamedExpression) $4, (string) constant.identifier,
constant.GetInitializer ((FullNamedExpression) $4), modflags,
(Attributes) $1, l);
if (RootContext.Documentation != null) {
c.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
current_container.AddConstant (c);
}
}
;
constant_declarators
: constant_declarator
{
variables_bucket.Clear ();
if ($1 != null)
variables_bucket.Add ($1);
$$ = variables_bucket;
}
| constant_declarators COMMA constant_declarator
{
if ($3 != null) {
var constants = (List) $1;
constants.Add ($3);
}
}
;
constant_declarator
: IDENTIFIER ASSIGN
{
++lexer.parsing_block;
}
constant_initializer
{
--lexer.parsing_block;
$$ = new VariableDeclaration ((Tokenizer.LocatedToken) $1, (Expression) $4);
}
| IDENTIFIER
{
// A const field requires a value to be provided
Report.Error (145, GetLocation ($1), "A const field requires a value to be provided");
$$ = null;
}
;
constant_initializer
: constant_expression
| array_initializer
;
field_declaration
: opt_attributes
opt_modifiers
member_type
variable_declarators
SEMICOLON
{
FullNamedExpression type = (FullNamedExpression) $3;
if (type == TypeManager.system_void_expr)
Report.Error (670, GetLocation ($3), "Fields cannot have void type");
var mod = (Modifiers) $2;
foreach (VariableMemberDeclaration var in (List) $4){
Field field = new Field (current_class, type, mod, var.MemberName, (Attributes) $1);
field.Initializer = var.GetInitializer (type);
if (RootContext.Documentation != null) {
field.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
current_container.AddField (field);
$$ = field; // FIXME: might be better if it points to the top item
}
}
| opt_attributes
opt_modifiers
FIXED
member_type
fixed_variable_declarators
SEMICOLON
{
FullNamedExpression type = (FullNamedExpression) $4;
var mod = (Modifiers) $2;
foreach (VariableDeclaration var in (List) $5) {
FixedField field = new FixedField (current_class, type, mod, var.identifier,
var.GetInitializer (type), (Attributes) $1, var.Location);
if (RootContext.Documentation != null) {
field.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
current_container.AddField (field);
$$ = field; // FIXME: might be better if it points to the top item
}
}
| opt_attributes
opt_modifiers
FIXED
member_type
error
{
Report.Error (1641, GetLocation ($4), "A fixed size buffer field must have the array size specifier after the field name");
}
;
fixed_variable_declarators
: fixed_variable_declarator
{
var decl = new List (2);
decl.Add ((VariableDeclaration)$1);
$$ = decl;
}
| fixed_variable_declarators COMMA fixed_variable_declarator
{
var decls = (List) $1;
decls.Add ((VariableDeclaration)$3);
$$ = $1;
}
;
fixed_variable_declarator
: IDENTIFIER OPEN_BRACKET expression CLOSE_BRACKET
{
$$ = new VariableDeclaration ((Tokenizer.LocatedToken) $1, (Expression) $3);
}
| IDENTIFIER OPEN_BRACKET CLOSE_BRACKET
{
Report.Error (443, lexer.Location, "Value or constant expected");
$$ = new VariableDeclaration ((Tokenizer.LocatedToken) $1, null);
}
;
local_variable_declarators
: local_variable_declarator
{
variables_bucket.Clear ();
if ($1 != null)
variables_bucket.Add ($1);
$$ = variables_bucket;
}
| local_variable_declarators COMMA local_variable_declarator
{
var decls = (List) $1;
decls.Add ($3);
$$ = $1;
}
;
local_variable_declarator
: IDENTIFIER ASSIGN local_variable_initializer
{
$$ = new VariableDeclaration ((Tokenizer.LocatedToken) $1, (Expression) $3);
}
| IDENTIFIER
{
$$ = new VariableDeclaration ((Tokenizer.LocatedToken) $1, null);
}
| IDENTIFIER variable_bad_array
{
$$ = null;
}
;
local_variable_initializer
: expression
| array_initializer
| STACKALLOC simple_type OPEN_BRACKET expression CLOSE_BRACKET
{
$$ = new StackAlloc ((Expression) $2, (Expression) $4, GetLocation ($1));
}
| ARGLIST
{
$$ = new ArglistAccess (GetLocation ($1));
}
| STACKALLOC simple_type
{
Report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type");
$$ = new StackAlloc ((Expression) $2, null, GetLocation ($1));
}
;
variable_declarators
: variable_declarator
{
variables_bucket.Clear ();
if ($1 != null)
variables_bucket.Add ($1);
$$ = variables_bucket;
}
| variable_declarators COMMA variable_declarator
{
var decls = (List) $1;
decls.Add ($3);
$$ = $1;
}
;
variable_declarator
: member_declaration_name ASSIGN
{
++lexer.parsing_block;
lexer.parsing_generic_declaration = false;
}
variable_initializer
{
--lexer.parsing_block;
$$ = new VariableMemberDeclaration ((MemberName) $1, (Expression) $4);
}
| member_declaration_name
{
lexer.parsing_generic_declaration = false;
$$ = new VariableMemberDeclaration ((MemberName) $1, null);
}
| member_declaration_name variable_bad_array
{
lexer.parsing_generic_declaration = false;
$$ = null;
}
;
variable_bad_array
: OPEN_BRACKET opt_expression CLOSE_BRACKET
{
Report.Error (650, GetLocation ($1), "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");
}
;
variable_initializer
: expression
| array_initializer
;
method_declaration
: method_header {
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.NotAllowed;
}
method_body
{
Method method = (Method) $1;
method.Block = (ToplevelBlock) $3;
current_container.AddMethod (method);
if (current_container.Kind == Kind.Interface && method.Block != null) {
Report.Error (531, method.Location, "`{0}': interface members cannot have a definition", method.GetSignatureForError ());
}
current_generic_method = null;
current_local_parameters = null;
if (RootContext.Documentation != null)
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;
if ($10 != null && name.TypeArguments == null)
Report.Error (80, lexer.Location,
"Constraints are not allowed on non-generic declarations");
Method method;
GenericMethod generic = null;
if (name.TypeArguments != null) {
generic = new GenericMethod (current_namespace, current_class, name,
(FullNamedExpression) $3, current_local_parameters);
generic.SetParameterInfo ((List) $10);
}
method = new Method (current_class, generic, (FullNamedExpression) $3, (Modifiers) $2,
name, current_local_parameters, (Attributes) $1);
current_generic_method = generic;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = method;
}
| opt_attributes
opt_modifiers
PARTIAL
VOID 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) $5;
current_local_parameters = (ParametersCompiled) $8;
if ($10 != null && name.TypeArguments == null)
Report.Error (80, lexer.Location,
"Constraints are not allowed on non-generic declarations");
Method method;
GenericMethod generic = null;
if (name.TypeArguments != null) {
generic = new GenericMethod (current_namespace, current_class, name,
TypeManager.system_void_expr, current_local_parameters);
generic.SetParameterInfo ((List) $11);
}
var modifiers = (Modifiers) $2;
const Modifiers invalid_partial_mod = Modifiers.AccessibilityMask | Modifiers.ABSTRACT | Modifiers.EXTERN |
Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.SEALED | Modifiers.VIRTUAL;
if ((modifiers & invalid_partial_mod) != 0) {
Report.Error (750, name.Location, "A partial method cannot define access modifier or " +
"any of abstract, extern, new, override, sealed, or virtual modifiers");
modifiers &= ~invalid_partial_mod;
}
if ((current_class.ModFlags & Modifiers.PARTIAL) == 0) {
Report.Error (751, name.Location, "A partial method must be declared within a " +
"partial class or partial struct");
}
modifiers |= Modifiers.PARTIAL | Modifiers.PRIVATE;
method = new Method (current_class, generic, TypeManager.system_void_expr,
modifiers, name, current_local_parameters, (Attributes) $1);
current_generic_method = generic;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = 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));
Method method = new Method (current_class, null, TypeManager.system_void_expr,
0, name, (ParametersCompiled) $7, (Attributes) $1);
current_local_parameters = (ParametersCompiled) $7;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = method;
}
;
method_body
: block
| SEMICOLON { $$ = null; }
;
opt_formal_parameter_list
: /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; }
| formal_parameter_list
;
formal_parameter_list
: fixed_parameters
{
var pars_list = (List) $1;
$$ = new ParametersCompiled (compiler, pars_list.ToArray ());
}
| fixed_parameters COMMA parameter_array
{
var pars_list = (List) $1;
pars_list.Add ((Parameter) $3);
$$ = new ParametersCompiled (compiler, pars_list.ToArray ());
}
| fixed_parameters COMMA arglist_modifier
{
var pars_list = (List) $1;
pars_list.Add (new ArglistParameter (GetLocation ($3)));
$$ = new ParametersCompiled (compiler, pars_list.ToArray (), true);
}
| 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 (compiler, new Parameter[] { (Parameter) $1 } );
}
| 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) $1;
pars_list.Add (new ArglistParameter (GetLocation ($3)));
$$ = new ParametersCompiled (compiler, pars_list.ToArray (), true);
}
| arglist_modifier COMMA error
{
Report.Error (257, GetLocation ($1), "An __arglist parameter must be the last parameter in a formal parameter list");
$$ = new ParametersCompiled (compiler, new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true);
}
| 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) $1;
pars_list.Add (new ArglistParameter (GetLocation ($3)));
$$ = new ParametersCompiled (compiler, pars_list.ToArray (), true);
}
| parameter_array
{
$$ = new ParametersCompiled (compiler, new Parameter[] { (Parameter) $1 } );
}
| arglist_modifier
{
$$ = new ParametersCompiled (compiler, new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true);
}
;
fixed_parameters
: fixed_parameter
{
parameters_bucket.Clear ();
Parameter p = (Parameter) $1;
parameters_bucket.Add (p);
default_parameter_used = p.HasDefaultValue;
$$ = parameters_bucket;
}
| fixed_parameters COMMA fixed_parameter
{
var pars = (List) $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);
}
$$ = $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);
}
| 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);
}
| opt_attributes
opt_parameter_modifier
parameter_type
error
{
Location l = GetLocation ($4);
CheckIdentifierToken (yyToken, l);
$$ = new Parameter ((FullNamedExpression) $3, "NeedSomeGeneratorHere", (Parameter.Modifier) $2, (Attributes) $1, l);
}
| opt_attributes
opt_parameter_modifier
parameter_type
IDENTIFIER
ASSIGN
constant_expression
{
if (RootContext.Version <= LanguageVersion.V_3) {
Report.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 ($6), "Optional parameter is not valid in this context");
var lt = (Tokenizer.LocatedToken) $4;
$$ = new Parameter ((FullNamedExpression) $3, lt.Value, mod, (Attributes) $1, lt.Location);
if ($6 != null)
((Parameter) $$).DefaultValue = (Expression) $6;
}
;
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));
$$ = Parameter.Modifier.REF;
}
| OUT
{
if ((valid_param_mod & ParameterModifierType.Out) == 0)
Error_ParameterModifierNotValid ("out", GetLocation ($1));
$$ = Parameter.Modifier.OUT;
}
| THIS
{
if ((valid_param_mod & ParameterModifierType.This) == 0)
Error_ParameterModifierNotValid ("this", GetLocation ($1));
if (RootContext.Version <= LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "extension methods");
$$ = 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);
}
| 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);
}
| opt_attributes params_modifier type error {
CheckIdentifierToken (yyToken, GetLocation ($4));
$$ = 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");
}
| 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");
}
}
| 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 (RootContext.Documentation != null)
tmpComment = Lexer.consume_doc_comment ();
}
OPEN_BRACE
{
implicit_value_parameter_type = (FullNamedExpression) $3;
lexer.PropertyParsing = true;
}
accessor_declarations
{
lexer.PropertyParsing = false;
has_get = has_set = false;
}
CLOSE_BRACE
{
Property prop;
Accessors accessors = (Accessors) $8;
Accessor get_block = accessors != null ? accessors.get_or_add : null;
Accessor set_block = accessors != null ? accessors.set_or_remove : null;
bool order = accessors != null ? accessors.declared_in_reverse : false;
MemberName name = (MemberName) $4;
FullNamedExpression ptype = (FullNamedExpression) $3;
prop = new Property (current_class, ptype, (Modifiers) $2,
name, (Attributes) $1, get_block, set_block, order, current_block);
if (ptype == TypeManager.system_void_expr)
Report.Error (547, name.Location, "`{0}': property or indexer cannot have void type", prop.GetSignatureForError ());
if (accessors == null)
Report.Error (548, prop.Location, "`{0}': property or indexer must have at least one accessor", prop.GetSignatureForError ());
if (current_container.Kind == Kind.Interface) {
if (prop.Get.Block != null)
Report.Error (531, prop.Location, "`{0}.get': interface members cannot have a definition", prop.GetSignatureForError ());
if (prop.Set.Block != null)
Report.Error (531, prop.Location, "`{0}.set': interface members cannot have a definition", prop.GetSignatureForError ());
}
current_container.AddProperty (prop);
implicit_value_parameter_type = null;
if (RootContext.Documentation != null)
prop.DocComment = ConsumeStoredComment ();
}
;
accessor_declarations
: get_accessor_declaration
{
$$ = new Accessors ((Accessor) $1, null);
}
| get_accessor_declaration accessor_declarations
{
Accessors accessors = (Accessors) $2;
accessors.get_or_add = (Accessor) $1;
$$ = accessors;
}
| set_accessor_declaration
{
$$ = new Accessors (null, (Accessor) $1);
}
| set_accessor_declaration accessor_declarations
{
Accessors accessors = (Accessors) $2;
accessors.set_or_remove = (Accessor) $1;
accessors.declared_in_reverse = true;
$$ = accessors;
}
| error
{
if (yyToken == Token.CLOSE_BRACE) {
$$ = null;
} 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");
$$ = new Accessors (null, null);
}
}
;
get_accessor_declaration
: opt_attributes opt_modifiers GET
{
// If this is not the case, then current_local_parameters has already
// been set in indexer_declaration
if (parsing_indexer == false)
current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters;
else
current_local_parameters = indexer_parameters;
lexer.PropertyParsing = false;
}
accessor_body
{
if (has_get) {
Report.Error (1007, GetLocation ($3), "Property accessor already defined");
break;
}
Accessor accessor = new Accessor ((ToplevelBlock) $5, (Modifiers) $2, (Attributes) $1, current_local_parameters, GetLocation ($3));
has_get = true;
current_local_parameters = null;
lexer.PropertyParsing = true;
if (RootContext.Documentation != null)
if (Lexer.doc_state == XmlCommentState.Error)
Lexer.doc_state = XmlCommentState.NotAllowed;
$$ = accessor;
}
;
set_accessor_declaration
: opt_attributes opt_modifiers SET
{
Parameter implicit_value_parameter = new Parameter (
implicit_value_parameter_type, "value",
Parameter.Modifier.NONE, null, GetLocation ($3));
if (!parsing_indexer) {
current_local_parameters = new ParametersCompiled (compiler, new Parameter [] { implicit_value_parameter });
} else {
current_local_parameters = ParametersCompiled.MergeGenerated (compiler,
indexer_parameters, true, implicit_value_parameter, null);
}
lexer.PropertyParsing = false;
}
accessor_body
{
if (has_set) {
Report.Error (1007, GetLocation ($3), "Property accessor already defined");
break;
}
Accessor accessor = new Accessor ((ToplevelBlock) $5, (Modifiers) $2, (Attributes) $1, current_local_parameters, GetLocation ($3));
has_set = true;
current_local_parameters = null;
lexer.PropertyParsing = true;
if (RootContext.Documentation != null
&& Lexer.doc_state == XmlCommentState.Error)
Lexer.doc_state = XmlCommentState.NotAllowed;
$$ = accessor;
}
;
accessor_body
: block
| SEMICOLON
{
$$ = 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
{
MemberName name = MakeName ((MemberName) $6);
push_current_class (new Interface (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3);
}
opt_class_base
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
current_class.SetParameterInfo ((List) $9);
if (RootContext.Documentation != null) {
current_container.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
interface_body
{
--lexer.parsing_declaration;
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
opt_semicolon
{
$$ = pop_current_class ();
}
| opt_attributes opt_modifiers opt_partial INTERFACE error {
CheckIdentifierToken (yyToken, GetLocation ($5));
}
;
interface_body
: OPEN_BRACE
opt_interface_member_declarations
CLOSE_BRACE
;
opt_interface_member_declarations
: /* empty */
| interface_member_declarations
;
interface_member_declarations
: interface_member_declaration
| interface_member_declarations interface_member_declaration
;
interface_member_declaration
: 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
{
if ($3 == null)
break;
OperatorDeclaration decl = (OperatorDeclaration) $3;
Operator op = new Operator (
current_class, decl.optype, decl.ret_type, (Modifiers) $2,
current_local_parameters,
(ToplevelBlock) $5, (Attributes) $1, decl.location);
if (RootContext.Documentation != null) {
op.DocComment = tmpComment;
Lexer.doc_state = XmlCommentState.Allowed;
}
// Note again, checking is done in semantic analysis
current_container.AddOperator (op);
current_local_parameters = null;
}
;
operator_body
: block
| SEMICOLON { $$ = null; }
;
operator_type
: type_expression_or_array
| VOID
{
Report.Error (590, GetLocation ($1), "User-defined operators cannot return void");
$$ = TypeManager.system_void_expr;
}
;
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 (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
$$ = new OperatorDeclaration (op, (FullNamedExpression) $1, loc);
}
| conversion_operator_declarator
;
overloadable_operator
// Unary operators:
: BANG { $$ = Operator.OpType.LogicalNot; }
| TILDE { $$ = Operator.OpType.OnesComplement; }
| OP_INC { $$ = Operator.OpType.Increment; }
| OP_DEC { $$ = Operator.OpType.Decrement; }
| TRUE { $$ = Operator.OpType.True; }
| FALSE { $$ = Operator.OpType.False; }
// Unary and binary:
| PLUS { $$ = Operator.OpType.Addition; }
| MINUS { $$ = Operator.OpType.Subtraction; }
// Binary:
| STAR { $$ = Operator.OpType.Multiply; }
| DIV { $$ = Operator.OpType.Division; }
| PERCENT { $$ = Operator.OpType.Modulus; }
| BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
| BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
| CARRET { $$ = Operator.OpType.ExclusiveOr; }
| OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
| OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
| OP_EQ { $$ = Operator.OpType.Equality; }
| OP_NE { $$ = Operator.OpType.Inequality; }
| OP_GT { $$ = Operator.OpType.GreaterThan; }
| OP_LT { $$ = Operator.OpType.LessThan; }
| OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
| OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
;
conversion_operator_declarator
: IMPLICIT OPERATOR type OPEN_PARENS
{
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 (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
$$ = new OperatorDeclaration (Operator.OpType.Implicit, (FullNamedExpression) $3, loc);
}
| 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 (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
$$ = new OperatorDeclaration (Operator.OpType.Explicit, (FullNamedExpression) $3, loc);
}
| 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 (RootContext.Documentation != null)
c.DocComment = ConsumeStoredComment ();
current_container.AddConstructor (c);
current_local_parameters = null;
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
;
constructor_declarator
: opt_attributes
opt_modifiers
IDENTIFIER
{
if (RootContext.Documentation != null) {
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;
//
// start block here, so possible anonymous methods inside
// constructor initializer can get correct parent block
//
start_block (lexer.Location);
}
opt_constructor_initializer
{
var lt = (Tokenizer.LocatedToken) $3;
var mods = (Modifiers) $2;
ConstructorInitializer ci = (ConstructorInitializer) $9;
Constructor c = new Constructor (current_class, lt.Value, mods,
(Attributes) $1, current_local_parameters, ci, 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 ());
}
if (ci != null) {
Report.Error (514, c.Location,
"`{0}': static constructor cannot have an explicit `this' or `base' constructor call",
c.GetSignatureForError ());
}
}
$$ = c;
}
;
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));
}
| COLON THIS OPEN_PARENS
{
++lexer.parsing_block;
}
opt_argument_list CLOSE_PARENS
{
--lexer.parsing_block;
$$ = new ConstructorThisInitializer ((Arguments) $5, GetLocation ($2));
}
| COLON error {
Report.Error (1018, GetLocation ($1), "Keyword `this' or `base' expected");
$$ = null;
}
;
destructor_declaration
: opt_attributes opt_modifiers TILDE
{
if (RootContext.Documentation != null) {
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 != Kind.Class){
Report.Error (575, lt.Location, "Only class types can contain destructor");
} else {
Destructor d = new Destructor (current_class, (Modifiers) $2,
ParametersCompiled.EmptyReadOnlyParameters, (Attributes) $1, lt.Location);
if (RootContext.Documentation != null)
d.DocComment = ConsumeStoredComment ();
d.Block = (ToplevelBlock) $8;
current_container.AddMethod (d);
}
current_local_parameters = null;
}
;
event_declaration
: opt_attributes
opt_modifiers
EVENT type variable_declarators SEMICOLON
{
foreach (VariableMemberDeclaration var in (List) $5) {
EventField e = new EventField (
current_class, (FullNamedExpression) $4, (Modifiers) $2, var.MemberName, (Attributes) $1);
e.Initializer = var.GetInitializer ((FullNamedExpression) $4);
if (current_container.Kind == Kind.Interface && e.Initializer != null) {
Report.Error (68, e.Location, "`{0}': event in interface cannot have initializer", e.GetSignatureForError ());
}
if (var.MemberName.Left != null) {
Report.Error (71, e.Location,
"`{0}': An explicit interface implementation of an event must use property syntax",
e.GetSignatureForError ());
}
current_container.AddEvent (e);
if (RootContext.Documentation != null) {
e.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
}
| opt_attributes
opt_modifiers
EVENT type member_declaration_name
OPEN_BRACE
{
implicit_value_parameter_type = (FullNamedExpression) $4;
current_local_parameters = new ParametersCompiled (compiler,
new Parameter (implicit_value_parameter_type, "value",
Parameter.Modifier.NONE, null, GetLocation ($3)));
lexer.EventParsing = true;
}
event_accessor_declarations
{
lexer.EventParsing = false;
}
CLOSE_BRACE
{
MemberName name = (MemberName) $5;
if (current_container.Kind == Kind.Interface) {
Report.Error (69, GetLocation ($3), "Event in interface cannot have add or remove accessors");
$8 = new Accessors (null, null);
} else if ($8 == null) {
Report.Error (65, GetLocation ($3), "`{0}.{1}': event property must have both add and remove accessors",
current_container.GetSignatureForError (), name.GetSignatureForError ());
$8 = new Accessors (null, null);
}
Accessors accessors = (Accessors) $8;
if (accessors.get_or_add == null || accessors.set_or_remove == null)
// CS0073 is already reported, so no CS0065 here.
$$ = null;
else {
Event e = new EventProperty (
current_class, (FullNamedExpression) $4, (Modifiers) $2, name,
(Attributes) $1, accessors.get_or_add, accessors.set_or_remove);
if (RootContext.Documentation != null) {
e.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
current_container.AddEvent (e);
implicit_value_parameter_type = null;
}
current_local_parameters = null;
}
| opt_attributes opt_modifiers EVENT type member_declaration_name error
{
MemberName mn = (MemberName) $5;
if (mn.Left != null)
Report.Error (71, mn.Location, "An explicit interface implementation of an event must use property syntax");
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
Error_SyntaxError (yyToken);
$$ = null;
}
;
event_accessor_declarations
: add_accessor_declaration remove_accessor_declaration
{
$$ = new Accessors ((Accessor) $1, (Accessor) $2);
}
| remove_accessor_declaration add_accessor_declaration
{
Accessors accessors = new Accessors ((Accessor) $2, (Accessor) $1);
accessors.declared_in_reverse = true;
$$ = accessors;
}
| add_accessor_declaration { $$ = null; }
| remove_accessor_declaration { $$ = null; }
| error
{
Report.Error (1055, GetLocation ($1), "An add or remove accessor expected");
$$ = null;
}
| { $$ = null; }
;
add_accessor_declaration
: opt_attributes ADD
{
lexer.EventParsing = false;
}
block
{
Accessor accessor = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, null, GetLocation ($2));
lexer.EventParsing = true;
$$ = accessor;
}
| opt_attributes ADD error {
Report.Error (73, GetLocation ($2), "An add or remove accessor must have a body");
$$ = null;
}
| opt_attributes modifiers ADD {
Report.Error (1609, GetLocation ($3), "Modifiers cannot be placed on event accessor declarations");
$$ = null;
}
;
remove_accessor_declaration
: opt_attributes REMOVE
{
lexer.EventParsing = false;
}
block
{
$$ = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, null, GetLocation ($2));
lexer.EventParsing = true;
}
| opt_attributes REMOVE error {
Report.Error (73, GetLocation ($2), "An add or remove accessor must have a body");
$$ = null;
}
| opt_attributes modifiers REMOVE {
Report.Error (1609, GetLocation ($3), "Modifiers cannot be placed on event accessor declarations");
$$ = 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;
implicit_value_parameter_type = (FullNamedExpression) $3;
indexer_parameters = (ParametersCompiled) $7;
if (indexer_parameters.IsEmpty) {
Report.Error (1551, GetLocation ($5), "Indexers must have at least one parameter");
}
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
lexer.PropertyParsing = true;
parsing_indexer = true;
}
accessor_declarations
{
lexer.PropertyParsing = false;
has_get = has_set = false;
parsing_indexer = false;
}
CLOSE_BRACE
{
Accessors accessors = (Accessors) $11;
Accessor get_block = accessors != null ? accessors.get_or_add : null;
Accessor set_block = accessors != null ? accessors.set_or_remove : null;
bool order = accessors != null ? accessors.declared_in_reverse : false;
Indexer indexer = new Indexer (current_class, (FullNamedExpression) $3,
(MemberName)$4, (Modifiers) $2, (ParametersCompiled) $7, (Attributes) $1,
get_block, set_block, order);
if ($3 == TypeManager.system_void_expr)
Report.Error (620, GetLocation ($3), "`{0}': indexer return type cannot be `void'", indexer.GetSignatureForError ());
if (accessors == null)
Report.Error (548, indexer.Location, "`{0}': property or indexer must have at least one accessor", indexer.GetSignatureForError ());
if (current_container.Kind == Kind.Interface) {
if (indexer.Get.Block != null)
Report.Error (531, indexer.Location, "`{0}.get': interface members cannot have a definition", indexer.GetSignatureForError ());
if (indexer.Set.Block != null)
Report.Error (531, indexer.Location, "`{0}.set': interface members cannot have a definition", indexer.GetSignatureForError ());
}
if (RootContext.Documentation != null)
indexer.DocComment = ConsumeStoredComment ();
current_container.AddIndexer (indexer);
current_local_parameters = null;
implicit_value_parameter_type = null;
indexer_parameters = null;
}
;
enum_declaration
: opt_attributes
opt_modifiers
ENUM type_declaration_name
opt_enum_base {
if (RootContext.Documentation != null)
enumTypeComment = Lexer.consume_doc_comment ();
}
enum_body
opt_semicolon
{
MemberName name = (MemberName) $4;
if (name.IsGeneric) {
Report.Error (1675, name.Location, "Enums cannot have type parameters");
}
name = MakeName (name);
Enum e = new Enum (current_namespace, current_class, (TypeExpr) $5, (Modifiers) $2,
name, (Attributes) $1);
if (RootContext.Documentation != null)
e.DocComment = enumTypeComment;
EnumMember em = null;
foreach (VariableDeclaration ev in (IList) $7) {
em = new EnumMember (
e, em, ev.identifier, ev.GetInitializer ((FullNamedExpression) $5),
ev.OptAttributes, ev.Location);
// if (RootContext.Documentation != null)
em.DocComment = ev.DocComment;
e.AddEnumMember (em);
}
if (RootContext.EvalMode)
undo.AddTypeContainer (current_container, e);
current_container.AddTypeContainer (e);
$$ = e;
}
;
opt_enum_base
: /* empty */
{
$$ = TypeManager.system_int32_expr;
}
| COLON type
{
if ($2 != TypeManager.system_int32_expr && $2 != TypeManager.system_uint32_expr &&
$2 != TypeManager.system_int64_expr && $2 != TypeManager.system_uint64_expr &&
$2 != TypeManager.system_int16_expr && $2 != TypeManager.system_uint16_expr &&
$2 != TypeManager.system_byte_expr && $2 != TypeManager.system_sbyte_expr) {
Enum.Error_1008 (GetLocation ($2), Report);
$2 = TypeManager.system_int32_expr;
}
$$ = $2;
}
| COLON error
{
Error_TypeExpected (lexer.Location);
$$ = TypeManager.system_int32_expr;
}
;
enum_body
: OPEN_BRACE
{
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
opt_enum_member_declarations
{
// here will be evaluated after CLOSE_BLACE is consumed.
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
CLOSE_BRACE
{
$$ = $3;
}
;
opt_enum_member_declarations
: /* empty */ { $$ = new VariableDeclaration [0]; }
| enum_member_declarations opt_comma { $$ = $1; }
;
enum_member_declarations
: enum_member_declaration
{
var l = new List (4);
l.Add ((VariableDeclaration) $1);
$$ = l;
}
| enum_member_declarations COMMA enum_member_declaration
{
var l = (List) $1;
l.Add ((VariableDeclaration) $3);
$$ = l;
}
;
enum_member_declaration
: opt_attributes IDENTIFIER
{
VariableDeclaration vd = new VariableDeclaration (
(Tokenizer.LocatedToken) $2, null, (Attributes) $1);
if (RootContext.Documentation != null) {
vd.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
$$ = vd;
}
| opt_attributes IDENTIFIER
{
++lexer.parsing_block;
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
}
ASSIGN constant_expression
{
--lexer.parsing_block;
VariableDeclaration vd = new VariableDeclaration (
(Tokenizer.LocatedToken) $2, (Expression) $5, (Attributes) $1);
if (RootContext.Documentation != null)
vd.DocComment = ConsumeStoredComment ();
$$ = vd;
}
;
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;
MemberName name = MakeName ((MemberName) $5);
ParametersCompiled p = (ParametersCompiled) $8;
Delegate del = new Delegate (current_namespace, current_class, (FullNamedExpression) $4,
(Modifiers) $2, name, p, (Attributes) $1);
if (RootContext.Documentation != null) {
del.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
current_container.AddDelegate (del);
current_delegate = del;
lexer.ConstraintsParsing = true;
}
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
}
SEMICOLON
{
current_delegate.SetParameterInfo ((List) $11);
$$ = current_delegate;
current_delegate = null;
}
;
opt_nullable
: /* empty */
{
$$ = null;
}
| INTERR_NULLABLE
{
if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2)
Report.FeatureIsNotSupported (GetLocation ($1), "nullable types");
else if (RootContext.Version < LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "nullable types");
$$ = this;
}
;
namespace_or_type_name
: member_name
| qualified_alias_member IDENTIFIER opt_type_argument_list
{
var lt1 = (Tokenizer.LocatedToken) $1;
var lt2 = (Tokenizer.LocatedToken) $2;
$$ = new MemberName (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location);
}
;
member_name
: type_name
| namespace_or_type_name DOT IDENTIFIER opt_type_argument_list
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location);
}
;
type_name
: IDENTIFIER opt_type_argument_list
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new MemberName (lt.Value, (TypeArguments)$2, lt.Location);
}
;
//
// Generics arguments (any type, without attributes)
//
opt_type_argument_list
: /* empty */ { $$ = null; }
| OP_GENERICS_LT type_arguments OP_GENERICS_GT
{
if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2)
Report.FeatureIsNotSupported (GetLocation ($1), "generics");
else if (RootContext.Version < LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "generics");
$$ = $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;
}
| type_arguments COMMA type
{
TypeArguments type_args = (TypeArguments) $1;
type_args.Add ((FullNamedExpression) $3);
$$ = type_args;
}
;
//
// 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, (TypeArguments)$3, lt.Location);
}
;
member_declaration_name
: method_declaration_name
{
MemberName mn = (MemberName)$1;
if (mn.TypeArguments != 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 ((MemberName) $1, lt.Value, (TypeArguments) $3, lt.Location);
}
;
indexer_declaration_name
: THIS
{
lexer.parsing_generic_declaration = false;
$$ = new MemberName (TypeContainer.DefaultIndexerName, GetLocation ($1));
}
| explicit_interface THIS
{
lexer.parsing_generic_declaration = false;
$$ = new MemberName ((MemberName) $1, TypeContainer.DefaultIndexerName, null, GetLocation ($1));
}
;
explicit_interface
: IDENTIFIER opt_type_argument_list DOT
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new MemberName (lt.Value, (TypeArguments) $2, lt.Location);
}
| qualified_alias_member IDENTIFIER opt_type_argument_list DOT
{
var lt1 = (Tokenizer.LocatedToken) $1;
var lt2 = (Tokenizer.LocatedToken) $2;
$$ = new MemberName (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location);
}
| explicit_interface IDENTIFIER opt_type_argument_list DOT
{
var lt = (Tokenizer.LocatedToken) $2;
$$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $3, lt.Location);
}
;
opt_type_parameter_list
: /* empty */ { $$ = null; }
| OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT
{
if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2)
Report.FeatureIsNotSupported (GetLocation ($1), "generics");
else if (RootContext.Version < LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "generics");
$$ = $2;
}
;
type_parameters
: type_parameter
{
TypeArguments type_args = new TypeArguments ();
type_args.Add ((FullNamedExpression)$1);
$$ = type_args;
}
| type_parameters COMMA type_parameter
{
TypeArguments type_args = (TypeArguments) $1;
type_args.Add ((FullNamedExpression)$3);
$$ = type_args;
}
;
type_parameter
: opt_attributes opt_type_parameter_variance IDENTIFIER
{
var lt = (Tokenizer.LocatedToken)$3;
$$ = new TypeParameterName (lt.Value, (Attributes)$1, (Variance) $2, lt.Location);
}
| 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 TypeParameterName ("", null, lexer.Location);
}
;
//
// All types where void is allowed
//
type_and_void
: type_expression_or_array
| VOID
{
$$ = TypeManager.system_void_expr;
}
;
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);
$$ = TypeManager.system_void_expr;
}
;
simple_type
: type_expression
| VOID
{
Expression.Error_VoidInvalidInTheContext (GetLocation ($1), Report);
$$ = TypeManager.system_void_expr;
}
;
parameter_type
: type_expression_or_array
| VOID
{
Report.Error (1536, GetLocation ($1), "Invalid parameter type `void'");
$$ = TypeManager.system_void_expr;
}
;
type_expression_or_array
: type_expression
| type_expression rank_specifiers
{
string rank_specifiers = (string) $2;
$$ = new ComposedCast ((FullNamedExpression) $1, rank_specifiers);
}
;
type_expression
: namespace_or_type_name opt_nullable
{
MemberName name = (MemberName) $1;
if ($2 != null) {
$$ = new ComposedCast (name.GetTypeExpression (), "?", lexer.Location);
} else {
if (name.Left == null && name.Name == "var")
$$ = new VarExpr (name.Location);
else
$$ = name.GetTypeExpression ();
}
}
| builtin_types opt_nullable
{
if ($2 != null)
$$ = new ComposedCast ((FullNamedExpression) $1, "?", lexer.Location);
}
| type_expression STAR
{
//
// Note that here only unmanaged types are allowed but we
// can't perform checks during this phase - we do it during
// semantic analysis.
//
$$ = new ComposedCast ((FullNamedExpression) $1, "*", Lexer.Location);
}
| VOID STAR
{
$$ = new ComposedCast (TypeManager.system_void_expr, "*", GetLocation ($1));
}
;
type_list
: base_type_name
{
var types = new List (2);
types.Add ((FullNamedExpression) $1);
$$ = types;
}
| type_list COMMA base_type_name
{
var types = (List) $1;
types.Add ((FullNamedExpression) $3);
$$ = types;
}
;
base_type_name
: type
{
if ($1 is ComposedCast)
Report.Error (1521, GetLocation ($1), "Invalid base type `{0}'", ((ComposedCast)$1).GetSignatureForError ());
$$ = $1;
}
| error
{
Error_TypeExpected (lexer.Location);
$$ = null;
}
;
/*
* replaces all the productions for isolating the various
* simple types, but we need this to reuse it easily in variable_type
*/
builtin_types
: OBJECT { $$ = TypeManager.system_object_expr; }
| STRING { $$ = TypeManager.system_string_expr; }
| BOOL { $$ = TypeManager.system_boolean_expr; }
| DECIMAL { $$ = TypeManager.system_decimal_expr; }
| FLOAT { $$ = TypeManager.system_single_expr; }
| DOUBLE { $$ = TypeManager.system_double_expr; }
| integral_type
;
integral_type
: SBYTE { $$ = TypeManager.system_sbyte_expr; }
| BYTE { $$ = TypeManager.system_byte_expr; }
| SHORT { $$ = TypeManager.system_int16_expr; }
| USHORT { $$ = TypeManager.system_uint16_expr; }
| INT { $$ = TypeManager.system_int32_expr; }
| UINT { $$ = TypeManager.system_uint32_expr; }
| LONG { $$ = TypeManager.system_int64_expr; }
| ULONG { $$ = TypeManager.system_uint64_expr; }
| CHAR { $$ = TypeManager.system_char_expr; }
;
predefined_type
: builtin_types
| VOID
{
$$ = TypeManager.system_void_expr;
}
;
//
// Expressions, section 7.5
//
primary_expression
: primary_expression_no_array_creation
| array_creation_expression
;
primary_expression_no_array_creation
: literal
| IDENTIFIER opt_type_argument_list
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new SimpleName (MemberName.MakeName (lt.Value, (TypeArguments)$2), (TypeArguments)$2, lt.Location);
}
| IDENTIFIER GENERATE_COMPLETION {
var lt = (Tokenizer.LocatedToken) $1;
$$ = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location);
}
| parenthesized_expression
| default_value_expression
| member_access
| 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
;
literal
: boolean_literal
| LITERAL
| NULL { $$ = new NullLiteral (GetLocation ($1)); }
;
boolean_literal
: TRUE { $$ = new BoolLiteral (true, GetLocation ($1)); }
| FALSE { $$ = new BoolLiteral (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
| OPEN_PARENS_LAMBDA
;
parenthesized_expression
: OPEN_PARENS expression CLOSE_PARENS
{
$$ = new ParenthesizedExpression ((Expression) $2);
}
| 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);
}
| predefined_type DOT IDENTIFIER opt_type_argument_list
{
var lt = (Tokenizer.LocatedToken) $3;
// TODO: Location is wrong as some predefined types doesn't hold a location
$$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location);
}
| 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);
}
| 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);
}
| predefined_type DOT GENERATE_COMPLETION
{
// TODO: Location is wrong as some predefined types doesn't hold a location
$$ = new CompletionMemberAccess ((Expression) $1, null, lexer.Location);
}
| predefined_type 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);
}
;
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)
$$ = CollectionOrObjectInitializers.Empty;
else
$$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1));
}
| OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE
{
$$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1));
}
;
opt_member_initializer_list
: /* empty */ { $$ = null; }
| member_initializer_list
{
$$ = $1;
}
;
member_initializer_list
: member_initializer
{
var a = new List ();
a.Add ((Expression) $1);
$$ = a;
}
| member_initializer_list COMMA member_initializer
{
var a = (List)$1;
a.Add ((Expression) $3);
$$ = a;
}
;
member_initializer
: IDENTIFIER ASSIGN initializer_value
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location);
}
| 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
{
$$ = new CollectionElementInitializer ((List)$2, GetLocation ($1));
}
| OPEN_BRACE CLOSE_BRACE
{
Report.Error (1920, GetLocation ($1), "An element initializer cannot be empty");
$$ = null;
}
;
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);
$$ = 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);
$$ = list;
}
| argument_list COMMA
{
Report.Error (839, GetLocation ($2), "An argument is missing");
$$ = null;
}
| COMMA argument_or_named_argument
{
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);
}
| OUT variable_reference
{
$$ = new Argument ((Expression) $2, Argument.AType.Out);
}
| ARGLIST open_parens_any argument_list CLOSE_PARENS
{
$$ = new Argument (new Arglist ((Arguments) $3, GetLocation ($1)));
}
| ARGLIST open_parens_any CLOSE_PARENS
{
$$ = new Argument (new Arglist (GetLocation ($1)));
}
| ARGLIST
{
$$ = new Argument (new ArglistAccess (GetLocation ($1)));
}
;
variable_reference
: expression
;
element_access
: primary_expression_no_array_creation OPEN_BRACKET expression_list_arguments CLOSE_BRACKET
{
$$ = new ElementAccess ((Expression) $1, (Arguments) $3);
}
| array_creation_expression OPEN_BRACKET expression_list_arguments CLOSE_BRACKET
{
// LAMESPEC: Not allowed according to specification
$$ = new ElementAccess ((Expression) $1, (Arguments) $3);
}
| primary_expression_no_array_creation rank_specifiers
{
// 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 (expr is ComposedCast){
$$ = new ComposedCast ((ComposedCast)expr, (string) $2);
} else if (expr is ATypeNameExpression){
//
// So we extract the string corresponding to the SimpleName
// or MemberAccess
//
$$ = new ComposedCast ((ATypeNameExpression)expr, (string) $2);
} else {
Error_ExpectingTypeName (expr);
$$ = TypeManager.system_object_expr;
}
}
;
expression_list
: expression
{
var list = new List (4);
list.Add ((Expression) $1);
$$ = list;
}
| expression_list COMMA expression
{
var list = (List) $1;
list.Add ((Expression) $3);
$$ = list;
}
;
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;
args.Add ((Argument) $3);
$$ = args;
}
;
expression_list_argument
: expression
{
$$ = new Argument ((Expression) $1);
}
| named_argument
;
this_access
: THIS
{
$$ = new This (current_block, GetLocation ($1));
}
;
base_access
: BASE DOT IDENTIFIER opt_type_argument_list
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new BaseAccess (lt.Value, (TypeArguments) $4, lt.Location);
}
| BASE OPEN_BRACKET expression_list_arguments CLOSE_BRACKET
{
$$ = new BaseIndexerAccess ((Arguments) $3, GetLocation ($1));
}
| BASE error
{
Error_SyntaxError (yyToken);
$$ = new BaseAccess (null, GetLocation ($2));
}
;
post_increment_expression
: primary_expression OP_INC
{
$$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) $1);
}
;
post_decrement_expression
: primary_expression OP_DEC
{
$$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) $1);
}
;
object_or_delegate_creation_expression
: new_expr_start open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer
{
if ($5 != null) {
if (RootContext.Version <= LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "object initializers");
$$ = new NewInitialize ((Expression) $1, (Arguments) $3, (CollectionOrObjectInitializers) $5, GetLocation ($1));
}
else
$$ = new New ((Expression) $1, (Arguments) $3, GetLocation ($1));
}
| new_expr_start object_or_collection_initializer
{
if (RootContext.Version <= LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "collection initializers");
$$ = new NewInitialize ((Expression) $1, null, (CollectionOrObjectInitializers) $2, GetLocation ($1));
}
;
array_creation_expression
: new_expr_start OPEN_BRACKET expression_list CLOSE_BRACKET
opt_rank_specifier // shift/reduce on OPEN_BRACE
opt_array_initializer
{
$$ = new ArrayCreation ((FullNamedExpression) $1, (List) $3, (string) $5, (ArrayInitializer) $6, GetLocation ($1));
}
| new_expr_start rank_specifiers opt_array_initializer
{
if ($3 == null)
Report.Error (1586, GetLocation ($1), "Array creation must have array size or array initializer");
$$ = new ArrayCreation ((FullNamedExpression) $1, (string) $2, (ArrayInitializer) $3, GetLocation ($1));
}
| NEW rank_specifiers array_initializer
{
if (RootContext.Version <= LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "implicitly typed arrays");
$$ = new ImplicitlyTypedArrayCreation ((string) $2, (ArrayInitializer) $3, GetLocation ($1));
}
| new_expr_start error
{
Report.Error (1526, GetLocation ($1), "A new expression requires () or [] after type");
$$ = new ArrayCreation ((FullNamedExpression) $1, "[]", null, GetLocation ($1));
}
;
new_expr_start
: NEW
{
++lexer.parsing_type;
}
simple_type
{
--lexer.parsing_type;
$$ = $3;
}
;
anonymous_type_expression
: NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE
{
if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2)
Report.FeatureIsNotSupported (GetLocation ($1), "anonymous types");
else if (RootContext.Version <= LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "anonymous types");
$$ = new NewAnonymousType ((List) $3, current_container, GetLocation ($1));
}
;
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 (4);
a.Add ((AnonymousTypeParameter) $1);
$$ = a;
}
| anonymous_type_parameters COMMA anonymous_type_parameter
{
var a = (List) $1;
a.Add ((AnonymousTypeParameter) $3);
$$ = a;
}
;
anonymous_type_parameter
: IDENTIFIER ASSIGN variable_initializer
{
var lt = (Tokenizer.LocatedToken)$1;
$$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location);
}
| IDENTIFIER
{
var lt = (Tokenizer.LocatedToken)$1;
$$ = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location),
lt.Value, lt.Location);
}
| BASE DOT IDENTIFIER opt_type_argument_list
{
var lt = (Tokenizer.LocatedToken) $3;
BaseAccess ba = new BaseAccess (lt.Value, (TypeArguments) $4, lt.Location);
$$ = new AnonymousTypeParameter (ba, 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
{
$$ = $1;
}
;
opt_rank_specifier_or_nullable
: opt_nullable
{
if ($1 != null)
$$ = "?";
else
$$ = string.Empty;
}
| opt_nullable rank_specifiers
{
if ($1 != null)
$$ = "?" + (string) $2;
else
$$ = $2;
}
;
rank_specifiers
: rank_specifier
| rank_specifier rank_specifiers
{
$$ = (string) $2 + (string) $1;
}
;
rank_specifier
: OPEN_BRACKET CLOSE_BRACKET
{
$$ = "[]";
}
| OPEN_BRACKET dim_separators CLOSE_BRACKET
{
$$ = "[" + (string) $2 + "]";
}
| OPEN_BRACKET error
{
Error_SyntaxError (178, yyToken, "Invalid rank specifier");
$$ = "[]";
}
;
dim_separators
: COMMA
{
$$ = ",";
}
| dim_separators COMMA
{
$$ = (string) $1 + ",";
}
;
opt_array_initializer
: /* empty */
{
$$ = null;
}
| array_initializer
{
$$ = $1;
}
;
array_initializer
: OPEN_BRACE CLOSE_BRACE
{
$$ = new ArrayInitializer (0, GetLocation ($1));
}
| OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
{
$$ = new ArrayInitializer ((List) $2, GetLocation ($1));
}
;
variable_initializer_list
: variable_initializer
{
var list = new List (4);
list.Add ((Expression) $1);
$$ = list;
}
| variable_initializer_list COMMA variable_initializer
{
var list = (List) $1;
list.Add ((Expression) $3);
$$ = list;
}
| error
{
Error_SyntaxError (yyToken);
$$ = new List ();
}
;
typeof_expression
: TYPEOF
{
lexer.TypeOfParsing = true;
}
open_parens_any typeof_type_expression CLOSE_PARENS
{
lexer.TypeOfParsing = false;
Expression type = (Expression)$4;
if (type == TypeManager.system_void_expr)
$$ = new TypeOfVoid (GetLocation ($1));
else
$$ = new TypeOf (type, GetLocation ($1));
}
;
typeof_type_expression
: type_and_void
| unbound_type_name
| error
{
Error_TypeExpected (lexer.Location);
$$ = null;
}
;
unbound_type_name
: IDENTIFIER generic_dimension
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new SimpleName (MemberName.MakeName (lt.Value, (int)$2), lt.Location);
}
| qualified_alias_member IDENTIFIER generic_dimension
{
var lt1 = (Tokenizer.LocatedToken) $1;
var lt2 = (Tokenizer.LocatedToken) $2;
$$ = new QualifiedAliasMember (lt1.Value, MemberName.MakeName (lt2.Value, (int) $3), lt1.Location);
}
| unbound_type_name DOT IDENTIFIER
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location);
}
| unbound_type_name DOT IDENTIFIER generic_dimension
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new MemberAccess ((Expression) $1, MemberName.MakeName (lt.Value, (int) $4), lt.Location);
}
| namespace_or_type_name DOT IDENTIFIER generic_dimension
{
var lt = (Tokenizer.LocatedToken) $3;
MemberName name = (MemberName) $1;
$$ = new MemberAccess (name.GetTypeExpression (), MemberName.MakeName (lt.Value, (int) $4), lt.Location);
}
;
generic_dimension
: GENERIC_DIMENSION
{
if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2)
Report.FeatureIsNotSupported (GetLocation ($1), "generics");
else if (RootContext.Version < LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "generics");
$$ = $1;
}
;
qualified_alias_member
: IDENTIFIER DOUBLE_COLON
{
var lt = (Tokenizer.LocatedToken) $1;
if (RootContext.Version == LanguageVersion.ISO_1)
Report.FeatureIsNotAvailable (lt.Location, "namespace alias qualifier");
$$ = lt;
}
;
sizeof_expression
: SIZEOF open_parens_any type CLOSE_PARENS {
$$ = new SizeOf ((Expression) $3, GetLocation ($1));
}
;
checked_expression
: CHECKED open_parens_any expression CLOSE_PARENS
{
$$ = new CheckedExpr ((Expression) $3, GetLocation ($1));
}
;
unchecked_expression
: UNCHECKED open_parens_any expression CLOSE_PARENS
{
$$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1));
}
;
pointer_member_access
: primary_expression OP_PTR IDENTIFIER
{
Expression deref;
var lt = (Tokenizer.LocatedToken) $3;
deref = new Indirection ((Expression) $1, lt.Location);
$$ = new MemberAccess (deref, lt.Value);
}
;
anonymous_method_expression
: DELEGATE opt_anonymous_method_signature
{
start_anonymous (false, (ParametersCompiled) $2, GetLocation ($1));
}
block
{
$$ = end_anonymous ((ToplevelBlock) $4);
}
;
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;
}
;
default_value_expression
: DEFAULT open_parens_any type CLOSE_PARENS
{
if (RootContext.Version < LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($1), "default value expression");
$$ = new DefaultValueExpression ((Expression) $3, GetLocation ($1));
}
;
unary_expression
: primary_expression
| BANG prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2);
}
| TILDE prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2);
}
| cast_expression
;
cast_expression
: OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression
{
$$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1));
}
| OPEN_PARENS predefined_type CLOSE_PARENS prefixed_unary_expression
{
$$ = new Cast ((FullNamedExpression) $2, (Expression) $4, 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);
}
| MINUS prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2);
}
| OP_INC prefixed_unary_expression
{
$$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) $2);
}
| OP_DEC prefixed_unary_expression
{
$$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) $2);
}
| STAR prefixed_unary_expression
{
$$ = new Indirection ((Expression) $2, GetLocation ($1));
}
| BITWISE_AND prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.AddressOf, (Expression) $2);
}
;
multiplicative_expression
: prefixed_unary_expression
| multiplicative_expression STAR prefixed_unary_expression
{
$$ = new Binary (Binary.Operator.Multiply,
(Expression) $1, (Expression) $3);
}
| multiplicative_expression DIV prefixed_unary_expression
{
$$ = new Binary (Binary.Operator.Division,
(Expression) $1, (Expression) $3);
}
| multiplicative_expression PERCENT prefixed_unary_expression
{
$$ = new Binary (Binary.Operator.Modulus,
(Expression) $1, (Expression) $3);
}
;
additive_expression
: multiplicative_expression
| additive_expression PLUS multiplicative_expression
{
$$ = new Binary (Binary.Operator.Addition,
(Expression) $1, (Expression) $3);
}
| additive_expression MINUS multiplicative_expression
{
$$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3);
}
| parenthesized_expression MINUS multiplicative_expression
{
// Shift/Reduce conflict
$$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3);
}
| 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);
}
| shift_expression OP_SHIFT_RIGHT additive_expression
{
$$ = new Binary (Binary.Operator.RightShift,
(Expression) $1, (Expression) $3);
}
;
relational_expression
: shift_expression
| relational_expression OP_LT shift_expression
{
$$ = new Binary (Binary.Operator.LessThan,
(Expression) $1, (Expression) $3);
}
| relational_expression OP_GT shift_expression
{
$$ = new Binary (Binary.Operator.GreaterThan,
(Expression) $1, (Expression) $3);
}
| relational_expression OP_LE shift_expression
{
$$ = new Binary (Binary.Operator.LessThanOrEqual,
(Expression) $1, (Expression) $3);
}
| relational_expression OP_GE shift_expression
{
$$ = new Binary (Binary.Operator.GreaterThanOrEqual,
(Expression) $1, (Expression) $3);
}
;
equality_expression
: relational_expression
| equality_expression OP_EQ relational_expression
{
$$ = new Binary (Binary.Operator.Equality,
(Expression) $1, (Expression) $3);
}
| equality_expression OP_NE relational_expression
{
$$ = new Binary (Binary.Operator.Inequality,
(Expression) $1, (Expression) $3);
}
;
and_expression
: equality_expression
| and_expression BITWISE_AND equality_expression
{
$$ = new Binary (Binary.Operator.BitwiseAnd,
(Expression) $1, (Expression) $3);
}
;
exclusive_or_expression
: and_expression
| exclusive_or_expression CARRET and_expression
{
$$ = new Binary (Binary.Operator.ExclusiveOr,
(Expression) $1, (Expression) $3);
}
;
inclusive_or_expression
: exclusive_or_expression
| inclusive_or_expression BITWISE_OR exclusive_or_expression
{
$$ = new Binary (Binary.Operator.BitwiseOr,
(Expression) $1, (Expression) $3);
}
;
conditional_and_expression
: inclusive_or_expression
| conditional_and_expression OP_AND inclusive_or_expression
{
$$ = new Binary (Binary.Operator.LogicalAnd,
(Expression) $1, (Expression) $3);
}
;
conditional_or_expression
: conditional_and_expression
| conditional_or_expression OP_OR conditional_and_expression
{
$$ = new Binary (Binary.Operator.LogicalOr,
(Expression) $1, (Expression) $3);
}
;
null_coalescing_expression
: conditional_or_expression
| conditional_or_expression OP_COALESCING null_coalescing_expression
{
if (RootContext.Version < LanguageVersion.ISO_2)
Report.FeatureIsNotAvailable (GetLocation ($2), "null coalescing operator");
$$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3, GetLocation ($2));
}
;
conditional_expression
: null_coalescing_expression
| null_coalescing_expression INTERR expression COLON expression
{
$$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5);
}
;
assignment_expression
: prefixed_unary_expression ASSIGN expression
{
$$ = new SimpleAssign ((Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_MULT_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.Multiply, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_DIV_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.Division, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_MOD_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.Modulus, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_ADD_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.Addition, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_SUB_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.Subtraction, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.LeftShift, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.RightShift, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_AND_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_OR_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3);
}
| prefixed_unary_expression OP_XOR_ASSIGN expression
{
$$ = new CompoundAssign (
Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3);
}
;
lambda_parameter_list
: lambda_parameter
{
var pars = new List (4);
pars.Add ((Parameter) $1);
$$ = pars;
}
| lambda_parameter_list COMMA lambda_parameter
{
var pars = (List) $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);
$$ = pars;
}
;
lambda_parameter
: parameter_modifier parameter_type IDENTIFIER
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new Parameter ((FullNamedExpression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location);
}
| parameter_type IDENTIFIER
{
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) $1;
$$ = new ParametersCompiled (compiler, pars_list.ToArray ());
}
;
lambda_expression_body
: {
start_block (lexer.Location);
}
expression
{
Block b = end_block (lexer.Location);
b.AddStatement (new ContextualReturn ((Expression) $2));
$$ = b;
}
| block {
$$ = $1;
}
;
lambda_expression
: IDENTIFIER ARROW
{
var lt = (Tokenizer.LocatedToken) $1;
Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location);
start_anonymous (true, new ParametersCompiled (compiler, p), GetLocation ($1));
}
lambda_expression_body
{
$$ = end_anonymous ((ToplevelBlock) $4);
}
| 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, GetLocation ($1));
}
lambda_expression_body
{
$$ = end_anonymous ((ToplevelBlock) $7);
}
;
expression
: assignment_expression
| non_assignment_expression
;
non_assignment_expression
: conditional_expression
| lambda_expression
| query_expression
;
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
{
MemberName name = MakeName ((MemberName) $6);
push_current_class (new Class (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3);
}
opt_class_base
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
current_class.SetParameterInfo ((List) $9);
if (RootContext.Documentation != null) {
current_container.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
class_body
{
--lexer.parsing_declaration;
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
opt_semicolon
{
$$ = pop_current_class ();
}
;
opt_partial
: /* empty */
{ $$ = null; }
| PARTIAL
{ $$ = $1; } // location
;
opt_modifiers
: /* empty */ { $$ = (int) 0; }
| modifiers
;
modifiers
: modifier
| modifiers modifier
{
var m1 = (Modifiers) $1;
var m2 = (Modifiers) $2;
if ((m1 & m2) != 0) {
Location l = lexer.Location;
Report.Error (1004, l, "Duplicate `{0}' modifier", ModifiersExtensions.Name (m2));
}
$$ = m1 | m2;
}
;
modifier
: NEW
{
$$ = Modifiers.NEW;
if (current_container == RootContext.ToplevelTypes)
Report.Error (1530, GetLocation ($1), "Keyword `new' is not allowed on namespace elements");
}
| PUBLIC { $$ = Modifiers.PUBLIC; }
| PROTECTED { $$ = Modifiers.PROTECTED; }
| INTERNAL { $$ = Modifiers.INTERNAL; }
| PRIVATE { $$ = Modifiers.PRIVATE; }
| ABSTRACT { $$ = Modifiers.ABSTRACT; }
| SEALED { $$ = Modifiers.SEALED; }
| STATIC { $$ = Modifiers.STATIC; }
| READONLY { $$ = Modifiers.READONLY; }
| VIRTUAL { $$ = Modifiers.VIRTUAL; }
| OVERRIDE { $$ = Modifiers.OVERRIDE; }
| EXTERN { $$ = Modifiers.EXTERN; }
| VOLATILE { $$ = Modifiers.VOLATILE; }
| UNSAFE { $$ = Modifiers.UNSAFE; }
;
opt_class_base
: /* empty */
| class_base
;
class_base
: COLON type_list
{
current_container.AddBasesForPart (current_class, (List) $2);
}
;
opt_type_parameter_constraints_clauses
: /* empty */ { $$ = null; }
| type_parameter_constraints_clauses
{ $$ = $1; }
;
type_parameter_constraints_clauses
: type_parameter_constraints_clause {
var constraints = new List (1);
constraints.Add ((Constraints) $1);
$$ = constraints;
}
| type_parameter_constraints_clauses type_parameter_constraints_clause {
var constraints = (List) $1;
Constraints new_constraint = (Constraints)$2;
foreach (Constraints c in constraints) {
if (new_constraint.TypeParameter == c.TypeParameter) {
Report.Error (409, new_constraint.Location, "A constraint clause has already been specified for type parameter `{0}'",
new_constraint.TypeParameter);
}
}
constraints.Add (new_constraint);
$$ = constraints;
}
;
type_parameter_constraints_clause
: WHERE IDENTIFIER COLON type_parameter_constraints {
var lt = (Tokenizer.LocatedToken) $2;
$$ = new Constraints (lt.Value, (List) $4, lt.Location);
}
;
type_parameter_constraints
: type_parameter_constraint {
var constraints = new List (1);
constraints.Add ($1);
$$ = constraints;
}
| type_parameter_constraints COMMA type_parameter_constraint {
var constraints = (List) $1;
constraints.Add ($3);
$$ = constraints;
}
;
type_parameter_constraint
: type
| NEW OPEN_PARENS CLOSE_PARENS {
$$ = SpecialConstraint.Constructor;
}
| CLASS {
$$ = SpecialConstraint.ReferenceType;
}
| STRUCT {
$$ = SpecialConstraint.ValueType;
}
;
opt_type_parameter_variance
: /* empty */
{
$$ = Variance.None;
}
| type_parameter_variance
{
if (RootContext.MetadataCompatibilityVersion < MetadataVersion.v2)
Report.FeatureIsNotSupported (lexer.Location, "generic type variance");
else if (RootContext.Version <= LanguageVersion.V_3)
Report.FeatureIsNotAvailable (lexer.Location, "generic type variance");
$$ = $1;
}
;
type_parameter_variance
: OUT
{
$$ = Variance.Covariant;
}
| IN
{
$$ = Variance.Contravariant;
}
;
//
// 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));
}
;
opt_statement_list
: /* empty */
| statement_list
;
statement_list
: statement
| statement_list statement
;
statement
: declaration_statement
{
if ($1 != null && (Block) $1 != current_block){
current_block.AddStatement ((Statement) $1);
current_block = (Block) $1;
}
}
| valid_declaration_statement
{
current_block.AddStatement ((Statement) $1);
}
| labeled_statement
;
//
// 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
: declaration_statement
{
if ($1 != null && (Block) $1 != current_block){
current_block.AddStatement ((Statement) $1);
current_block = (Block) $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
| declaration_statement
{
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;
}
;
empty_statement
: SEMICOLON
{
$$ = EmptyStatement.Value;
}
;
labeled_statement
: IDENTIFIER COLON
{
var lt = (Tokenizer.LocatedToken) $1;
LabeledStatement labeled = new LabeledStatement (lt.Value, lt.Location);
if (current_block.AddLabel (labeled))
current_block.AddStatement (labeled);
}
statement
;
declaration_statement
: local_variable_declaration SEMICOLON
{
if ($1 != null){
var de = (Tuple>) $1;
$$ = declare_local_variables (de.Item1, de.Item2, de.Item1.Location);
}
}
| local_constant_declaration SEMICOLON
{
if ($1 != null){
var de = (Tuple>) $1;
$$ = declare_local_constants (de.Item1, de.Item2);
}
}
;
/*
* 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
: primary_expression_no_array_creation opt_rank_specifier_or_nullable
{
// FIXME: Do something smart here regarding the composition of the type.
// Ok, the above "primary_expression" is there to get rid of
// both reduce/reduce and shift/reduces in the grammar, it should
// really just be "type_name". If you use type_name, a reduce/reduce
// creeps up. If you use 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;
string rank_or_nullable = (string) $2;
if (expr is ComposedCast){
$$ = new ComposedCast ((ComposedCast)expr, rank_or_nullable);
} else if (expr is ATypeNameExpression){
//
// So we extract the string corresponding to the SimpleName
// or MemberAccess
//
if (rank_or_nullable.Length == 0) {
SimpleName sn = expr as SimpleName;
if (sn != null && sn.Name == "var")
$$ = new VarExpr (sn.Location);
else
$$ = $1;
} else {
$$ = new ComposedCast ((ATypeNameExpression)expr, rank_or_nullable);
}
} else {
Error_ExpectingTypeName (expr);
$$ = TypeManager.system_object_expr;
}
}
| builtin_types opt_rank_specifier_or_nullable
{
if ((string) $2 == "")
$$ = $1;
else
$$ = new ComposedCast ((FullNamedExpression) $1, (string) $2, lexer.Location);
}
| VOID opt_rank_specifier
{
Expression.Error_VoidInvalidInTheContext (GetLocation ($1), Report);
$$ = TypeManager.system_void_expr;
}
;
local_variable_pointer_type
: primary_expression_no_array_creation STAR
{
ATypeNameExpression expr = $1 as ATypeNameExpression;
if (expr != null) {
$$ = new ComposedCast (expr, "*");
} else {
Error_ExpectingTypeName ((Expression)$1);
$$ = expr;
}
}
| builtin_types STAR
{
$$ = new ComposedCast ((FullNamedExpression) $1, "*", GetLocation ($1));
}
| VOID STAR
{
$$ = new ComposedCast (TypeManager.system_void_expr, "*", GetLocation ($1));
}
| local_variable_pointer_type STAR
{
$$ = new ComposedCast ((FullNamedExpression) $1, "*");
}
;
local_variable_type
: variable_type
| local_variable_pointer_type opt_rank_specifier
{
if ($1 != null){
string rank = (string)$2;
if (rank == "")
$$ = $1;
else
$$ = new ComposedCast ((FullNamedExpression) $1, rank);
} else {
$$ = null;
}
}
;
local_variable_declaration
: local_variable_type local_variable_declarators
{
if ($1 != null) {
VarExpr ve = $1 as VarExpr;
if (ve != null) {
if (!((VariableDeclaration) ((List)$2) [0]).HasInitializer)
ve.VariableInitializersCount = 0;
else
ve.VariableInitializersCount = ((List)$2).Count;
}
$$ = new Tuple> ((FullNamedExpression) $1, (List) $2);
} else
$$ = null;
}
;
local_constant_declaration
: CONST variable_type constant_declarators
{
if ($2 != null)
$$ = new Tuple> ((FullNamedExpression) $2, (List) $3);
else
$$ = null;
}
;
expression_statement
: statement_expression SEMICOLON { $$ = $1; }
| statement_expression COMPLETE_COMPLETION { $$ = $1; }
;
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));
s = EmptyExpressionStatement.Instance;
}
$$ = new StatementExpression (s);
}
| error
{
Error_SyntaxError (yyToken);
$$ = null;
}
;
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);
$$ = EmptyStatement.Value;
}
;
selection_statement
: if_statement
| switch_statement
;
if_statement
: IF open_parens_any boolean_expression CLOSE_PARENS
embedded_statement
{
Location l = GetLocation ($1);
$$ = new If ((BooleanExpression) $3, (Statement) $5, l);
// FIXME: location for warning should be loc property of $5.
if ($5 == EmptyStatement.Value)
Report.Warning (642, 3, l, "Possible mistaken empty statement");
}
| IF open_parens_any boolean_expression CLOSE_PARENS
embedded_statement ELSE embedded_statement
{
Location l = GetLocation ($1);
$$ = new If ((BooleanExpression) $3, (Statement) $5, (Statement) $7, l);
// FIXME: location for warning should be loc property of $5 and $7.
if ($5 == EmptyStatement.Value)
Report.Warning (642, 3, l, "Possible mistaken empty statement");
if ($7 == EmptyStatement.Value)
Report.Warning (642, 3, l, "Possible mistaken empty statement");
}
;
switch_statement
: SWITCH open_parens_any
{
if (switch_stack == null)
switch_stack = new Stack (2);
switch_stack.Push (current_block);
}
expression CLOSE_PARENS
switch_block
{
$$ = new Switch ((Expression) $4, (List) $6, GetLocation ($1));
current_block = (Block) switch_stack.Pop ();
}
;
switch_block
: OPEN_BRACE
opt_switch_sections
CLOSE_BRACE
{
$$ = $2;
}
;
opt_switch_sections
: /* empty */
{
Report.Warning (1522, 1, lexer.Location, "Empty switch block");
$$ = new List ();
}
| switch_sections
;
switch_sections
: switch_section
{
var sections = new List (4);
sections.Add ((SwitchSection) $1);
$$ = sections;
}
| switch_sections switch_section
{
var sections = (List) $1;
sections.Add ((SwitchSection) $2);
$$ = sections;
}
;
switch_section
: switch_labels
{
current_block = current_block.CreateSwitchBlock (lexer.Location);
}
statement_list
{
$$ = new SwitchSection ((List) $1, current_block.Explicit);
}
;
switch_labels
: switch_label
{
var labels = new List (4);
labels.Add ((SwitchLabel) $1);
$$ = labels;
}
| switch_labels switch_label
{
var labels = (List) ($1);
labels.Add ((SwitchLabel) $2);
$$ = labels;
}
;
switch_label
: CASE constant_expression COLON
{
$$ = 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
{
Location l = GetLocation ($1);
$$ = new While ((BooleanExpression) $3, (Statement) $5, l);
}
;
do_statement
: DO embedded_statement
WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON
{
Location l = GetLocation ($1);
$$ = new Do ((Statement) $2, (BooleanExpression) $5, l);
}
;
for_statement
: FOR open_parens_any opt_for_initializer SEMICOLON
{
Location l = lexer.Location;
start_block (l);
Block assign_block = current_block;
if ($3 is Tuple>){
var de = (Tuple>) $3;
var type = de.Item1;
foreach (VariableDeclaration decl in de.Item2){
LocalInfo vi;
vi = current_block.AddVariable (type, decl.identifier, decl.Location);
if (vi == null)
continue;
Expression expr = decl.GetInitializer (type);
LocalVariableReference var;
var = new LocalVariableReference (assign_block, decl.identifier, l);
if (expr != null) {
Assign a = new SimpleAssign (var, expr, decl.Location);
assign_block.AddStatement (new StatementExpression (a));
}
}
// Note: the $$ below refers to the value of this code block, not of the LHS non-terminal.
// This can be referred to as $5 below.
$$ = null;
} else {
$$ = $3;
}
}
opt_for_condition SEMICOLON
opt_for_iterator CLOSE_PARENS
embedded_statement
{
Location l = GetLocation ($1);
For f = new For ((Statement) $5, (BooleanExpression) $6, (Statement) $8, (Statement) $10, l);
current_block.AddStatement (f);
$$ = end_block (lexer.Location);
}
;
opt_for_initializer
: /* empty */ { $$ = EmptyStatement.Value; }
| for_initializer
;
for_initializer
: local_variable_declaration
| statement_expression_list
;
opt_for_condition
: /* empty */ { $$ = null; }
| boolean_expression
;
opt_for_iterator
: /* empty */ { $$ = EmptyStatement.Value; }
| for_iterator
;
for_iterator
: statement_expression_list
;
statement_expression_list
: statement_expression
{
// CHANGE: was `null'
Statement s = (Statement) $1;
Block b = new Block (current_block, s.loc, lexer.Location);
b.AddStatement (s);
$$ = b;
}
| statement_expression_list COMMA statement_expression
{
Block b = (Block) $1;
b.AddStatement ((Statement) $3);
$$ = $1;
}
;
foreach_statement
: FOREACH open_parens_any type IN expression CLOSE_PARENS
{
Report.Error (230, GetLocation ($1), "Type and identifier are both required in a foreach statement");
$$ = null;
}
| FOREACH open_parens_any type IDENTIFIER IN
expression CLOSE_PARENS
{
start_block (lexer.Location);
Block foreach_block = current_block;
var lt = (Tokenizer.LocatedToken) $4;
Location l = lt.Location;
LocalInfo vi = foreach_block.AddVariable ((Expression) $3, lt.Value, l);
if (vi != null) {
vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Foreach);
// Get a writable reference to this read-only variable.
//
// Note that the $$ here refers to the value of _this_ code block,
// not the value of the LHS non-terminal. This can be referred to as $8 below.
$$ = new LocalVariableReference (foreach_block, lt.Value, l, vi, false);
} else {
$$ = null;
}
}
embedded_statement
{
LocalVariableReference v = (LocalVariableReference) $8;
Location l = GetLocation ($1);
if (v != null) {
Foreach f = new Foreach ((Expression) $3, v, (Expression) $6, (Statement) $9, l);
current_block.AddStatement (f);
}
$$ = end_block (lexer.Location);
}
;
jump_statement
: break_statement
| continue_statement
| goto_statement
| return_statement
| throw_statement
| yield_statement
;
break_statement
: BREAK SEMICOLON
{
$$ = new Break (GetLocation ($1));
}
;
continue_statement
: CONTINUE SEMICOLON
{
$$ = new Continue (GetLocation ($1));
}
;
goto_statement
: GOTO IDENTIFIER SEMICOLON
{
var lt = (Tokenizer.LocatedToken) $2;
$$ = new Goto (lt.Value, lt.Location);
}
| GOTO CASE constant_expression SEMICOLON
{
$$ = new GotoCase ((Expression) $3, GetLocation ($1));
}
| GOTO DEFAULT SEMICOLON
{
$$ = new GotoDefault (GetLocation ($1));
}
;
return_statement
: RETURN opt_expression SEMICOLON
{
$$ = new Return ((Expression) $2, GetLocation ($1));
}
;
throw_statement
: THROW opt_expression SEMICOLON
{
$$ = new Throw ((Expression) $2, GetLocation ($1));
}
;
yield_statement
: IDENTIFIER RETURN expression SEMICOLON
{
var lt = (Tokenizer.LocatedToken) $1;
string s = lt.Value;
if (s != "yield"){
Report.Error (1003, lt.Location, "; expected");
$$ = null;
}
if (RootContext.Version == LanguageVersion.ISO_1){
Report.FeatureIsNotAvailable (lt.Location, "yield statement");
$$ = null;
}
current_block.Toplevel.IsIterator = true;
$$ = new Yield ((Expression) $3, lt.Location);
}
| IDENTIFIER RETURN SEMICOLON
{
Report.Error (1627, GetLocation ($2), "Expression expected after yield return");
$$ = null;
}
| IDENTIFIER BREAK SEMICOLON
{
var lt = (Tokenizer.LocatedToken) $1;
string s = lt.Value;
if (s != "yield"){
Report.Error (1003, lt.Location, "; expected");
$$ = null;
}
if (RootContext.Version == LanguageVersion.ISO_1){
Report.FeatureIsNotAvailable (lt.Location, "yield statement");
$$ = null;
}
current_block.Toplevel.IsIterator = true;
$$ = new YieldBreak (lt.Location);
}
;
opt_expression
: /* empty */
| expression
;
try_statement
: TRY block catch_clauses
{
$$ = new TryCatch ((Block) $2, (List) $3, GetLocation ($1), false);
}
| TRY block FINALLY block
{
$$ = new TryFinally ((Statement) $2, (Block) $4, GetLocation ($1));
}
| TRY block catch_clauses FINALLY block
{
$$ = new TryFinally (new TryCatch ((Block) $2, (List) $3, GetLocation ($1), true), (Block) $5, GetLocation ($1));
}
| TRY block error
{
Report.Error (1524, GetLocation ($1), "Expected catch or finally");
$$ = null;
}
;
catch_clauses
: catch_clause
{
var l = new List (2);
l.Add ((Catch) $1);
$$ = l;
}
| catch_clauses catch_clause
{
var l = (List) $1;
Catch c = (Catch) $2;
if (l [0].IsGeneral) {
Report.Error (1017, c.loc, "Try statement already has an empty catch block");
} else {
if (c.IsGeneral)
l.Insert (0, c);
else
l.Add (c);
}
$$ = l;
}
;
opt_identifier
: /* empty */ { $$ = null; }
| IDENTIFIER
;
catch_clause
: CATCH opt_catch_args
{
if ($2 != null) {
var cc = (Tuple) $2;
var lt = cc.Item2;
if (lt != null){
List one = new List (1);
one.Add (new VariableDeclaration (lt, null));
start_block (lexer.Location);
current_block = declare_local_variables (cc.Item1, one, lt.Location);
}
}
} block {
Expression type = null;
string id = null;
Block var_block = null;
if ($2 != null){
var cc = (Tuple) $2;
type = cc.Item1;
var lt = cc.Item2;
if (lt != null){
id = lt.Value;
var_block = end_block (lexer.Location);
}
}
$$ = new Catch (type, id, (Block) $4, var_block, ((Block) $4).loc);
}
;
opt_catch_args
: /* empty */ { $$ = null; }
| catch_args
;
catch_args
: open_parens_any type opt_identifier CLOSE_PARENS
{
$$ = new Tuple ((FullNamedExpression)$2, (Tokenizer.LocatedToken) $3);
}
| open_parens_any CLOSE_PARENS
{
Report.Error (1015, GetLocation ($1), "A type that derives from `System.Exception', `object', or `string' expected");
$$ = null;
}
;
checked_statement
: CHECKED block
{
$$ = new Checked ((Block) $2);
}
;
unchecked_statement
: UNCHECKED block
{
$$ = new Unchecked ((Block) $2);
}
;
unsafe_statement
: UNSAFE
{
RootContext.CheckUnsafeOption (GetLocation ($1), Report);
} block {
$$ = new Unsafe ((Block) $3);
}
;
fixed_statement
: FIXED open_parens_any
type_and_void fixed_pointer_declarators
CLOSE_PARENS
{
start_block (lexer.Location);
}
embedded_statement
{
Expression type = (Expression) $3;
var list = (List>) $4;
Fixed f = new Fixed (type,
list.ConvertAll (i => {
var v = new KeyValuePair (current_block.AddVariable (type, i.Key.Value, i.Key.Location), i.Value);
if (v.Key != null) {
v.Key.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Fixed);
v.Key.Pinned = true;
}
return v;
}), (Statement) $7, GetLocation ($1));
current_block.AddStatement (f);
$$ = end_block (lexer.Location);
}
;
fixed_pointer_declarators
: fixed_pointer_declarator {
var declarators = new List> (2);
if ($1 != null)
declarators.Add ((KeyValuePair)$1);
$$ = declarators;
}
| fixed_pointer_declarators COMMA fixed_pointer_declarator
{
var declarators = (List>) $1;
if ($3 != null)
declarators.Add ((KeyValuePair)$3);
$$ = declarators;
}
;
fixed_pointer_declarator
: IDENTIFIER ASSIGN expression
{
var lt = (Tokenizer.LocatedToken) $1;
$$ = new KeyValuePair (lt, (Expression) $3);
}
| IDENTIFIER
{
Report.Error (210, ((Tokenizer.LocatedToken) $1).Location, "You must provide an initializer in a fixed or using statement declaration");
$$ = null;
}
;
lock_statement
: LOCK open_parens_any expression CLOSE_PARENS
{
//
}
embedded_statement
{
$$ = new Lock ((Expression) $3, (Statement) $6, GetLocation ($1));
}
;
using_statement
: USING open_parens_any local_variable_declaration CLOSE_PARENS
{
start_block (lexer.Location);
Block assign_block = current_block;
var de = (Tuple>) $3;
Location l = GetLocation ($1);
var vars = new Stack> ();
foreach (VariableDeclaration decl in de.Item2) {
LocalInfo vi = current_block.AddVariable (de.Item1, decl.identifier, decl.Location);
if (vi == null)
continue;
vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Using);
Expression expr = decl.GetInitializer (de.Item1);
if (expr == null) {
Report.Error (210, l, "You must provide an initializer in a fixed or using statement declaration");
continue;
}
LocalVariableReference var;
// Get a writable reference to this read-only variable.
var = new LocalVariableReference (assign_block, decl.identifier, l, vi, false);
// This is so that it is not a warning on using variables
vi.Used = true;
vars.Push (new Tuple (var, expr));
// Assign a = new SimpleAssign (var, expr, decl.Location);
// assign_block.AddStatement (new StatementExpression (a));
}
// Note: the $$ here refers to the value of this code block and not of the LHS non-terminal.
// It can be referred to as $5 below.
$$ = vars;
}
embedded_statement
{
Statement stmt = (Statement) $6;
var vars = (Stack>) $5;
Location l = GetLocation ($1);
while (vars.Count > 0) {
var de = vars.Pop ();
stmt = new Using (de.Item1, de.Item2, stmt, l);
}
current_block.AddStatement (stmt);
$$ = end_block (lexer.Location);
}
| USING open_parens_any expression CLOSE_PARENS
{
start_block (lexer.Location);
}
embedded_statement
{
current_block.AddStatement (new UsingTemporary ((Expression) $3, (Statement) $6, GetLocation ($1)));
$$ = end_block (lexer.Location);
}
;
// 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;
}
;
first_from_clause
: FROM_FIRST IDENTIFIER IN expression
{
$$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
var lt = (Tokenizer.LocatedToken) $2;
current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
}
| FROM_FIRST type IDENTIFIER IN expression
{
var lt = (Tokenizer.LocatedToken) $3;
$$ = new Linq.QueryExpression (current_block, new Linq.Cast ((FullNamedExpression)$2, (Expression)$5));
current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
}
;
nested_from_clause
: FROM IDENTIFIER IN expression
{
$$ = new Linq.QueryExpression (current_block, new Linq.QueryStartClause ((Expression)$4));
var lt = (Tokenizer.LocatedToken) $2;
current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
}
| FROM type IDENTIFIER IN expression
{
$$ = new Linq.QueryExpression (current_block, new Linq.Cast ((FullNamedExpression)$2, (Expression)$5));
var lt = (Tokenizer.LocatedToken) $3;
current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
}
;
from_clause
: FROM IDENTIFIER IN
{
current_block = new Linq.QueryBlock (compiler, current_block, GetLocation ($1));
}
expression
{
var lt = (Tokenizer.LocatedToken) $2;
var sn = new SimpleMemberName (lt.Value, lt.Location);
$$ = new Linq.SelectMany (current_block.Toplevel, sn, (Expression)$5);
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
}
| FROM type IDENTIFIER IN
{
current_block = new Linq.QueryBlock (compiler, current_block, GetLocation ($1));
}
expression
{
var lt = (Tokenizer.LocatedToken) $3;
var sn = new SimpleMemberName (lt.Value, lt.Location);
FullNamedExpression type = (FullNamedExpression)$2;
$$ = new Linq.SelectMany (current_block.Toplevel, sn, new Linq.Cast (type, (FullNamedExpression)$6));
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
}
;
query_body
: opt_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
: SELECT
{
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
}
expression
{
$$ = new Linq.Select (current_block.Toplevel, (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 ();
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
linq_clause_blocks.Push (current_block);
}
expression
{
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
}
BY expression
{
$$ = new Linq.GroupBy (current_block.Toplevel, (Expression)$3, (ToplevelBlock) linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1));
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
}
;
opt_query_body_clauses
: /* empty */
| query_body_clauses
;
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 ASSIGN
{
current_block = new Linq.QueryBlock (compiler, current_block, GetLocation ($1));
}
expression
{
var lt = (Tokenizer.LocatedToken) $2;
var sn = new SimpleMemberName (lt.Value, lt.Location);
$$ = new Linq.Let (current_block.Toplevel, current_container, sn, (Expression)$5);
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
}
;
where_clause
: WHERE
{
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
}
boolean_expression
{
$$ = new Linq.Where (current_block.Toplevel, (BooleanExpression)$3, GetLocation ($1));
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
}
;
join_clause
: JOIN IDENTIFIER IN
{
if (linq_clause_blocks == null)
linq_clause_blocks = new Stack ();
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
linq_clause_blocks.Push (current_block);
}
expression ON
{
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
linq_clause_blocks.Push (current_block);
}
expression EQUALS
{
current_block.AddStatement (new ContextualReturn ((Expression) $8));
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
var lt = (Tokenizer.LocatedToken) $2;
current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), lexer.Location);
}
expression opt_join_into
{
var lt = (Tokenizer.LocatedToken) $2;
var sn = new SimpleMemberName (lt.Value, lt.Location);
SimpleMemberName sn2 = null;
ToplevelBlock outer_selector = (ToplevelBlock) linq_clause_blocks.Pop ();
ToplevelBlock block = (ToplevelBlock) linq_clause_blocks.Pop ();
if ($12 == null) {
$$ = new Linq.Join (block, sn, (Expression)$5, outer_selector, current_block.Toplevel, GetLocation ($1));
} else {
var lt2 = (Tokenizer.LocatedToken) $12;
sn2 = new SimpleMemberName (lt2.Value, lt2.Location);
$$ = new Linq.GroupJoin (block, sn, (Expression)$5, outer_selector, current_block.Toplevel,
sn2, GetLocation ($1));
}
current_block.AddStatement (new ContextualReturn ((Expression) $11));
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
if (sn2 == null)
((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
else
((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn2);
}
| JOIN type IDENTIFIER IN
{
if (linq_clause_blocks == null)
linq_clause_blocks = new Stack ();
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
linq_clause_blocks.Push (current_block);
}
expression ON
{
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
current_block = new Linq.QueryBlock (compiler, current_block, lexer.Location);
linq_clause_blocks.Push (current_block);
}
expression EQUALS
{
current_block.AddStatement (new ContextualReturn ((Expression) $9));
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
var lt = (Tokenizer.LocatedToken) $3;
current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), lexer.Location);
}
expression opt_join_into
{
var lt = (Tokenizer.LocatedToken) $3;
var sn = new SimpleMemberName (lt.Value, lt.Location);
SimpleMemberName sn2 = null;
ToplevelBlock outer_selector = (ToplevelBlock) linq_clause_blocks.Pop ();
ToplevelBlock block = (ToplevelBlock) linq_clause_blocks.Pop ();
Linq.Cast cast = new Linq.Cast ((FullNamedExpression)$2, (Expression)$6);
if ($13 == null) {
$$ = new Linq.Join (block, sn, cast, outer_selector, current_block.Toplevel, GetLocation ($1));
} else {
var lt2 = (Tokenizer.LocatedToken) $13;
sn2 = new SimpleMemberName (lt2.Value, lt2.Location);
$$ = new Linq.GroupJoin (block, sn, cast, outer_selector, current_block.Toplevel,
sn2, GetLocation ($1));
}
current_block.AddStatement (new ContextualReturn ((Expression) $12));
current_block.SetEndLocation (lexer.Location);
current_block = current_block.Parent;
if (sn2 == null)
((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn);
else
((Linq.QueryBlock)current_block).AddTransparentParameter (compiler, sn2);
}
;
opt_join_into
: /* empty */
| INTO IDENTIFIER
{
$$ = $2;
}
;
orderby_clause
: ORDERBY
{
current_block = new Linq.QueryBlock (compiler, 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 (compiler, 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 (compiler, current_block, lexer.Location);
}
then_by
{
((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$3;
$$ = $1;
}
;
order_by
: expression
{
$$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);
}
| expression ASCENDING
{
$$ = new Linq.OrderByAscending (current_block.Toplevel, (Expression)$1);
}
| expression DESCENDING
{
$$ = new Linq.OrderByDescending (current_block.Toplevel, (Expression)$1);
}
;
then_by
: expression
{
$$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1);
}
| expression ASCENDING
{
$$ = new Linq.ThenByAscending (current_block.Toplevel, (Expression)$1);
}
| expression DESCENDING
{
$$ = new Linq.ThenByDescending (current_block.Toplevel, (Expression)$1);
}
;
opt_query_continuation
: /* empty */
| INTO IDENTIFIER
{
// 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;
var lt = (Tokenizer.LocatedToken) $2;
current_block = new Linq.QueryBlock (compiler, current_block, new SimpleMemberName (lt.Value, lt.Location), GetLocation ($1));
}
query_body
{
$$ = new Linq.QueryExpression (current_block, (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
| EVAL_STATEMENT_PARSER {
Evaluator.LoadAliases (current_namespace);
push_current_class (new Class (current_namespace, current_class, new MemberName ("Class" + class_count++),
Modifiers.PUBLIC, null), null);
var baseclass_list = new List ();
baseclass_list.Add (new TypeExpression (Evaluator.InteractiveBaseClass, lexer.Location));
current_container.AddBasesForPart (current_class, baseclass_list);
// (ref object retval)
Parameter [] mpar = new Parameter [1];
mpar [0] = new Parameter (TypeManager.system_object_expr, "$retval", Parameter.Modifier.REF, null, Location.Null);
ParametersCompiled pars = new ParametersCompiled (compiler, mpar);
current_local_parameters = pars;
Method method = new Method (
current_class,
null, // generic
TypeManager.system_void_expr,
Modifiers.PUBLIC | Modifiers.STATIC,
new MemberName ("Host"),
pars,
null /* attributes */);
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);
current_container.AddMethod (method);
--lexer.parsing_declaration;
InteractiveResult = pop_current_class ();
current_local_parameters = null;
}
| EVAL_COMPILATION_UNIT_PARSER {
Evaluator.LoadAliases (current_namespace);
}
interactive_compilation_unit
;
interactive_compilation_unit
: outer_declarations
| outer_declarations global_attributes
| global_attributes
| /* nothing */
;
opt_COMPLETE_COMPLETION
: /* nothing */
| COMPLETE_COMPLETION
;
close_brace_or_complete_completion
: CLOSE_BRACE
| COMPLETE_COMPLETION
;
%%
//
// A class used to pass around variable declarations and constants
//
class VariableDeclaration {
public string identifier;
Expression initializer;
public Location Location;
public Attributes OptAttributes;
public string DocComment;
public VariableDeclaration (Tokenizer.LocatedToken lt, Expression initializer, Attributes opt_attrs)
{
this.identifier = lt.Value;
this.initializer = initializer;
this.Location = lt.Location;
this.OptAttributes = opt_attrs;
}
public VariableDeclaration (Tokenizer.LocatedToken lt, Expression initializer)
: this (lt, initializer, null)
{
}
public Expression GetInitializer (FullNamedExpression type)
{
if (initializer is ArrayInitializer)
return new ArrayCreation (type, "", (ArrayInitializer)initializer, Location);
return initializer;
}
public bool HasInitializer {
get { return initializer != null; }
}
}
class VariableMemberDeclaration
{
public readonly MemberName MemberName;
Expression initializer;
public VariableMemberDeclaration (MemberName mn, Expression initializer)
{
MemberName = mn;
this.initializer = initializer;
}
public Expression GetInitializer (FullNamedExpression type)
{
if (initializer is ArrayInitializer)
return new ArrayCreation (type, "", (ArrayInitializer)initializer, MemberName.Location);
return initializer;
}
}
//
// A class used to hold info about an operator declarator
//
struct 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_NamedArgumentExpected (NamedArgument a)
{
Report.Error (1738, a.Location, "Named arguments must appear after the positional arguments");
}
void push_current_class (TypeContainer tc, object partial_token)
{
if (RootContext.EvalMode){
tc.ModFlags = (tc.ModFlags & ~(Modifiers.PRIVATE|Modifiers.INTERNAL)) | Modifiers.PUBLIC;
undo.AddTypeContainer (current_container, tc);
}
if (partial_token != null)
current_container = current_container.AddPartial (tc);
else
current_container = current_container.AddTypeContainer (tc);
++lexer.parsing_declaration;
current_class = tc;
}
DeclSpace pop_current_class ()
{
DeclSpace retval = current_class;
current_class = current_class.Parent;
current_container = current_class.PartialContainer;
return retval;
}
//
// Given the @class_name name, it creates a fully qualified name
// based on the containing declaration space
//
MemberName
MakeName (MemberName class_name)
{
Namespace ns = current_namespace.NS;
if (current_container == RootContext.ToplevelTypes) {
if (ns.Name.Length != 0)
return new MemberName (ns.MemberName, class_name);
else
return class_name;
} else {
return new MemberName (current_container.MemberName, class_name);
}
}
Block declare_local_variables (FullNamedExpression type, List variable_declarators, Location loc)
{
Block implicit_block;
//
// If we are doing interactive editing, we want variable declarations
// that are in the top block to be added instead to the class as
// static variables
//
if (RootContext.StatementMode){
bool hoist = true;
for (Block b = current_block; b != null; b = b.Parent){
if (b is ExplicitBlock && !(b is ToplevelBlock)){
// There has been an explicit block, we cant add to the class
hoist = false;
break;
}
}
if (hoist){
//
// We can use "current_block" since we know there are no explicit blocks
//
foreach (VariableDeclaration decl in variable_declarators){
// We can not use the super-handy f.Initializer, because
// multiple lines would force code to be executed out of sync
var init = decl.GetInitializer (type);
if (init != null){
string id = "$" + decl.identifier;
LocalInfo vi = current_block.AddVariable (type, id, decl.Location);
// Avoid warning about this variable not being used.
vi.Used = true;
LocalVariableReference var;
var = new LocalVariableReferenceWithClassSideEffect (current_container, decl.identifier, current_block, id, vi, decl.Location);
Assign assign = new SimpleAssign (var, init, decl.Location);
current_block.AddStatement (new StatementExpression (assign));
assign = new SimpleAssign (new SimpleName (decl.identifier, decl.Location), var);
current_block.AddStatement (new StatementExpression (assign));
} else {
Field f = new Field (current_container, (FullNamedExpression) type, Modifiers.PUBLIC | Modifiers.STATIC,
new MemberName (decl.identifier, loc), null);
current_container.AddField (f);
// Register the field to be visible later as a global variable
Evaluator.QueueField (f);
}
}
return current_block;
}
}
//
// We use the `Used' property to check whether statements
// have been added to the current block. If so, we need
// to create another block to contain the new declaration
// otherwise, as an optimization, we use the same block to
// add the declaration.
//
// FIXME: A further optimization is to check if the statements
// that were added were added as part of the initialization
// below. In which case, no other statements have been executed
// and we might be able to reduce the number of blocks for
// situations like this:
//
// int j = 1; int k = j + 1;
//
if (current_block.Used)
implicit_block = new Block (current_block, loc, lexer.Location);
else
implicit_block = current_block;
foreach (VariableDeclaration decl in variable_declarators){
if (implicit_block.AddVariable (type, decl.identifier, decl.Location) != null) {
if (decl.HasInitializer){
Assign assign;
var lvr = new LocalVariableReference (implicit_block, decl.identifier, loc);
assign = new SimpleAssign (lvr, decl.GetInitializer (type), decl.Location);
implicit_block.AddStatement (new StatementExpression (assign));
}
}
}
return implicit_block;
}
Block declare_local_constants (FullNamedExpression type, List declarators)
{
Block implicit_block;
if (current_block.Used)
implicit_block = new Block (current_block);
else
implicit_block = current_block;
foreach (VariableDeclaration decl in declarators){
implicit_block.AddConstant (type, decl.identifier, decl.GetInitializer (type), decl.Location);
}
return implicit_block;
}
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;
}
}
static CSharpParser ()
{
oob_stack = new Stack ();
}
public CSharpParser (SeekableStreamReader reader, CompilationUnit file, CompilerContext ctx)
{
if (RootContext.EvalMode)
undo = new Undo ();
this.file = file;
this.compiler = ctx;
current_namespace = new NamespaceEntry (null, file, null);
current_class = current_namespace.SlaveDeclSpace;
current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes
oob_stack.Clear ();
lexer = new Tokenizer (reader, file, ctx);
use_global_stacks = true;
}
public void parse ()
{
eof_token = Token.EOF;
Tokenizer.LocatedToken.Initialize ();
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)
UnexpectedEOF = true;
if (e is yyParser.yyException)
Report.Error (-25, lexer.Location, "Parsing error");
else if (yacc_verbose_flag > 0)
throw; // Used by compiler-tester to test internal errors
else
Report.Error (589, lexer.Location, "Internal compiler error during parsing");
}
if (RootContext.ToplevelTypes.NamespaceEntry != null)
throw new InternalErrorException ("who set it?");
}
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);
}
void CheckIdentifierToken (int yyToken, Location loc)
{
CheckToken (1041, yyToken, "Identifier expected", loc);
}
string ConsumeStoredComment ()
{
string s = tmpComment;
tmpComment = null;
Lexer.doc_state = XmlCommentState.Allowed;
return s;
}
Location GetLocation (object obj)
{
if (obj is Tokenizer.LocatedToken)
return ((Tokenizer.LocatedToken) obj).Location;
if (obj is MemberName)
return ((MemberName) obj).Location;
return lexer.Location;
}
Report Report {
get { return compiler.Report; }
}
void start_block (Location loc)
{
if (current_block == null || parsing_anonymous_method) {
current_block = new ToplevelBlock (compiler, current_block, current_local_parameters, current_generic_method, loc);
parsing_anonymous_method = false;
} else {
current_block = new ExplicitBlock (current_block, loc, Location.Null);
}
}
Block
end_block (Location loc)
{
Block retval = current_block.Explicit;
retval.SetEndLocation (loc);
current_block = retval.Parent;
return retval;
}
void
start_anonymous (bool lambda, ParametersCompiled parameters, Location loc)
{
if (RootContext.Version == LanguageVersion.ISO_1){
Report.FeatureIsNotAvailable (loc, "anonymous methods");
}
oob_stack.Push (current_anonymous_method);
oob_stack.Push (current_local_parameters);
current_local_parameters = parameters;
current_anonymous_method = lambda
? new LambdaExpression (loc)
: new AnonymousMethodExpression (loc);
// Force the next block to be created as a ToplevelBlock
parsing_anonymous_method = true;
}
/*
* Completes the anonymous method processing, if lambda_expr is null, this
* means that we have a Statement instead of an Expression embedded
*/
AnonymousMethodExpression end_anonymous (ToplevelBlock anon_block)
{
AnonymousMethodExpression retval;
current_anonymous_method.Block = anon_block;
retval = current_anonymous_method;
current_local_parameters = (ParametersCompiled) oob_stack.Pop ();
current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
return retval;
}
public NamespaceEntry CurrentNamespace {
get {
return current_namespace;
}
}
void Error_SyntaxError (int token)
{
Error_SyntaxError (0, token, "Unexpected symbol");
}
void Error_SyntaxError (int error_code, int token, string msg)
{
string symbol = GetSymbolName (token);
string expecting = GetExpecting ();
if (error_code == 0) {
if (expecting == "`)'")
error_code = 1026;
else
error_code = 1525;
}
if (expecting != null)
Report.Error (error_code, lexer.Location, "{2} `{0}', expecting {1}",
symbol, expecting, msg);
else
Report.Error (error_code, lexer.Location, "{1} `{0}'", symbol, msg);
}
string GetExpecting ()
{
int [] tokens = yyExpectingTokens (yyExpectingState);
var names = new List (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 == "")
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.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:
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.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:
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 "";
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:
return "identifier";
// All of these are internal.
case Token.NONE:
case Token.ERROR:
case Token.FIRST_KEYWORD:
case Token.EOF:
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 "";
// A bit more robust.
default:
return yyNames [token];
}
}
/* end end end */
}