%{
//
// 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)
//
// Licensed under the terms of the GNU GPL
//
// (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 { }"
//
// Possible optimization:
// Run memory profiler with parsing only, and consider dropping
// arraylists where not needed. Some pieces can use linked lists.
//
using System.Text;
using System.IO;
using System;
namespace Mono.CSharp
{
using System.Collections;
///
/// The C# Parser
///
public class CSharpParser {
NamespaceEntry current_namespace;
TypeContainer current_container;
DeclSpace current_class;
IAnonymousHost anonymous_host;
///
/// 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.
///
Parameters 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).
///
Expression implicit_value_parameter_type;
Parameters indexer_parameters;
///
/// Hack to help create non-typed array initializer
///
public static Expression current_array_type;
Expression pushed_current_array_type;
///
/// 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;
static public int yacc_verbose_flag;
// Name of the file we are parsing
public string name;
///
/// The current file.
///
SourceFile 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;
%}
%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 ASSEMBLY
%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 QUERY_FIRST_TOKEN
%token FROM
%token JOIN
%token ON
%token EQUALS
%token SELECT
%token GROUP
%token BY
%token LET
%token ORDERBY
%token ASCENDING
%token DESCENDING
%token INTO
%token QUERY_LAST_TOKEN
/* C# keywords which are not really keywords */
%token GET "get"
%token SET "set"
%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_GENERICS_LT "<"
%token OP_GT ">"
%token OP_GENERICS_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 "??"
/* Numbers */
%token LITERAL_INTEGER "int literal"
%token LITERAL_FLOAT "float literal"
%token LITERAL_DOUBLE "double literal"
%token LITERAL_DECIMAL "decimal literal"
%token LITERAL_CHARACTER "character literal"
%token LITERAL_STRING "string literal"
%token IDENTIFIER
%token OPEN_PARENS_LAMBDA
%token CLOSE_PARENS_CAST
%token CLOSE_PARENS_NO_CAST
%token CLOSE_PARENS_OPEN_PARENS
%token CLOSE_PARENS_MINUS
%token DEFAULT_OPEN_PARENS
%token GENERIC_DIMENSION
%token DEFAULT_COLON
/* Add precedence rules to solve dangling else s/r conflict */
%nonassoc LOWPREC
%nonassoc IF
%nonassoc ELSE
%right ASSIGN
%left OP_OR
%left OP_AND
%left BITWISE_OR
%left BITWISE_AND
%left OP_SHIFT_LEFT OP_SHIFT_RIGHT
%left PLUS MINUS
%left STAR DIV PERCENT
%right BANG CARRET UMINUS
%nonassoc OP_INC OP_DEC
%left OPEN_PARENS
%left OPEN_BRACKET OPEN_BRACE
%left DOT
%nonassoc HIGHPREC
%start compilation_unit
%%
compilation_unit
: outer_declarations opt_EOF
| outer_declarations global_attributes opt_EOF
| global_attributes opt_EOF
| opt_EOF /* allow empty files */
;
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 IDENTIFIER IDENTIFIER SEMICOLON
{
LocatedToken lt = (LocatedToken) $2;
string s = lt.Value;
if (s != "alias"){
Report.Error (1003, lt.Location, "'alias' expected");
} else if (RootContext.Version == LanguageVersion.ISO_1) {
Report.FeatureIsNotISO1 (lt.Location, "external alias");
} else {
lt = (LocatedToken) $3;
current_namespace.UsingExternalAlias (lt.Value, lt.Location);
}
}
;
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
{
LocatedToken lt = (LocatedToken) $2;
current_namespace.UsingAlias (lt.Value, (MemberName) $4, (Location) $1);
}
| USING error {
CheckIdentifierToken (yyToken, GetLocation ($2));
}
;
using_namespace_directive
: USING namespace_name SEMICOLON
{
current_namespace.Using ((MemberName) $2, (Location) $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 namespace_or_type_name
{
MemberName name = (MemberName) $3;
if ($1 != null) {
Report.Error(1671, name.Location, "A namespace declaration cannot have modifiers or attributes");
}
if (name.TypeArguments != null)
syntax_error (lexer.Location, "namespace name expected");
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;
}
;
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);
} 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) {
ArrayList sect = (ArrayList) $1;
if (global_attrs_enabled) {
if (current_attr_target == "module") {
CodeGen.Module.AddAttributes (sect);
$$ = null;
} else if (current_attr_target != null && current_attr_target.Length > 0) {
CodeGen.Assembly.AddAttributes (sect);
$$ = null;
} else {
$$ = new Attributes (sect);
}
if ($$ == null) {
if (RootContext.Documentation != null) {
Lexer.check_incorrect_doc_comment ();
Lexer.doc_state =
XmlCommentState.Allowed;
}
}
} else {
$$ = new Attributes (sect);
}
}
else
$$ = null;
current_attr_target = null;
}
| attribute_sections attribute_section
{
if (current_attr_target != String.Empty) {
Attributes attrs = $1 as Attributes;
ArrayList sect = (ArrayList) $2;
if (global_attrs_enabled) {
if (current_attr_target == "module") {
CodeGen.Module.AddAttributes (sect);
$$ = null;
} else if (current_attr_target == "assembly") {
CodeGen.Assembly.AddAttributes (sect);
$$ = null;
} else {
if (attrs == null)
attrs = new Attributes (sect);
else
attrs.AddAttributes (sect);
}
} else {
if (attrs == null)
attrs = new Attributes (sect);
else
attrs.AddAttributes (sect);
}
$$ = 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
{
LocatedToken lt = (LocatedToken) $1;
$$ = CheckAttributeTarget (lt.Value, lt.Location);
}
| EVENT { $$ = "event"; }
| RETURN { $$ = "return"; }
| error
{
string name = yyNames [yyToken].ToLower ();
$$ = CheckAttributeTarget (name, GetLocation ($1));
}
;
attribute_list
: attribute
{
ArrayList attrs = new ArrayList (4);
attrs.Add ($1);
$$ = attrs;
}
| attribute_list COMMA attribute
{
ArrayList attrs = (ArrayList) $1;
attrs.Add ($3);
$$ = attrs;
}
;
attribute
: attribute_name opt_attribute_arguments
{
MemberName mname = (MemberName) $1;
if (mname.IsGeneric) {
Report.Error (404, lexer.Location,
"'<' unexpected: attributes cannot be generic");
}
object [] arguments = (object []) $2;
MemberName left = mname.Left;
string identifier = mname.Name;
Expression left_expr = left == null ? null : left.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,
left_expr, identifier, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
else
$$ = new Attribute (current_attr_target, left_expr, identifier, 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
: opt_positional_argument_list
{
if ($1 == null)
$$ = null;
else {
$$ = new object [] { $1, null };
}
}
| positional_argument_list COMMA named_argument_list
{
$$ = new object[] { $1, $3 };
}
| named_argument_list
{
$$ = new object [] { null, $1 };
}
;
opt_positional_argument_list
: /* empty */ { $$ = null; }
| positional_argument_list
;
positional_argument_list
: expression
{
ArrayList args = new ArrayList (4);
args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
$$ = args;
}
| positional_argument_list COMMA expression
{
ArrayList args = (ArrayList) $1;
args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
$$ = args;
}
;
named_argument_list
: named_argument
{
ArrayList args = new ArrayList (4);
args.Add ($1);
$$ = args;
}
| named_argument_list COMMA named_argument
{
ArrayList args = (ArrayList) $1;
args.Add ($3);
$$ = args;
}
| named_argument_list COMMA expression
{
Report.Error (1016, ((Expression) $3).Location, "Named attribute argument expected");
$$ = null;
}
;
named_argument
: IDENTIFIER ASSIGN expression
{
// FIXME: keep location
$$ = new DictionaryEntry (
((LocatedToken) $1).Value,
new Argument ((Expression) $3, Argument.AType.Expression));
}
;
class_body
: OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
;
opt_class_member_declarations
: /* empty */
| class_member_declarations
;
class_member_declarations
: class_member_declaration
| class_member_declarations
class_member_declaration
;
class_member_declaration
: constant_declaration // done
| field_declaration // done
| method_declaration // done
| property_declaration // done
| event_declaration // done
| indexer_declaration // done
| operator_declaration // done
| constructor_declaration // done
| destructor_declaration // done
| type_declaration
;
struct_declaration
: opt_attributes
opt_modifiers
opt_partial
STRUCT
{
lexer.ConstraintsParsing = true;
}
type_name
{
MemberName name = MakeName ((MemberName) $6);
push_current_class (new Struct (
current_namespace, current_class, name, (int) $2,
(Attributes) $1), $3);
}
opt_class_base
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
if ($8 != null)
current_container.AddBasesForPart (current_class, (ArrayList) $8);
current_class.SetParameterInfo ((ArrayList) $9);
if (RootContext.Documentation != null)
current_container.DocComment = Lexer.consume_doc_comment ();
}
struct_body
{
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
{
int modflags = (int) $2;
foreach (VariableDeclaration constant in (ArrayList) $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, (Expression) $4, (string) constant.identifier,
(Expression) constant.expression_or_array_initializer, 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
{
ArrayList constants = new ArrayList (4);
if ($1 != null)
constants.Add ($1);
$$ = constants;
}
| constant_declarators COMMA constant_declarator
{
if ($3 != null) {
ArrayList constants = (ArrayList) $1;
constants.Add ($3);
}
}
;
constant_declarator
: IDENTIFIER ASSIGN constant_expression
{
$$ = new VariableDeclaration ((LocatedToken) $1, $3);
}
| IDENTIFIER
{
// A const field requires a value to be provided
Report.Error (145, ((LocatedToken) $1).Location, "A const field requires a value to be provided");
$$ = null;
}
;
field_declaration
: opt_attributes
opt_modifiers
type
variable_declarators
SEMICOLON
{
Expression type = (Expression) $3;
int mod = (int) $2;
current_array_type = null;
foreach (VariableDeclaration var in (ArrayList) $4){
Field field = new Field (current_class, type, mod, var.identifier,
(Attributes) $1, var.Location);
field.Initializer = var.expression_or_array_initializer;
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
type
fixed_variable_declarators
SEMICOLON
{
Expression type = (Expression) $4;
int mod = (int) $2;
current_array_type = null;
foreach (VariableDeclaration var in (ArrayList) $5) {
FixedField field = new FixedField (current_class, type, mod, var.identifier,
(Expression)var.expression_or_array_initializer, (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
type
error
{
Report.Error (1641, GetLocation ($4), "A fixed size buffer field must have the array size specifier after the field name");
}
| opt_attributes
opt_modifiers
VOID
variable_declarators
SEMICOLON {
current_array_type = null;
Report.Error (670, (Location) $3, "Fields cannot have void type");
}
;
fixed_variable_declarators
: fixed_variable_declarator
{
ArrayList decl = new ArrayList (2);
decl.Add ($1);
$$ = decl;
}
| fixed_variable_declarators COMMA fixed_variable_declarator
{
ArrayList decls = (ArrayList) $1;
decls.Add ($3);
$$ = $1;
}
;
fixed_variable_declarator
: IDENTIFIER OPEN_BRACKET expression CLOSE_BRACKET
{
$$ = new VariableDeclaration ((LocatedToken) $1, $3);
}
| IDENTIFIER OPEN_BRACKET CLOSE_BRACKET
{
Report.Error (443, lexer.Location, "Value or constant expected");
$$ = new VariableDeclaration ((LocatedToken) $1, null);
}
;
variable_declarators
: variable_declarator
{
ArrayList decl = new ArrayList (4);
if ($1 != null)
decl.Add ($1);
$$ = decl;
}
| variable_declarators COMMA variable_declarator
{
ArrayList decls = (ArrayList) $1;
decls.Add ($3);
$$ = $1;
}
;
variable_declarator
: IDENTIFIER ASSIGN variable_initializer
{
$$ = new VariableDeclaration ((LocatedToken) $1, $3);
}
| IDENTIFIER
{
$$ = new VariableDeclaration ((LocatedToken) $1, null);
}
| IDENTIFIER OPEN_BRACKET opt_expression CLOSE_BRACKET
{
Report.Error (650, ((LocatedToken) $1).Location, "Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier. " +
"To declare a fixed size buffer field, use the fixed keyword before the field type");
$$ = null;
}
;
variable_initializer
: expression
{
$$ = $1;
}
| array_initializer
{
$$ = $1;
}
| STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
{
$$ = new StackAlloc ((Expression) $2, (Expression) $4, (Location) $1);
}
| ARGLIST
{
$$ = new ArglistAccess ((Location) $1);
}
| STACKALLOC type
{
Report.Error (1575, (Location) $1, "A stackalloc expression requires [] after type");
$$ = null;
}
;
method_declaration
: method_header {
anonymous_host = (IAnonymousHost) $1;
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.NotAllowed;
}
method_body
{
Method method = (Method) $1;
method.Block = (ToplevelBlock) $3;
current_container.AddMethod (method);
anonymous_host = null;
current_generic_method = null;
current_local_parameters = null;
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
;
opt_error_modifier
: /* empty */
| modifiers
{
int m = (int) $1;
int i = 1;
while (m != 0){
if ((i & m) != 0){
Report.Error (1585, lexer.Location,
"Member modifier `{0}' must precede the member type and name",
Modifiers.Name (i));
}
m &= ~i;
i = i << 1;
}
}
;
//
// This rule is used to handle the cases where OPEN_PARENS_LAMBDA
// is returned (type followed by an identifier), these are the
// declarations (methods, overloads, constructors, etc) and a handful
// of expressions ("using", "fixed") or "catch".
//
open_parens
: OPEN_PARENS
| OPEN_PARENS_LAMBDA
;
method_header
: opt_attributes
opt_modifiers
type member_name
open_parens opt_formal_parameter_list CLOSE_PARENS
{
lexer.ConstraintsParsing = true;
}
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
MemberName name = (MemberName) $4;
if ($9 != 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,
(Expression) $3, (Parameters) $6);
generic.SetParameterInfo ((ArrayList) $9);
}
method = new Method (current_class, generic, (Expression) $3, (int) $2, false,
name, (Parameters) $6, (Attributes) $1);
anonymous_host = method;
current_local_parameters = (Parameters) $6;
current_generic_method = generic;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = method;
}
| opt_attributes
opt_modifiers
VOID member_name
open_parens opt_formal_parameter_list CLOSE_PARENS
{
lexer.ConstraintsParsing = true;
}
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
MemberName name = (MemberName) $4;
if ($9 != 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, (Parameters) $6);
generic.SetParameterInfo ((ArrayList) $9);
}
method = new Method (current_class, generic, TypeManager.system_void_expr,
(int) $2, false, name, (Parameters) $6, (Attributes) $1);
anonymous_host = method;
current_local_parameters = (Parameters) $6;
current_generic_method = generic;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = method;
}
| opt_attributes
opt_modifiers
type
modifiers member_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", Modifiers.Name ((int) $4));
Method method = new Method (current_class, null, TypeManager.system_void_expr,
0, false, name, (Parameters) $6, (Attributes) $1);
current_local_parameters = (Parameters) $6;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = null;
}
;
method_body
: block
| SEMICOLON { $$ = null; }
;
opt_formal_parameter_list
: /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; }
| formal_parameter_list
;
formal_parameter_list
: fixed_parameters
{
ArrayList pars_list = (ArrayList) $1;
Parameter [] pars = new Parameter [pars_list.Count];
pars_list.CopyTo (pars);
$$ = new Parameters (pars);
}
| fixed_parameters COMMA parameter_array
{
ArrayList pars_list = (ArrayList) $1;
pars_list.Add ($3);
Parameter [] pars = new Parameter [pars_list.Count];
pars_list.CopyTo (pars);
$$ = new Parameters (pars);
}
| fixed_parameters COMMA ARGLIST
{
ArrayList pars_list = (ArrayList) $1;
//pars_list.Add (new ArglistParameter (GetLocation ($3)));
Parameter [] pars = new Parameter [pars_list.Count];
pars_list.CopyTo (pars);
$$ = new Parameters (pars, 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");
$$ = null;
}
| 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");
$$ = null;
}
| ARGLIST COMMA error
{
Report.Error (257, (Location) $1, "An __arglist parameter must be the last parameter in a formal parameter list");
$$ = null;
}
| fixed_parameters COMMA ARGLIST COMMA error
{
Report.Error (257, (Location) $3, "An __arglist parameter must be the last parameter in a formal parameter list");
$$ = null;
}
| parameter_array
{
$$ = new Parameters (new Parameter[] { (Parameter) $1 } );
}
| ARGLIST
{
$$ = new Parameters (new Parameter[0], true);
}
;
fixed_parameters
: fixed_parameter
{
ArrayList pars = new ArrayList (4);
pars.Add ($1);
$$ = pars;
}
| fixed_parameters COMMA fixed_parameter
{
ArrayList pars = (ArrayList) $1;
Parameter p = (Parameter)$3;
if (p != null) {
if ((p.modFlags & Parameter.Modifier.This) != 0)
Report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter");
pars.Add (p);
}
$$ = $1;
}
;
fixed_parameter
: opt_attributes
opt_parameter_modifier
type
IDENTIFIER
{
LocatedToken lt = (LocatedToken) $4;
$$ = new Parameter ((Expression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location);
}
| opt_attributes
opt_parameter_modifier
type
IDENTIFIER OPEN_BRACKET CLOSE_BRACKET
{
LocatedToken lt = (LocatedToken) $4;
Report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name");
$$ = null;
}
| opt_attributes
opt_parameter_modifier
type
{
Report.Error (1001, GetLocation ($3), "Identifier expected");
$$ = null;
}
| opt_attributes
opt_parameter_modifier
type
error {
CheckIdentifierToken (yyToken, GetLocation ($4));
$$ = null;
}
| opt_attributes
opt_parameter_modifier
type
IDENTIFIER
ASSIGN
constant_expression
{
LocatedToken lt = (LocatedToken) $4;
Report.Error (241, lt.Location, "Default parameter specifiers are not permitted");
$$ = null;
}
;
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 { $$ = Parameter.Modifier.REF; }
| OUT { $$ = Parameter.Modifier.OUT; }
| THIS { $$ = Parameter.Modifier.This; }
;
parameter_array
: opt_attributes PARAMS type IDENTIFIER
{
LocatedToken lt = (LocatedToken) $4;
$$ = new ParamsParameter ((Expression) $3, lt.Value, (Attributes) $1, lt.Location);
}
| opt_attributes PARAMS PARAMS type IDENTIFIER
{
Error_DuplicateParameterModifier (lexer.Location, Parameter.Modifier.PARAMS);
$$ = null;
}
| opt_attributes PARAMS parameter_modifier type IDENTIFIER
{
Parameter.Modifier mod = (Parameter.Modifier)$3;
if ((mod & Parameter.Modifier.This) != 0) {
Report.Error (1104, lexer.Location, "The parameter modifiers `this' and `params' cannot be used altogether");
} else {
Report.Error (1611, (Location) $2, "The params parameter cannot be declared as ref or out");
}
$$ = null;
}
| opt_attributes PARAMS type error {
CheckIdentifierToken (yyToken, GetLocation ($4));
$$ = null;
}
;
property_declaration
: opt_attributes
opt_modifiers
type
namespace_or_type_name
{
if (RootContext.Documentation != null)
tmpComment = Lexer.consume_doc_comment ();
}
OPEN_BRACE
{
implicit_value_parameter_type = (Expression) $3;
lexer.PropertyParsing = true;
}
accessor_declarations
{
lexer.PropertyParsing = false;
has_get = has_set = false;
}
CLOSE_BRACE
{
if ($8 == null)
break;
Property prop;
Accessors accessors = (Accessors) $8;
Accessor get_block = accessors.get_or_add;
Accessor set_block = accessors.set_or_remove;
MemberName name = (MemberName) $4;
if (name.TypeArguments != null)
syntax_error (lexer.Location, "a property can't have type arguments");
prop = new Property (current_class, (Expression) $3, (int) $2, false,
name, (Attributes) $1, get_block, set_block, accessors.declared_in_reverse, current_block);
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
{
Report.Error (1014, GetLocation ($1), "A get or set accessor expected");
$$ = 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 = null;
else
current_local_parameters = indexer_parameters;
lexer.PropertyParsing = false;
anonymous_host = SimpleAnonymousHost.GetSimple ();
}
accessor_body
{
if (has_get) {
Report.Error (1007, (Location) $3, "Property accessor already defined");
break;
}
Accessor accessor = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, (Location) $3);
has_get = true;
current_local_parameters = null;
lexer.PropertyParsing = true;
SimpleAnonymousHost.Simple.Propagate (accessor);
anonymous_host = null;
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 [] args;
Parameter implicit_value_parameter = new Parameter (
implicit_value_parameter_type, "value",
Parameter.Modifier.NONE, null, (Location) $3);
if (parsing_indexer == false) {
args = new Parameter [1];
args [0] = implicit_value_parameter;
current_local_parameters = new Parameters (args);
} else {
Parameter [] fpars = indexer_parameters.FixedParameters;
if (fpars != null){
int count = fpars.Length;
args = new Parameter [count + 1];
fpars.CopyTo (args, 0);
args [count] = implicit_value_parameter;
} else
args = null;
current_local_parameters = new Parameters (
args);
}
lexer.PropertyParsing = false;
anonymous_host = SimpleAnonymousHost.GetSimple ();
}
accessor_body
{
if (has_set) {
Report.Error (1007, ((LocatedToken) $3).Location, "Property accessor already defined");
break;
}
Accessor accessor = new Accessor ((ToplevelBlock) $5, (int) $2, (Attributes) $1, (Location) $3);
has_set = true;
current_local_parameters = null;
lexer.PropertyParsing = true;
SimpleAnonymousHost.Simple.Propagate (accessor);
anonymous_host = null;
if (RootContext.Documentation != null
&& Lexer.doc_state == XmlCommentState.Error)
Lexer.doc_state = XmlCommentState.NotAllowed;
$$ = accessor;
}
;
accessor_body
: block
| SEMICOLON { $$ = null; }
;
interface_declaration
: opt_attributes
opt_modifiers
opt_partial
INTERFACE
{
lexer.ConstraintsParsing = true;
}
type_name
{
MemberName name = MakeName ((MemberName) $6);
push_current_class (new Interface (
current_namespace, current_class, name, (int) $2,
(Attributes) $1), $3);
}
opt_class_base
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
if ($8 != null)
current_container.AddBasesForPart (current_class, (ArrayList) $8);
current_class.SetParameterInfo ((ArrayList) $9);
if (RootContext.Documentation != null) {
current_container.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
interface_body
{
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
: interface_method_declaration
{
if ($1 == null)
break;
Method m = (Method) $1;
if (m.IsExplicitImpl)
Report.Error (541, m.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
m.GetSignatureForError ());
current_container.AddMethod (m);
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
| interface_property_declaration
{
if ($1 == null)
break;
Property p = (Property) $1;
if (p.IsExplicitImpl)
Report.Error (541, p.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
p.GetSignatureForError ());
current_container.AddProperty (p);
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
| interface_event_declaration
{
if ($1 != null){
Event e = (Event) $1;
if (e.IsExplicitImpl)
Report.Error (541, e.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
e.GetSignatureForError ());
current_container.AddEvent (e);
}
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
| interface_indexer_declaration
{
if ($1 == null)
break;
Indexer i = (Indexer) $1;
if (i.IsExplicitImpl)
Report.Error (541, i.Location, "`{0}': explicit interface declaration can only be declared in a class or struct",
i.GetSignatureForError ());
current_container.AddIndexer (i);
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
| delegate_declaration
{
if ($1 != null) {
Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
((MemberCore)$1).GetSignatureForError ());
}
}
| class_declaration
{
if ($1 != null) {
Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
((MemberCore)$1).GetSignatureForError ());
}
}
| struct_declaration
{
if ($1 != null) {
Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
((MemberCore)$1).GetSignatureForError ());
}
}
| enum_declaration
{
if ($1 != null) {
Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
((MemberCore)$1).GetSignatureForError ());
}
}
| interface_declaration
{
if ($1 != null) {
Report.Error (524, GetLocation ($1), "`{0}': Interfaces cannot declare classes, structs, interfaces, delegates, enumerations or constants",
((MemberCore)$1).GetSignatureForError ());
}
}
| constant_declaration
{
Report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants");
}
;
opt_new
: opt_modifiers
{
int val = (int) $1;
val = Modifiers.Check (Modifiers.NEW | Modifiers.UNSAFE, val, 0, GetLocation ($1));
$$ = val;
}
;
interface_method_declaration_body
: OPEN_BRACE
{
lexer.ConstraintsParsing = false;
}
opt_statement_list CLOSE_BRACE
{
Report.Error (531, lexer.Location,
"'{0}': interface members cannot have a definition", ((MemberName) $-1).ToString ());
$$ = null;
}
| SEMICOLON
;
interface_method_declaration
: opt_attributes opt_new type namespace_or_type_name
open_parens opt_formal_parameter_list CLOSE_PARENS
{
lexer.ConstraintsParsing = true;
}
opt_type_parameter_constraints_clauses
{
// Refer to the name as $-1 in interface_method_declaration_body
$$ = $4;
}
interface_method_declaration_body
{
lexer.ConstraintsParsing = false;
MemberName name = (MemberName) $4;
if ($9 != null && name.TypeArguments == null)
Report.Error (80, lexer.Location,
"Constraints are not allowed on non-generic declarations");
GenericMethod generic = null;
if (name.TypeArguments != null) {
generic = new GenericMethod (current_namespace, current_class, name,
(Expression) $3, (Parameters) $6);
generic.SetParameterInfo ((ArrayList) $9);
}
$$ = new Method (current_class, generic, (Expression) $3, (int) $2, true, name,
(Parameters) $6, (Attributes) $1);
if (RootContext.Documentation != null)
((Method) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes opt_new VOID namespace_or_type_name
open_parens opt_formal_parameter_list CLOSE_PARENS
{
lexer.ConstraintsParsing = true;
}
opt_type_parameter_constraints_clauses
{
$$ = $4;
}
interface_method_declaration_body
{
lexer.ConstraintsParsing = false;
MemberName name = (MemberName) $4;
if ($9 != null && name.TypeArguments == null)
Report.Error (80, lexer.Location,
"Constraints are not allowed on non-generic declarations");
GenericMethod generic = null;
if (name.TypeArguments != null) {
generic = new GenericMethod (current_namespace, current_class, name,
TypeManager.system_void_expr, (Parameters) $6);
generic.SetParameterInfo ((ArrayList) $9);
}
$$ = new Method (current_class, generic, TypeManager.system_void_expr, (int) $2,
true, name, (Parameters) $6, (Attributes) $1);
if (RootContext.Documentation != null)
((Method) $$).DocComment = Lexer.consume_doc_comment ();
}
;
interface_property_declaration
: opt_attributes
opt_new
type IDENTIFIER
OPEN_BRACE
{
lexer.PropertyParsing = true;
implicit_value_parameter_type = (Expression)$3;
}
accessor_declarations
{
has_get = has_set = false;
lexer.PropertyParsing = false;
implicit_value_parameter_type = null;
}
CLOSE_BRACE
{
LocatedToken lt = (LocatedToken) $4;
MemberName name = new MemberName (lt.Value, lt.Location);
if ($3 == TypeManager.system_void_expr) {
Report.Error (547, lt.Location, "`{0}': property or indexer cannot have void type", lt.Value);
break;
}
Property p = null;
if ($7 == null) {
p = new Property (current_class, (Expression) $3, (int) $2, true,
name, (Attributes) $1,
null, null, false);
Report.Error (548, p.Location, "`{0}': property or indexer must have at least one accessor", p.GetSignatureForError ());
break;
}
Accessors accessor = (Accessors) $7;
p = new Property (current_class, (Expression) $3, (int) $2, true,
name, (Attributes) $1,
accessor.get_or_add, accessor.set_or_remove, accessor.declared_in_reverse);
if (accessor.get_or_add != null && accessor.get_or_add.Block != null) {
Report.Error (531, p.Location, "`{0}.get': interface members cannot have a definition", p.GetSignatureForError ());
$$ = null;
break;
}
if (accessor.set_or_remove != null && accessor.set_or_remove.Block != null) {
Report.Error (531, p.Location, "`{0}.set': interface members cannot have a definition", p.GetSignatureForError ());
$$ = null;
break;
}
if (RootContext.Documentation != null)
p.DocComment = Lexer.consume_doc_comment ();
$$ = p;
}
| opt_attributes
opt_new
type error {
CheckIdentifierToken (yyToken, GetLocation ($4));
$$ = null;
}
;
interface_event_declaration
: opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
{
LocatedToken lt = (LocatedToken) $5;
$$ = new EventField (current_class, (Expression) $4, (int) $2, true,
new MemberName (lt.Value, lt.Location),
(Attributes) $1);
if (RootContext.Documentation != null)
((EventField) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes opt_new EVENT type error {
CheckIdentifierToken (yyToken, GetLocation ($5));
$$ = null;
}
| opt_attributes opt_new EVENT type IDENTIFIER ASSIGN {
LocatedToken lt = (LocatedToken) $5;
Report.Error (68, lt.Location, "`{0}.{1}': event in interface cannot have initializer", current_container.Name, lt.Value);
$$ = null;
}
| opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE
{
implicit_value_parameter_type = (Expression) $4;
lexer.EventParsing = true;
}
event_accessor_declarations
{
lexer.EventParsing = false;
implicit_value_parameter_type = null;
}
CLOSE_BRACE {
Report.Error (69, (Location) $3, "Event in interface cannot have add or remove accessors");
$$ = null;
}
;
interface_indexer_declaration
: opt_attributes opt_new type THIS
OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
OPEN_BRACE
{
lexer.PropertyParsing = true;
implicit_value_parameter_type = (Expression)$3;
}
accessor_declarations
{
has_get = has_set = false;
lexer.PropertyParsing = false;
implicit_value_parameter_type = null;
}
CLOSE_BRACE
{
Indexer i = null;
if ($10 == null) {
i = new Indexer (current_class, (Expression) $3,
new MemberName (TypeContainer.DefaultIndexerName, (Location) $4),
(int) $2, true, (Parameters) $6, (Attributes) $1,
null, null, false);
Report.Error (548, i.Location, "`{0}': property or indexer must have at least one accessor", i.GetSignatureForError ());
break;
}
Accessors accessors = (Accessors) $10;
i = new Indexer (current_class, (Expression) $3,
new MemberName (TypeContainer.DefaultIndexerName, (Location) $4),
(int) $2, true, (Parameters) $6, (Attributes) $1,
accessors.get_or_add, accessors.set_or_remove, accessors.declared_in_reverse);
if (accessors.get_or_add != null && accessors.get_or_add.Block != null) {
Report.Error (531, i.Location, "`{0}.get': interface members cannot have a definition", i.GetSignatureForError ());
$$ = null;
break;
}
if (accessors.set_or_remove != null && accessors.set_or_remove.Block != null) {
Report.Error (531, i.Location, "`{0}.set': interface members cannot have a definition", i.GetSignatureForError ());
$$ = null;
break;
}
if (RootContext.Documentation != null)
i.DocComment = ConsumeStoredComment ();
$$ = i;
}
;
operator_declaration
: opt_attributes opt_modifiers operator_declarator
{
anonymous_host = SimpleAnonymousHost.GetSimple ();
}
operator_body
{
if ($3 == null)
break;
OperatorDeclaration decl = (OperatorDeclaration) $3;
Parameter [] param_list = new Parameter [decl.arg2type != null ? 2 : 1];
param_list[0] = new Parameter (decl.arg1type, decl.arg1name, Parameter.Modifier.NONE, null, decl.location);
if (decl.arg2type != null)
param_list[1] = new Parameter (decl.arg2type, decl.arg2name, Parameter.Modifier.NONE, null, decl.location);
Operator op = new Operator (
current_class, decl.optype, decl.ret_type, (int) $2,
new Parameters (param_list),
(ToplevelBlock) $5, (Attributes) $1, decl.location);
if (RootContext.Documentation != null) {
op.DocComment = tmpComment;
Lexer.doc_state = XmlCommentState.Allowed;
}
SimpleAnonymousHost.Simple.Propagate (op);
anonymous_host = null;
// Note again, checking is done in semantic analysis
current_container.AddOperator (op);
current_local_parameters = null;
}
;
operator_body
: block
| SEMICOLON { $$ = null; }
;
operator_declarator
: type OPERATOR overloadable_operator
open_parens opt_attributes opt_parameter_modifier type IDENTIFIER CLOSE_PARENS
{
// TODO: wrong location
if ((Parameter.Modifier)$6 != Parameter.Modifier.NONE)
Error_ParameterModifierNotValid ((Location) $2);
LocatedToken lt = (LocatedToken) $8;
Operator.OpType op = (Operator.OpType) $3;
CheckUnaryOperator (op, lt.Location);
if (op == Operator.OpType.Addition)
op = Operator.OpType.UnaryPlus;
if (op == Operator.OpType.Subtraction)
op = Operator.OpType.UnaryNegation;
Parameter [] pars = new Parameter [1];
Expression type = (Expression) $7;
pars [0] = new Parameter (type, lt.Value, Parameter.Modifier.NONE, (Attributes) $5, lt.Location);
current_local_parameters = new Parameters (pars);
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
$$ = new OperatorDeclaration (op, (Expression) $1, type, lt.Value,
null, null, (Location) $2);
}
| type OPERATOR overloadable_operator
open_parens
opt_attributes opt_parameter_modifier type IDENTIFIER COMMA
opt_attributes opt_parameter_modifier type IDENTIFIER
CLOSE_PARENS
{
// TODO: wrong location
if ((Parameter.Modifier)$6 != Parameter.Modifier.NONE || (Parameter.Modifier)$11 != Parameter.Modifier.NONE)
Error_ParameterModifierNotValid ((Location) $2);
LocatedToken ltParam1 = (LocatedToken) $8;
LocatedToken ltParam2 = (LocatedToken) $13;
CheckBinaryOperator ((Operator.OpType) $3, (Location) $2);
Parameter [] pars = new Parameter [2];
Expression typeL = (Expression) $7;
Expression typeR = (Expression) $12;
pars [0] = new Parameter (typeL, ltParam1.Value, Parameter.Modifier.NONE, (Attributes) $5, ltParam1.Location);
pars [1] = new Parameter (typeR, ltParam2.Value, Parameter.Modifier.NONE, (Attributes) $10, ltParam2.Location);
current_local_parameters = new Parameters (pars);
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
$$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1,
typeL, ltParam1.Value,
typeR, ltParam2.Value, (Location) $2);
}
| conversion_operator_declarator
| type OPERATOR overloadable_operator
open_parens
opt_attributes opt_parameter_modifier type IDENTIFIER COMMA
opt_attributes opt_parameter_modifier type IDENTIFIER COMMA error
{
Report.Error (1534, (Location) $2, "Overloaded binary operator `{0}' takes two parameters",
Operator.GetName ((Operator.OpType) $3));
$$ = null;
}
| type OPERATOR overloadable_operator
open_parens CLOSE_PARENS
{
Report.Error (1535, (Location) $2, "Overloaded unary operator `{0}' takes one parameter",
Operator.GetName ((Operator.OpType) $3));
$$ = null;
}
;
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 opt_parameter_modifier type IDENTIFIER CLOSE_PARENS
{
// TODO: wrong location
if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE)
Error_ParameterModifierNotValid (GetLocation ($4));
LocatedToken lt = (LocatedToken) $7;
Parameter [] pars = new Parameter [1];
pars [0] = new Parameter ((Expression) $6, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
current_local_parameters = new Parameters (pars);
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
$$ = new OperatorDeclaration (Operator.OpType.Implicit, (Expression) $3, (Expression) $6, lt.Value,
null, null, (Location) $2);
}
| EXPLICIT OPERATOR type open_parens opt_parameter_modifier type IDENTIFIER CLOSE_PARENS
{
// TODO: wrong location
if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE)
Error_ParameterModifierNotValid (GetLocation ($4));
LocatedToken lt = (LocatedToken) $7;
Parameter [] pars = new Parameter [1];
pars [0] = new Parameter ((Expression) $6, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
current_local_parameters = new Parameters (pars);
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
$$ = new OperatorDeclaration (Operator.OpType.Explicit, (Expression) $3, (Expression) $6, lt.Value,
null, null, (Location) $2);
}
| IMPLICIT error
{
syntax_error ((Location) $1, "'operator' expected");
}
| EXPLICIT error
{
syntax_error ((Location) $1, "'operator' expected");
}
;
constructor_declaration
: opt_attributes
opt_modifiers
constructor_declarator
constructor_body
{
Constructor c = (Constructor) $3;
c.Block = (ToplevelBlock) $4;
c.OptAttributes = (Attributes) $1;
c.ModFlags = (int) $2;
if (RootContext.Documentation != null)
c.DocComment = ConsumeStoredComment ();
if (c.Name == current_container.Basename){
if ((c.ModFlags & Modifiers.STATIC) != 0){
if ((c.ModFlags & Modifiers.Accessibility) != 0){
Report.Error (515, c.Location,
"`{0}': access modifiers are not allowed on static constructors",
c.GetSignatureForError ());
}
c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
if (c.Initializer != null){
Report.Error (514, c.Location,
"`{0}': static constructor cannot have an explicit `this' or `base' constructor call",
c.GetSignatureForError ());
}
} else {
c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
}
} else {
// We let another layer check the validity of the constructor.
//Console.WriteLine ("{0} and {1}", c.Name, current_container.Basename);
}
current_container.AddConstructor (c);
current_local_parameters = null;
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
;
constructor_declarator
: constructor_header
{
$$ = $1;
}
| constructor_header constructor_initializer
{
((Constructor)$1).Initializer = (ConstructorInitializer) $2;
$$ = $1;
}
;
constructor_header
: IDENTIFIER
{
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
open_parens opt_formal_parameter_list CLOSE_PARENS
{
LocatedToken lt = (LocatedToken) $1;
current_local_parameters = (Parameters) $4;
current_block = new ToplevelBlock (null, current_local_parameters, null, lt.Location);
$$ = new Constructor (current_class, lt.Value, 0, current_local_parameters,
null, lt.Location);
anonymous_host = (IAnonymousHost) $$;
}
;
constructor_body
: block_prepared
| SEMICOLON { current_block = null; $$ = null; }
;
constructor_initializer
: COLON BASE open_parens opt_argument_list CLOSE_PARENS
{
$$ = new ConstructorBaseInitializer ((ArrayList) $4, (Location) $2);
}
| COLON THIS open_parens opt_argument_list CLOSE_PARENS
{
$$ = new ConstructorThisInitializer ((ArrayList) $4, (Location) $2);
}
| COLON error {
Report.Error (1018, (Location) $1, "Keyword this or base expected");
$$ = null;
}
;
opt_finalizer
: /* EMPTY */ { $$ = 0; }
| UNSAFE { $$ = Modifiers.UNSAFE; }
| EXTERN { $$ = Modifiers.EXTERN; }
;
destructor_declaration
: opt_attributes opt_finalizer TILDE
{
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
}
IDENTIFIER OPEN_PARENS CLOSE_PARENS block
{
LocatedToken lt = (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 {
Location l = lt.Location;
int m = (int) $2;
if (!RootContext.StdLib && current_container.Name == "System.Object")
m |= Modifiers.PROTECTED | Modifiers.VIRTUAL;
else
m |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
Method d = new Destructor (
current_class, TypeManager.system_void_expr, m, "Finalize",
Parameters.EmptyReadOnlyParameters, (Attributes) $1, l);
if (RootContext.Documentation != null)
d.DocComment = ConsumeStoredComment ();
d.Block = (ToplevelBlock) $8;
current_container.AddMethod (d);
}
}
;
event_declaration
: opt_attributes
opt_modifiers
EVENT type variable_declarators SEMICOLON
{
current_array_type = null;
foreach (VariableDeclaration var in (ArrayList) $5) {
MemberName name = new MemberName (var.identifier,
var.Location);
EventField e = new EventField (
current_class, (Expression) $4, (int) $2, false, name,
(Attributes) $1);
e.Initializer = var.expression_or_array_initializer;
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 namespace_or_type_name
OPEN_BRACE
{
implicit_value_parameter_type = (Expression) $4;
lexer.EventParsing = true;
}
event_accessor_declarations
{
lexer.EventParsing = false;
}
CLOSE_BRACE
{
MemberName name = (MemberName) $5;
if ($8 == null){
Report.Error (65, (Location) $3, "`{0}.{1}': event property must have both add and remove accessors",
current_container.Name, name.ToString ());
$$ = null;
} else {
Accessors accessors = (Accessors) $8;
if (name.TypeArguments != null)
syntax_error (lexer.Location, "an event can't have type arguments");
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, (Expression) $4, (int) $2, false, 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;
}
}
}
| opt_attributes opt_modifiers EVENT type namespace_or_type_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");
else
Report.Error (71, mn.Location, "Event declaration should use property syntax");
if (RootContext.Documentation != null)
Lexer.doc_state = XmlCommentState.Allowed;
}
;
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
{
Parameter [] args = new Parameter [1];
Parameter implicit_value_parameter = new Parameter (
implicit_value_parameter_type, "value",
Parameter.Modifier.NONE, null, (Location) $2);
args [0] = implicit_value_parameter;
current_local_parameters = new Parameters (args);
lexer.EventParsing = false;
anonymous_host = SimpleAnonymousHost.GetSimple ();
}
block
{
Accessor accessor = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, (Location) $2);
lexer.EventParsing = true;
current_local_parameters = null;
SimpleAnonymousHost.Simple.Propagate (accessor);
anonymous_host = null;
$$ = accessor;
}
| opt_attributes ADD error {
Report.Error (73, (Location) $2, "An add or remove accessor must have a body");
$$ = null;
}
| opt_attributes modifiers ADD {
Report.Error (1609, (Location) $3, "Modifiers cannot be placed on event accessor declarations");
$$ = null;
}
;
remove_accessor_declaration
: opt_attributes REMOVE
{
Parameter [] args = new Parameter [1];
Parameter implicit_value_parameter = new Parameter (
implicit_value_parameter_type, "value",
Parameter.Modifier.NONE, null, (Location) $2);
args [0] = implicit_value_parameter;
current_local_parameters = new Parameters (args);
lexer.EventParsing = false;
}
block
{
$$ = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, (Location) $2);
lexer.EventParsing = true;
}
| opt_attributes REMOVE error {
Report.Error (73, (Location) $2, "An add or remove accessor must have a body");
$$ = null;
}
| opt_attributes modifiers REMOVE {
Report.Error (1609, (Location) $3, "Modifiers cannot be placed on event accessor declarations");
$$ = null;
}
;
indexer_declaration
: opt_attributes opt_modifiers indexer_declarator
OPEN_BRACE
{
IndexerDeclaration decl = (IndexerDeclaration) $3;
implicit_value_parameter_type = decl.type;
lexer.PropertyParsing = true;
parsing_indexer = true;
indexer_parameters = decl.param_list;
anonymous_host = SimpleAnonymousHost.GetSimple ();
}
accessor_declarations
{
lexer.PropertyParsing = false;
has_get = has_set = false;
parsing_indexer = false;
}
CLOSE_BRACE
{
if ($6 == null)
break;
// The signature is computed from the signature of the indexer. Look
// at section 3.6 on the spec
Indexer indexer;
IndexerDeclaration decl = (IndexerDeclaration) $3;
Accessors accessors = (Accessors) $6;
Accessor get_block = accessors.get_or_add;
Accessor set_block = accessors.set_or_remove;
MemberName name;
if (decl.interface_type != null)
name = new MemberName (
decl.interface_type, TypeContainer.DefaultIndexerName, decl.location);
else
name = new MemberName (TypeContainer.DefaultIndexerName, decl.location);
indexer = new Indexer (current_class, decl.type, name,
(int) $2, false, decl.param_list, (Attributes) $1,
get_block, set_block, accessors.declared_in_reverse);
if (RootContext.Documentation != null)
indexer.DocComment = ConsumeStoredComment ();
current_container.AddIndexer (indexer);
current_local_parameters = null;
implicit_value_parameter_type = null;
indexer_parameters = null;
}
;
indexer_declarator
: type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
{
Parameters pars = (Parameters) $4;
if (pars.HasArglist) {
// "__arglist is not valid in this context"
Report.Error (1669, (Location) $2, "__arglist is not valid in this context");
} else if (pars.Empty){
Report.Error (1551, (Location) $2, "Indexers must have at least one parameter");
}
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
$$ = new IndexerDeclaration ((Expression) $1, null, pars, (Location) $2);
}
| type namespace_or_type_name DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
{
Parameters pars = (Parameters) $6;
if (pars.HasArglist) {
// "__arglist is not valid in this context"
Report.Error (1669, (Location) $4, "__arglist is not valid in this context");
} else if (pars.Empty){
Report.Error (1551, (Location) $4, "Indexers must have at least one parameter");
}
MemberName name = (MemberName) $2;
$$ = new IndexerDeclaration ((Expression) $1, name, pars, (Location) $4);
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
;
enum_declaration
: opt_attributes
opt_modifiers
ENUM IDENTIFIER
opt_enum_base {
if (RootContext.Documentation != null)
enumTypeComment = Lexer.consume_doc_comment ();
}
enum_body
opt_semicolon
{
LocatedToken lt = (LocatedToken) $4;
Location enum_location = lt.Location;
MemberName name = MakeName (new MemberName (lt.Value, enum_location));
Enum e = new Enum (current_namespace, current_class, (Expression) $5, (int) $2,
name, (Attributes) $1);
if (RootContext.Documentation != null)
e.DocComment = enumTypeComment;
EnumMember em = null;
foreach (VariableDeclaration ev in (ArrayList) $7) {
em = new EnumMember (
e, em, ev.identifier, (Expression) ev.expression_or_array_initializer,
ev.OptAttributes, ev.Location);
// if (RootContext.Documentation != null)
em.DocComment = ev.DocComment;
e.AddEnumMember (em);
}
current_container.AddTypeContainer (e);
$$ = e;
}
;
opt_enum_base
: /* empty */ { $$ = TypeManager.system_int32_expr; }
| COLON type { $$ = $2; }
;
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 ArrayList (4); }
| enum_member_declarations opt_comma { $$ = $1; }
;
enum_member_declarations
: enum_member_declaration
{
ArrayList l = new ArrayList (4);
l.Add ($1);
$$ = l;
}
| enum_member_declarations COMMA enum_member_declaration
{
ArrayList l = (ArrayList) $1;
l.Add ($3);
$$ = l;
}
;
enum_member_declaration
: opt_attributes IDENTIFIER
{
VariableDeclaration vd = new VariableDeclaration (
(LocatedToken) $2, null, (Attributes) $1);
if (RootContext.Documentation != null) {
vd.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
$$ = vd;
}
| opt_attributes IDENTIFIER
{
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.NotAllowed;
}
}
ASSIGN expression
{
VariableDeclaration vd = new VariableDeclaration (
(LocatedToken) $2, $5, (Attributes) $1);
if (RootContext.Documentation != null)
vd.DocComment = ConsumeStoredComment ();
$$ = vd;
}
;
delegate_declaration
: opt_attributes
opt_modifiers
DELEGATE
{
lexer.ConstraintsParsing = true;
}
type type_name
open_parens opt_formal_parameter_list CLOSE_PARENS
{
MemberName name = MakeName ((MemberName) $6);
Parameters p = (Parameters) $8;
if (p.HasArglist) {
// TODO: wrong location
Report.Error (1669, name.Location, "__arglist is not valid in this context");
}
Delegate del = new Delegate (current_namespace, current_class, (Expression) $5,
(int) $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;
}
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
}
SEMICOLON
{
current_delegate.SetParameterInfo ((ArrayList) $11);
$$ = current_delegate;
current_delegate = null;
}
;
opt_nullable
: /* empty */
{
lexer.CheckNullable (false);
$$ = false;
}
| INTERR
{
lexer.CheckNullable (true);
$$ = true;
}
;
namespace_or_type_name
: IDENTIFIER opt_type_argument_list
{
LocatedToken lt = (LocatedToken) $1;
$$ = new MemberName (lt.Value, (TypeArguments) $2, lt.Location);
}
| IDENTIFIER DOUBLE_COLON IDENTIFIER {
LocatedToken lt1 = (LocatedToken) $1;
LocatedToken lt2 = (LocatedToken) $3;
$$ = new MemberName (lt1.Value, lt2.Value, lt2.Location);
}
| namespace_or_type_name DOT IDENTIFIER opt_type_argument_list {
LocatedToken lt = (LocatedToken) $3;
$$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location);
}
;
member_name
: IDENTIFIER opt_type_parameter_list
{
LocatedToken lt = (LocatedToken) $1;
$$ = new MemberName (lt.Value, (TypeArguments) $2, lt.Location);
}
| namespace_or_type_name DOT IDENTIFIER opt_type_parameter_list
{
LocatedToken lt = (LocatedToken) $3;
$$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location);
}
;
type_name
: IDENTIFIER opt_type_parameter_list
{
LocatedToken lt = (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.Version == LanguageVersion.ISO_1)
Report.FeatureIsNotISO1 (lexer.Location, "generics");
$$ = $2;
}
;
//
// Generics parameters (identifiers only, with attributes), used in type, method declarations
//
opt_type_parameter_list
: /* empty */ { $$ = null; }
| OP_GENERICS_LT type_arguments OP_GENERICS_GT
{
if (RootContext.Version == LanguageVersion.ISO_1)
Report.FeatureIsNotISO1 (lexer.Location, "generics");
$$ = $2;
}
;
type_arguments
: type_argument
{
TypeArguments type_args = new TypeArguments (lexer.Location);
type_args.Add ((Expression) $1);
$$ = type_args;
}
| type_arguments COMMA type_argument
{
TypeArguments type_args = (TypeArguments) $1;
type_args.Add ((Expression) $3);
$$ = type_args;
}
;
type_argument
: type
{
$$ = $1;
}
| attribute_sections type
{
SimpleName sn = $2 as SimpleName;
if (sn == null)
Error_TypeExpected (GetLocation ($2));
else
$2 = new TypeParameterName (sn.Name, (Attributes) $1, lexer.Location);
$$ = $2;
}
;
/*
* Before you think of adding a return_type, notice that we have been
* using two rules in the places where it matters (one rule using type
* and another identical one that uses VOID as the return type). This
* gets rid of a shift/reduce couple
*/
type
: namespace_or_type_name opt_nullable
{
MemberName name = (MemberName) $1;
$$ = name.GetTypeExpression ();
if ((bool) $2)
$$ = new ComposedCast ((Expression) $$, "?", lexer.Location);
}
| builtin_types opt_nullable
{
if ((bool) $2)
$$ = new ComposedCast ((Expression) $1, "?", lexer.Location);
}
| array_type
| pointer_type
;
pointer_type
: type 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 ((Expression) $1, "*", Lexer.Location);
}
| VOID STAR
{
$$ = new ComposedCast (TypeManager.system_void_expr, "*", (Location) $1);
}
;
non_expression_type
: builtin_types opt_nullable
{
if ((bool) $2)
$$ = new ComposedCast ((Expression) $1, "?", lexer.Location);
}
| non_expression_type rank_specifier
{
Location loc = GetLocation ($1);
if (loc.IsNull)
loc = lexer.Location;
$$ = new ComposedCast ((Expression) $1, (string) $2, loc);
}
| non_expression_type STAR
{
Location loc = GetLocation ($1);
if (loc.IsNull)
loc = lexer.Location;
$$ = new ComposedCast ((Expression) $1, "*", loc);
}
| expression rank_specifiers
{
$$ = new ComposedCast ((Expression) $1, (string) $2);
}
| expression STAR
{
$$ = new ComposedCast ((Expression) $1, "*");
}
//
// We need this because the parser will happily go and reduce IDENTIFIER STAR
// through this different path
//
| multiplicative_expression STAR
{
$$ = new ComposedCast ((Expression) $1, "*");
}
;
type_list
: type
{
ArrayList types = new ArrayList (4);
types.Add ($1);
$$ = types;
}
| type_list COMMA type
{
ArrayList types = (ArrayList) $1;
types.Add ($3);
$$ = types;
}
;
/*
* replaces all the productions for isolating the various
* simple types, but we need this to reuse it easily in local_variable_type
*/
builtin_types
: OBJECT { $$ = 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; }
| VOID { $$ = TypeManager.system_void_expr; }
;
array_type
: type rank_specifiers opt_nullable
{
string rank_specifiers = (string) $2;
if ((bool) $3)
rank_specifiers += "?";
$$ = current_array_type = new ComposedCast ((Expression) $1, rank_specifiers);
}
;
//
// Expressions, section 7.5
//
primary_expression
: literal
{
// 7.5.1: Literals
}
| type_name
{
MemberName mn = (MemberName) $1;
$$ = mn.GetTypeExpression ();
}
| IDENTIFIER DOUBLE_COLON IDENTIFIER
{
LocatedToken lt1 = (LocatedToken) $1;
LocatedToken lt2 = (LocatedToken) $3;
$$ = new QualifiedAliasMember (lt1.Value, lt2.Value, lt2.Location);
}
| parenthesized_expression
| default_value_expression
| member_access
| invocation_expression
| element_access
| this_access
| base_access
| post_increment_expression
| post_decrement_expression
| new_expression
| typeof_expression
| sizeof_expression
| checked_expression
| unchecked_expression
| pointer_member_access
| anonymous_method_expression
;
literal
: boolean_literal
| integer_literal
| real_literal
| LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value, lexer.Location); }
| LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value, lexer.Location); }
| NULL { $$ = new NullLiteral (lexer.Location); }
;
real_literal
: LITERAL_FLOAT { $$ = new FloatLiteral ((float) lexer.Value, lexer.Location); }
| LITERAL_DOUBLE { $$ = new DoubleLiteral ((double) lexer.Value, lexer.Location); }
| LITERAL_DECIMAL { $$ = new DecimalLiteral ((decimal) lexer.Value, lexer.Location); }
;
integer_literal
: LITERAL_INTEGER {
object v = lexer.Value;
if (v is int){
$$ = new IntLiteral ((int) v, lexer.Location);
} else if (v is uint)
$$ = new UIntLiteral ((UInt32) v, lexer.Location);
else if (v is long)
$$ = new LongLiteral ((Int64) v, lexer.Location);
else if (v is ulong)
$$ = new ULongLiteral ((UInt64) v, lexer.Location);
else
Console.WriteLine ("OOPS. Unexpected result from scanner");
}
;
boolean_literal
: TRUE { $$ = new BoolLiteral (true, lexer.Location); }
| FALSE { $$ = new BoolLiteral (false, lexer.Location); }
;
parenthesized_expression_0
: OPEN_PARENS expression CLOSE_PARENS
{
$$ = $2;
lexer.Deambiguate_CloseParens ($$);
// After this, the next token returned is one of
// CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST (CLOSE_PARENS), CLOSE_PARENS_OPEN_PARENS
// or CLOSE_PARENS_MINUS.
}
| OPEN_PARENS expression error { CheckToken (1026, yyToken, "Expecting ')'", lexer.Location); }
;
parenthesized_expression
: parenthesized_expression_0 CLOSE_PARENS_NO_CAST
{
$$ = $1;
}
| parenthesized_expression_0 CLOSE_PARENS
{
$$ = $1;
}
| parenthesized_expression_0 CLOSE_PARENS_MINUS
{
// If a parenthesized expression is followed by a minus, we need to wrap
// the expression inside a ParenthesizedExpression for the CS0075 check
// in Binary.DoResolve().
$$ = new ParenthesizedExpression ((Expression) $1);
}
;
member_access
: primary_expression DOT IDENTIFIER opt_type_argument_list
{
LocatedToken lt = (LocatedToken) $3;
$$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location);
}
| predefined_type DOT IDENTIFIER opt_type_argument_list
{
LocatedToken lt = (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);
}
;
predefined_type
: builtin_types
;
invocation_expression
: primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
{
if ($1 == null)
Report.Error (1, (Location) $2, "Parse error");
else
$$ = new Invocation ((Expression) $1, (ArrayList) $3);
}
| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS CLOSE_PARENS
{
$$ = new Invocation ((Expression) $1, new ArrayList ());
}
| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS primary_expression
{
$$ = new InvocationOrCast ((Expression) $1, (Expression) $3);
}
| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS non_simple_argument CLOSE_PARENS
{
ArrayList args = new ArrayList (1);
args.Add ($4);
$$ = new Invocation ((Expression) $1, args);
}
| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS argument_list COMMA argument CLOSE_PARENS
{
ArrayList args = ((ArrayList) $4);
args.Add ($6);
$$ = new Invocation ((Expression) $1, args);
}
;
opt_object_initializer
: /* empty */ { $$ = null; }
| OPEN_BRACE variable_declarators CLOSE_BRACE
{
ArrayList vars = (ArrayList) $2;
ArrayList inits = new ArrayList (vars.Count);
foreach (VariableDeclaration variable in vars) {
Initializer i = new Initializer (variable.identifier, variable.expression_or_array_initializer);
inits.Add (i);
}
$$ = inits;
}
;
opt_object_or_collection_initializer
: /* empty */ { $$ = null; }
| object_or_collection_initializer
;
object_or_collection_initializer
: object_initializer
| collection_initializer
;
object_initializer
: OPEN_BRACE opt_member_initializer_list CLOSE_BRACE
{
if ($2 == null)
$$ = null;
else
$$ = new ObjectInitializer ((ArrayList)$2);
}
| OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE
{
$$ = new ObjectInitializer ((ArrayList) $2);
}
;
opt_member_initializer_list
: /* empty */ { $$ = null; }
| member_initializer_list
;
member_initializer_list
: member_initializer
{
ArrayList a = new ArrayList ();
a.Add ($1);
$$ = a;
}
| member_initializer_list COMMA member_initializer
{
ArrayList a = (ArrayList)$1;
a.Add ($3);
$$ = a;
}
;
member_initializer
: IDENTIFIER ASSIGN initializer_value
{
LocatedToken id = $1 as LocatedToken;
IInitializable i = $3 as IInitializable;
if (i != null)
$$ = new Initializer (id.Value, i);
else
$$ = new Initializer (id.Value, (Expression)$3);
}
;
initializer_value
: expression
| object_or_collection_initializer
;
collection_initializer
: OPEN_BRACE element_initializer_list CLOSE_BRACE
{
$$ = new CollectionInitializer ((ArrayList) $2);
}
| OPEN_BRACE element_initializer_list COMMA CLOSE_BRACE
{
$$ = new CollectionInitializer ((ArrayList) $2);
}
;
element_initializer_list
: element_initializer
{
ArrayList a = new ArrayList ();
a.Add ($1);
$$ = a;
}
| element_initializer_list COMMA element_initializer
{
ArrayList a = $1 as ArrayList;
a.Add ($3);
$$ = a;
}
;
element_initializer
: non_assignment_expression
;
opt_argument_list
: /* empty */ { $$ = null; }
| argument_list
;
argument_list
: argument
{
ArrayList list = new ArrayList (4);
list.Add ($1);
$$ = list;
}
| argument_list COMMA argument
{
ArrayList list = (ArrayList) $1;
list.Add ($3);
$$ = list;
}
| argument_list error {
CheckToken (1026, yyToken, "Expected `,' or `)'", GetLocation ($2));
$$ = null;
}
;
argument
: expression
{
$$ = new Argument ((Expression) $1, Argument.AType.Expression);
}
| non_simple_argument
{
$$ = $1;
}
;
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 argument_list CLOSE_PARENS
{
ArrayList list = (ArrayList) $3;
Argument[] args = new Argument [list.Count];
list.CopyTo (args, 0);
Expression expr = new Arglist (args, (Location) $1);
$$ = new Argument (expr, Argument.AType.Expression);
}
| ARGLIST OPEN_PARENS CLOSE_PARENS
{
$$ = new Argument (new Arglist ((Location) $1), Argument.AType.Expression);
}
| ARGLIST
{
$$ = new Argument (new ArglistAccess ((Location) $1), Argument.AType.ArgList);
}
;
variable_reference
: expression { note ("section 5.4"); $$ = $1; }
;
element_access
: primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET
{
$$ = new ElementAccess ((Expression) $1, (ArrayList) $3);
}
| primary_expression 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 (expr, (string) $2);
} else if (!(expr is SimpleName || expr is MemberAccess || expr is ConstructedType || expr is QualifiedAliasMember)){
Error_ExpectingTypeName (expr);
$$ = TypeManager.system_object_expr;
} else {
//
// So we extract the string corresponding to the SimpleName
// or MemberAccess
//
$$ = new ComposedCast (expr, (string) $2);
}
current_array_type = (Expression)$$;
}
;
expression_list
: expression
{
ArrayList list = new ArrayList (4);
list.Add ($1);
$$ = list;
}
| expression_list COMMA expression
{
ArrayList list = (ArrayList) $1;
list.Add ($3);
$$ = list;
}
;
this_access
: THIS
{
$$ = new This (current_block, (Location) $1);
}
;
base_access
: BASE DOT IDENTIFIER opt_type_argument_list
{
LocatedToken lt = (LocatedToken) $3;
$$ = new BaseAccess (lt.Value, (TypeArguments) $4, lt.Location);
}
| BASE OPEN_BRACKET expression_list CLOSE_BRACKET
{
$$ = new BaseIndexerAccess ((ArrayList) $3, (Location) $1);
}
| BASE error {
Report.Error (175, (Location) $1, "Use of keyword `base' is not valid in this context");
$$ = null;
}
;
post_increment_expression
: primary_expression OP_INC
{
$$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
(Expression) $1, (Location) $2);
}
;
post_decrement_expression
: primary_expression OP_DEC
{
$$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
(Expression) $1, (Location) $2);
}
;
new_expression
: object_or_delegate_creation_expression
| array_creation_expression
| anonymous_type_expression
;
object_or_delegate_creation_expression
: NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer
{
if ($6 != null) {
if (RootContext.Version < LanguageVersion.LINQ) {
Error_ExpectingTypeName ((Expression) $2);
$$ = null;
}
else
$$ = new NewInitialize ((Expression) $2, (ArrayList) $4, (IInitializable) $6, (Location) $1);
}
else
$$ = new New ((Expression) $2, (ArrayList) $4, (Location) $1);
}
| NEW type object_or_collection_initializer
{
if (RootContext.Version < LanguageVersion.LINQ) {
Report.Error (1526, (Location) $1, "A new expression requires () or [] after type");
$$ = null;
}
else
$$ = new NewInitialize ((Expression) $2, new ArrayList (), (IInitializable) $3, (Location) $1);
}
;
array_creation_expression
: NEW type OPEN_BRACKET expression_list CLOSE_BRACKET
opt_rank_specifier
opt_array_initializer
{
$$ = new ArrayCreation ((Expression) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, (Location) $1);
}
| NEW type rank_specifiers array_initializer
{
$$ = new ArrayCreation ((Expression) $2, (string) $3, (ArrayList) $4, (Location) $1);
}
| NEW rank_specifiers array_initializer
{
if (RootContext.Version < LanguageVersion.LINQ) {
Report.Error (1031, (Location) $1, "Type expected");
$$ = null;
}
else
$$ = new ImplicitlyTypedArrayCreation ((string) $2, (ArrayList) $3, (Location) $1);
}
| NEW error
{
Report.Error (1031, (Location) $1, "Type expected");
$$ = null;
}
| NEW type error
{
Report.Error (1526, (Location) $1, "A new expression requires () or [] after type");
$$ = null;
}
;
anonymous_type_expression
: NEW OPEN_BRACE anonymous_type_parameters CLOSE_BRACE
{
if (RootContext.Version < LanguageVersion.LINQ) {
Report.Error (1031, (Location) $1, "Type expected");
$$ = null;
}
else
$$ = new AnonymousType ((ArrayList) $3, current_container, lexer.Location);
}
;
anonymous_type_parameters
: anonymous_type_parameter
{
ArrayList a = new ArrayList (4);
a.Add ($1);
$$ = a;
}
| anonymous_type_parameters COMMA anonymous_type_parameter
{
ArrayList a = (ArrayList) $1;
a.Add ($3);
$$ = a;
}
;
anonymous_type_parameter
: variable_declarator
{
VariableDeclaration v = (VariableDeclaration) $1;
Expression e = v.expression_or_array_initializer;
if (e == null) {
e = new LocalVariableReference (current_block, v.identifier, lexer.Location);
}
$$ = new AnonymousTypeParameter (e, v.identifier);
}
| member_access
{
MemberAccess ma = (MemberAccess) $1;
$$ = new AnonymousTypeParameter (ma, ma.Identifier);
}
;
opt_rank_specifier
: /* empty */
{
$$ = "";
}
| rank_specifiers
{
$$ = $1;
}
;
opt_rank_specifier_or_nullable
: /* empty */
{
$$ = "";
}
| INTERR
{
$$ = "?";
}
| opt_nullable rank_specifiers
{
if ((bool) $1)
$$ = "?" + $2;
else
$$ = $2;
}
| opt_nullable rank_specifiers INTERR
{
if ((bool) $1)
$$ = "?" + $2 + "?";
else
$$ = $2 + "?";
}
;
rank_specifiers
: rank_specifier opt_rank_specifier
{
$$ = (string) $2 + (string) $1;
}
;
rank_specifier
: OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
{
$$ = "[" + (string) $2 + "]";
}
;
opt_dim_separators
: /* empty */
{
$$ = "";
}
| dim_separators
{
$$ = $1;
}
;
dim_separators
: COMMA
{
$$ = ",";
}
| dim_separators COMMA
{
$$ = (string) $1 + ",";
}
;
opt_array_initializer
: /* empty */
{
$$ = null;
}
| array_initializer
{
$$ = $1;
}
;
array_initializer
: OPEN_BRACE CLOSE_BRACE
{
ArrayList list = new ArrayList (4);
$$ = list;
}
| OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
{
$$ = (ArrayList) $2;
}
;
variable_initializer_list
: variable_initializer
{
ArrayList list = new ArrayList (4);
list.Add ($1);
$$ = list;
}
| variable_initializer_list COMMA variable_initializer
{
ArrayList list = (ArrayList) $1;
list.Add ($3);
$$ = list;
}
;
typeof_expression
: TYPEOF
{
pushed_current_array_type = current_array_type;
lexer.TypeOfParsing = true;
}
OPEN_PARENS typeof_type_expression CLOSE_PARENS
{
lexer.TypeOfParsing = false;
Expression type = (Expression)$4;
if (type == TypeManager.system_void_expr)
$$ = new TypeOfVoid ((Location) $1);
else
$$ = new TypeOf (type, (Location) $1);
current_array_type = pushed_current_array_type;
}
;
typeof_type_expression
: type
{
$$ = $1;
}
| unbound_type_name
{
$$ = new UnboundTypeExpression ((MemberName)$1, lexer.Location);
}
;
unbound_type_name
: IDENTIFIER GENERIC_DIMENSION
{
if (RootContext.Version == LanguageVersion.ISO_1)
Report.FeatureIsNotISO1 (lexer.Location, "generics");
LocatedToken lt = (LocatedToken) $1;
TypeArguments ta = new TypeArguments ((int)$2, lt.Location);
$$ = new MemberName (lt.Value, ta, lt.Location);
}
| IDENTIFIER DOUBLE_COLON IDENTIFIER GENERIC_DIMENSION
{
LocatedToken lt = (LocatedToken) $1;
MemberName left = new MemberName (lt.Value, lt.Location);
lt = (LocatedToken) $3;
TypeArguments ta = new TypeArguments ((int)$4, lt.Location);
$$ = new MemberName (left, lt.Value, ta, lt.Location);
}
| unbound_type_name DOT IDENTIFIER GENERIC_DIMENSION
{
LocatedToken lt = (LocatedToken) $3;
TypeArguments ta = new TypeArguments ((int)$4, lt.Location);
$$ = new MemberName ((MemberName)$1, lt.Value, ta, lt.Location);
}
| namespace_or_type_name DOT IDENTIFIER GENERIC_DIMENSION
{
LocatedToken lt = (LocatedToken) $3;
TypeArguments ta = new TypeArguments ((int)$4, lt.Location);
$$ = new MemberName ((MemberName)$1, lt.Value, ta, lt.Location);
}
;
sizeof_expression
: SIZEOF OPEN_PARENS type CLOSE_PARENS {
$$ = new SizeOf ((Expression) $3, (Location) $1);
}
;
checked_expression
: CHECKED OPEN_PARENS expression CLOSE_PARENS
{
$$ = new CheckedExpr ((Expression) $3, (Location) $1);
}
;
unchecked_expression
: UNCHECKED OPEN_PARENS expression CLOSE_PARENS
{
$$ = new UnCheckedExpr ((Expression) $3, (Location) $1);
}
;
pointer_member_access
: primary_expression OP_PTR IDENTIFIER
{
Expression deref;
LocatedToken lt = (LocatedToken) $3;
deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lt.Location);
$$ = new MemberAccess (deref, lt.Value);
}
;
anonymous_method_expression
: DELEGATE opt_anonymous_method_signature
{
start_anonymous (false, (Parameters) $2, (Location) $1);
}
block
{
$$ = end_anonymous ((ToplevelBlock) $4, (Location) $1);
}
;
opt_anonymous_method_signature
: /* empty */ { $$ = null; }
| anonymous_method_signature
;
anonymous_method_signature
: open_parens opt_anonymous_method_parameter_list CLOSE_PARENS
{
if ($2 == null)
$$ = Parameters.EmptyReadOnlyParameters;
else {
ArrayList par_list = (ArrayList) $2;
Parameter [] pars = new Parameter [par_list.Count];
par_list.CopyTo (pars);
$$ = new Parameters (pars);
}
}
;
opt_anonymous_method_parameter_list
: /* empty */ { $$ = null; }
| anonymous_method_parameter_list { $$ = $1; }
;
anonymous_method_parameter_list
: anonymous_method_parameter
{
ArrayList a = new ArrayList (4);
a.Add ($1);
$$ = a;
}
| anonymous_method_parameter_list COMMA anonymous_method_parameter
{
ArrayList a = (ArrayList) $1;
a.Add ($3);
$$ = a;
}
;
anonymous_method_parameter
: opt_parameter_modifier type IDENTIFIER {
LocatedToken lt = (LocatedToken) $3;
$$ = new Parameter ((Expression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location);
}
| PARAMS type IDENTIFIER {
Report.Error (1670, ((LocatedToken) $3).Location, "The `params' modifier is not allowed in anonymous method declaration");
$$ = null;
}
;
default_value_expression
: DEFAULT_OPEN_PARENS type CLOSE_PARENS
{
$$ = new DefaultValueExpression ((Expression) $2, lexer.Location);
}
;
unary_expression
: primary_expression
| BANG prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, (Location) $1);
}
| TILDE prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, (Location) $1);
}
| cast_expression
;
cast_list
: parenthesized_expression_0 CLOSE_PARENS_CAST unary_expression
{
$$ = new Cast ((Expression) $1, (Expression) $3);
}
| parenthesized_expression_0 CLOSE_PARENS_NO_CAST default_value_expression
{
$$ = new Cast ((Expression) $1, (Expression) $3);
}
| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression
{
$$ = new Cast ((Expression) $1, (Expression) $3);
}
;
cast_expression
: cast_list
| OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
{
// TODO: wrong location
$$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
}
;
//
// 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, (Location) $1);
}
| MINUS prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, (Location) $1);
}
| OP_INC prefixed_unary_expression
{
$$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
(Expression) $2, (Location) $1);
}
| OP_DEC prefixed_unary_expression
{
$$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
(Expression) $2, (Location) $1);
}
| STAR prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.Indirection, (Expression) $2, (Location) $1);
}
| BITWISE_AND prefixed_unary_expression
{
$$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, (Location) $1);
}
;
pre_increment_expression
: OP_INC prefixed_unary_expression
{
$$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
(Expression) $2, (Location) $1);
}
;
pre_decrement_expression
: OP_DEC prefixed_unary_expression
{
$$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
(Expression) $2, (Location) $1);
}
;
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);
}
;
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);
}
;
opt_error
: /* empty */
{
$$ = false;
}
| error
{
lexer.PutbackNullable ();
$$ = true;
}
;
nullable_type_or_conditional
: type opt_error
{
if (((bool) $2) && ($1 is ComposedCast))
$$ = ((ComposedCast) $1).RemoveNullable ();
else
$$ = $1;
}
;
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);
}
| relational_expression IS
{
yyErrorFlag = 3;
} nullable_type_or_conditional
{
$$ = new Is ((Expression) $1, (Expression) $4, (Location) $2);
}
| relational_expression AS
{
yyErrorFlag = 3;
} nullable_type_or_conditional
{
$$ = new As ((Expression) $1, (Expression) $4, (Location) $2);
}
;
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);
}
;
conditional_expression
: conditional_or_expression
| conditional_or_expression INTERR expression COLON expression
{
$$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5);
}
| conditional_or_expression OP_COALESCING expression
{
$$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3, lexer.Location);
}
// We'll be resolved into a `parenthesized_expression_0' later on.
| conditional_or_expression INTERR CLOSE_PARENS
{
$$ = new ComposedCast ((Expression) $1, "?", lexer.Location);
lexer.PutbackCloseParens ();
}
;
assignment_expression
: prefixed_unary_expression ASSIGN expression
{
$$ = new Assign ((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
{
ArrayList pars = new ArrayList (4);
pars.Add ($1);
$$ = pars;
}
| lambda_parameter_list COMMA lambda_parameter
{
ArrayList pars = (ArrayList) $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 type IDENTIFIER
{
LocatedToken lt = (LocatedToken) $3;
$$ = new Parameter ((Expression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location);
}
| type IDENTIFIER
{
LocatedToken lt = (LocatedToken) $2;
$$ = new Parameter ((Expression) $1, lt.Value, Parameter.Modifier.NONE, null, lt.Location);
}
| IDENTIFIER
{
LocatedToken lt = (LocatedToken) $1;
$$ = new ImplicitLambdaParameter (lt.Value, lt.Location);
}
;
opt_lambda_parameter_list
: /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; }
| lambda_parameter_list {
ArrayList pars_list = (ArrayList) $1;
$$ = new Parameters ((Parameter[])pars_list.ToArray (typeof (Parameter)));
}
;
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
{
LocatedToken lt = (LocatedToken) $1;
Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location);
start_anonymous (true, new Parameters (p), (Location) $2);
}
lambda_expression_body
{
$$ = end_anonymous ((ToplevelBlock) $4, (Location) $2);
}
| OPEN_PARENS_LAMBDA opt_lambda_parameter_list CLOSE_PARENS ARROW
{
start_anonymous (true, (Parameters) $2, (Location) $4);
}
lambda_expression_body
{
$$ = end_anonymous ((ToplevelBlock) $6, (Location) $4);
}
;
expression
: assignment_expression
| non_assignment_expression
;
non_assignment_expression
: conditional_expression
| lambda_expression
| query_expression
;
constant_expression
: expression
;
boolean_expression
: expression
;
//
// 10 classes
//
class_declaration
: opt_attributes
opt_modifiers
opt_partial
CLASS
{
lexer.ConstraintsParsing = true;
}
type_name
{
MemberName name = MakeName ((MemberName) $6);
int mod_flags = (int) $2;
push_current_class (new Class (
current_namespace, current_class, name,
mod_flags, (Attributes) $1), $3);
}
opt_class_base
opt_type_parameter_constraints_clauses
{
lexer.ConstraintsParsing = false;
if ($8 != null) {
if (current_class.Name == "System.Object") {
Report.Error (537, current_class.Location,
"The class System.Object cannot have a base " +
"class or implement an interface.");
}
current_container.AddBasesForPart (current_class, (ArrayList) $8);
}
current_class.SetParameterInfo ((ArrayList) $9);
if (RootContext.Documentation != null) {
current_container.DocComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
class_body
{
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
{
int m1 = (int) $1;
int m2 = (int) $2;
if ((m1 & m2) != 0) {
Location l = lexer.Location;
Report.Error (1004, l, "Duplicate `{0}' modifier", Modifiers.Name (m2));
}
$$ = (int) (m1 | m2);
}
;
modifier
: NEW { $$ = Modifiers.NEW; }
| PUBLIC { $$ = Modifiers.PUBLIC; }
| PROTECTED { $$ = Modifiers.PROTECTED; }
| INTERNAL { $$ = Modifiers.INTERNAL; }
| PRIVATE { $$ = Modifiers.PRIVATE; }
| ABSTRACT { $$ = Modifiers.ABSTRACT; }
| SEALED { $$ = Modifiers.SEALED; }
| STATIC { $$ = Modifiers.STATIC; }
| READONLY { $$ = Modifiers.READONLY; }
| VIRTUAL { $$ = Modifiers.VIRTUAL; }
| OVERRIDE { $$ = Modifiers.OVERRIDE; }
| EXTERN { $$ = Modifiers.EXTERN; }
| VOLATILE { $$ = Modifiers.VOLATILE; }
| UNSAFE { $$ = Modifiers.UNSAFE; }
;
opt_class_base
: /* empty */ { $$ = null; }
| class_base { $$ = $1; }
;
class_base
: COLON type_list { $$ = $2; }
;
opt_type_parameter_constraints_clauses
: /* empty */ { $$ = null; }
| type_parameter_constraints_clauses
{ $$ = $1; }
;
type_parameter_constraints_clauses
: type_parameter_constraints_clause {
ArrayList constraints = new ArrayList (1);
constraints.Add ($1);
$$ = constraints;
}
| type_parameter_constraints_clauses type_parameter_constraints_clause {
ArrayList constraints = (ArrayList) $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 {
LocatedToken lt = (LocatedToken) $2;
$$ = new Constraints (lt.Value, (ArrayList) $4, lt.Location);
}
;
type_parameter_constraints
: type_parameter_constraint {
ArrayList constraints = new ArrayList (1);
constraints.Add ($1);
$$ = constraints;
}
| type_parameter_constraints COMMA type_parameter_constraint {
ArrayList constraints = (ArrayList) $1;
constraints.Add ($3);
$$ = constraints;
}
;
type_parameter_constraint
: type
| NEW OPEN_PARENS CLOSE_PARENS {
$$ = SpecialConstraint.Constructor;
}
| CLASS {
$$ = SpecialConstraint.ReferenceType;
}
| STRUCT {
$$ = SpecialConstraint.ValueType;
}
;
//
// 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
{
start_block ((Location) $1);
}
opt_statement_list CLOSE_BRACE
{
$$ = end_block ((Location) $4);
}
;
block_prepared
: OPEN_BRACE
opt_statement_list CLOSE_BRACE
{
$$ = end_block ((Location) $3);
}
;
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
;
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
;
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
{
LocatedToken lt = (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
{
current_array_type = null;
if ($1 != null){
DictionaryEntry de = (DictionaryEntry) $1;
Expression e = (Expression) de.Key;
$$ = declare_local_variables (e, (ArrayList) de.Value, e.Location);
}
}
| local_constant_declaration SEMICOLON
{
current_array_type = null;
if ($1 != null){
DictionaryEntry de = (DictionaryEntry) $1;
$$ = declare_local_constants ((Expression) de.Key, (ArrayList) de.Value);
}
}
;
/*
* The following is from Rhys' grammar:
* > Types in local variable declarations must be recognized as
* > expressions to prevent reduce/reduce errors in the grammar.
* > The expressions are converted into types during semantic analysis.
*/
local_variable_type
: primary_expression 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;
if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is ConstructedType || expr is QualifiedAliasMember)) {
Error_ExpectingTypeName (expr);
$$ = null;
} else {
//
// So we extract the string corresponding to the SimpleName
// or MemberAccess
//
if ((string) $2 == "")
$$ = $1;
else
$$ = new ComposedCast ((Expression) $1, (string) $2);
}
}
| builtin_types opt_rank_specifier_or_nullable
{
if ((string) $2 == "")
$$ = $1;
else
$$ = current_array_type = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
}
;
local_variable_pointer_type
: primary_expression STAR
{
Expression expr = (Expression) $1;
if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast || expr is ConstructedType || expr is QualifiedAliasMember)) {
Error_ExpectingTypeName (expr);
$$ = null;
} else
$$ = new ComposedCast ((Expression) $1, "*");
}
| builtin_types STAR
{
$$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
}
| VOID STAR
{
$$ = new ComposedCast (TypeManager.system_void_expr, "*", (Location) $1);
}
| local_variable_pointer_type STAR
{
$$ = new ComposedCast ((Expression) $1, "*");
}
;
local_variable_declaration
: local_variable_type variable_declarators
{
if ($1 != null) {
VarExpr ve = $1 as VarExpr;
if (ve != null)
ve.VariableInitializer = (ArrayList)$2;
$$ = new DictionaryEntry ($1, $2);
} else
$$ = null;
}
| local_variable_pointer_type opt_rank_specifier_or_nullable variable_declarators
{
if ($1 != null){
Expression t;
if ((string) $2 == "")
t = (Expression) $1;
else
t = new ComposedCast ((Expression) $1, (string) $2);
$$ = new DictionaryEntry (t, $3);
} else
$$ = null;
}
;
local_constant_declaration
: CONST local_variable_type constant_declarators
{
if ($2 != null)
$$ = new DictionaryEntry ($2, $3);
else
$$ = null;
}
;
expression_statement
: statement_expression SEMICOLON { $$ = $1; }
;
//
// We have to do the wrapping here and not in the case above,
// because statement_expression is used for example in for_statement
//
statement_expression
: expression
{
Expression expr = (Expression) $1;
ExpressionStatement s = expr as ExpressionStatement;
if (s == null) {
Report.Error (201, expr.Location, "Only assignment, call, increment, decrement, and new object expressions can be used as a statement");
$$ = null;
}
$$ = new StatementExpression (s);
}
| error
{
Report.Error (1002, GetLocation ($1), "Expecting `;'");
$$ = null;
}
;
object_creation_expression
: object_or_delegate_creation_expression
{ note ("complain if this is a delegate maybe?"); }
;
selection_statement
: if_statement
| switch_statement
;
if_statement
: IF OPEN_PARENS boolean_expression CLOSE_PARENS
embedded_statement
{
Location l = (Location) $1;
$$ = new If ((Expression) $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 boolean_expression CLOSE_PARENS
embedded_statement ELSE embedded_statement
{
Location l = (Location) $1;
$$ = new If ((Expression) $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
{
if (switch_stack == null)
switch_stack = new Stack (2);
switch_stack.Push (current_block);
}
expression CLOSE_PARENS
switch_block
{
$$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) $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 ArrayList ();
}
| switch_sections
;
switch_sections
: switch_section
{
ArrayList sections = new ArrayList (4);
sections.Add ($1);
$$ = sections;
}
| switch_sections switch_section
{
ArrayList sections = (ArrayList) $1;
sections.Add ($2);
$$ = sections;
}
;
switch_section
: switch_labels
{
current_block = current_block.CreateSwitchBlock (lexer.Location);
}
statement_list
{
$$ = new SwitchSection ((ArrayList) $1, current_block.Explicit);
}
;
switch_labels
: switch_label
{
ArrayList labels = new ArrayList (4);
labels.Add ($1);
$$ = labels;
}
| switch_labels switch_label
{
ArrayList labels = (ArrayList) ($1);
labels.Add ($2);
$$ = labels;
}
;
switch_label
: CASE constant_expression COLON { $$ = new SwitchLabel ((Expression) $2, (Location) $1); }
| DEFAULT_COLON { $$ = new SwitchLabel (null, (Location) $1); }
| error {
Report.Error (
1523, GetLocation ($1),
"The keyword case or default must precede code in switch block");
}
;
iteration_statement
: while_statement
| do_statement
| for_statement
| foreach_statement
;
while_statement
: WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
{
Location l = (Location) $1;
$$ = new While ((Expression) $3, (Statement) $5, l);
}
;
do_statement
: DO embedded_statement
WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
{
Location l = (Location) $1;
$$ = new Do ((Statement) $2, (Expression) $5, l);
}
;
for_statement
: FOR open_parens
opt_for_initializer SEMICOLON
{
Location l = lexer.Location;
start_block (l);
Block assign_block = current_block;
if ($3 is DictionaryEntry){
DictionaryEntry de = (DictionaryEntry) $3;
Expression type = (Expression) de.Key;
ArrayList var_declarators = (ArrayList) de.Value;
foreach (VariableDeclaration decl in var_declarators){
LocalInfo vi;
vi = current_block.AddVariable (type, decl.identifier, decl.Location);
if (vi == null)
continue;
Expression expr = decl.expression_or_array_initializer;
LocalVariableReference var;
var = new LocalVariableReference (assign_block, decl.identifier, l);
if (expr != null) {
Assign a = new Assign (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 = (Location) $1;
For f = new For ((Statement) $5, (Expression) $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 type IN expression CLOSE_PARENS
{
Report.Error (230, (Location) $1, "Type and identifier are both required in a foreach statement");
$$ = null;
}
| FOREACH open_parens type IDENTIFIER IN
expression CLOSE_PARENS
{
start_block (lexer.Location);
Block foreach_block = current_block;
LocatedToken lt = (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 = (Location) $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 ((Location) $1);
}
;
continue_statement
: CONTINUE SEMICOLON
{
$$ = new Continue ((Location) $1);
}
;
goto_statement
: GOTO IDENTIFIER SEMICOLON
{
LocatedToken lt = (LocatedToken) $2;
$$ = new Goto (lt.Value, lt.Location);
}
| GOTO CASE constant_expression SEMICOLON
{
$$ = new GotoCase ((Expression) $3, (Location) $1);
}
| GOTO DEFAULT SEMICOLON
{
$$ = new GotoDefault ((Location) $1);
}
;
return_statement
: RETURN opt_expression SEMICOLON
{
$$ = new Return ((Expression) $2, (Location) $1);
}
;
throw_statement
: THROW opt_expression SEMICOLON
{
$$ = new Throw ((Expression) $2, (Location) $1);
}
;
yield_statement
: IDENTIFIER RETURN expression SEMICOLON
{
LocatedToken lt = (LocatedToken) $1;
string s = lt.Value;
if (s != "yield"){
Report.Error (1003, lt.Location, "; expected");
$$ = null;
}
if (RootContext.Version == LanguageVersion.ISO_1){
Report.FeatureIsNotISO1 (lt.Location, "yield statement");
$$ = null;
}
if (anonymous_host == null){
Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
$$ = null;
} else {
anonymous_host.SetYields ();
$$ = new Yield ((Expression) $3, lt.Location);
}
}
| IDENTIFIER RETURN SEMICOLON
{
Report.Error (1627, (Location) $2, "Expression expected after yield return");
$$ = null;
}
| IDENTIFIER BREAK SEMICOLON
{
LocatedToken lt = (LocatedToken) $1;
string s = lt.Value;
if (s != "yield"){
Report.Error (1003, lt.Location, "; expected");
$$ = null;
}
if (RootContext.Version == LanguageVersion.ISO_1){
Report.FeatureIsNotISO1 (lt.Location, "yield statement");
$$ = null;
}
if (anonymous_host == null){
Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
$$ = null;
} else {
anonymous_host.SetYields ();
$$ = new YieldBreak (lt.Location);
}
}
;
opt_expression
: /* empty */
| expression
;
try_statement
: TRY block catch_clauses
{
Catch g = null;
ArrayList c = (ArrayList)$3;
for (int i = 0; i < c.Count; ++i) {
Catch cc = (Catch) c [i];
if (cc.IsGeneral) {
if (i != c.Count - 1)
Report.Error (1017, cc.loc, "Try statement already has an empty catch block");
g = cc;
c.RemoveAt (i);
i--;
}
}
// Now s contains the list of specific catch clauses
// and g contains the general one.
$$ = new Try ((Block) $2, c, g, null, ((Block) $2).loc);
}
| TRY block opt_catch_clauses FINALLY block
{
Catch g = null;
ArrayList s = new ArrayList (4);
ArrayList catch_list = (ArrayList) $3;
if (catch_list != null){
foreach (Catch cc in catch_list) {
if (cc.IsGeneral)
g = cc;
else
s.Add (cc);
}
}
$$ = new Try ((Block) $2, s, g, (Block) $5, ((Block) $2).loc);
}
| TRY block error
{
Report.Error (1524, (Location) $1, "Expected catch or finally");
$$ = null;
}
;
opt_catch_clauses
: /* empty */ { $$ = null; }
| catch_clauses
;
catch_clauses
: catch_clause
{
ArrayList l = new ArrayList (4);
l.Add ($1);
$$ = l;
}
| catch_clauses catch_clause
{
ArrayList l = (ArrayList) $1;
l.Add ($2);
$$ = l;
}
;
opt_identifier
: /* empty */ { $$ = null; }
| IDENTIFIER
;
catch_clause
: CATCH opt_catch_args
{
Expression type = null;
if ($2 != null) {
DictionaryEntry cc = (DictionaryEntry) $2;
type = (Expression) cc.Key;
LocatedToken lt = (LocatedToken) cc.Value;
if (lt != null){
ArrayList one = new ArrayList (4);
one.Add (new VariableDeclaration (lt, null));
start_block (lexer.Location);
current_block = declare_local_variables (type, one, lt.Location);
}
}
} block {
Expression type = null;
string id = null;
Block var_block = null;
if ($2 != null){
DictionaryEntry cc = (DictionaryEntry) $2;
type = (Expression) cc.Key;
LocatedToken lt = (LocatedToken) cc.Value;
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 type opt_identifier CLOSE_PARENS
{
$$ = new DictionaryEntry ($2, $3);
}
;
checked_statement
: CHECKED block
{
$$ = new Checked ((Block) $2);
}
;
unchecked_statement
: UNCHECKED block
{
$$ = new Unchecked ((Block) $2);
}
;
unsafe_statement
: UNSAFE
{
RootContext.CheckUnsafeOption ((Location) $1);
} block {
$$ = new Unsafe ((Block) $3);
}
;
fixed_statement
: FIXED open_parens
type fixed_pointer_declarators
CLOSE_PARENS
{
ArrayList list = (ArrayList) $4;
Expression type = (Expression) $3;
Location l = (Location) $1;
int top = list.Count;
if (type is VarExpr)
Report.Error (821, GetLocation ($3), "A fixed statement cannot use an implicitly typed local variable");
start_block (lexer.Location);
for (int i = 0; i < top; i++){
Pair p = (Pair) list [i];
LocalInfo v;
v = current_block.AddVariable (type, (string) p.First, l);
if (v == null)
continue;
v.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Fixed);
v.Pinned = true;
p.First = v;
list [i] = p;
}
}
embedded_statement
{
Location l = (Location) $1;
Fixed f = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l);
current_block.AddStatement (f);
$$ = end_block (lexer.Location);
}
;
fixed_pointer_declarators
: fixed_pointer_declarator {
ArrayList declarators = new ArrayList (4);
if ($1 != null)
declarators.Add ($1);
$$ = declarators;
}
| fixed_pointer_declarators COMMA fixed_pointer_declarator
{
ArrayList declarators = (ArrayList) $1;
if ($3 != null)
declarators.Add ($3);
$$ = declarators;
}
;
fixed_pointer_declarator
: IDENTIFIER ASSIGN expression
{
LocatedToken lt = (LocatedToken) $1;
// FIXME: keep location
$$ = new Pair (lt.Value, $3);
}
| IDENTIFIER
{
Report.Error (210, ((LocatedToken) $1).Location, "You must provide an initializer in a fixed or using statement declaration");
$$ = null;
}
;
lock_statement
: LOCK OPEN_PARENS expression CLOSE_PARENS
{
//
}
embedded_statement
{
$$ = new Lock ((Expression) $3, (Statement) $6, (Location) $1);
}
;
using_statement
: USING open_parens resource_acquisition CLOSE_PARENS
{
start_block (lexer.Location);
Block assign_block = current_block;
if ($3 is DictionaryEntry){
DictionaryEntry de = (DictionaryEntry) $3;
Location l = (Location) $1;
Expression type = (Expression) de.Key;
ArrayList var_declarators = (ArrayList) de.Value;
ArrayList vars = new ArrayList (4);
foreach (VariableDeclaration decl in var_declarators){
LocalInfo vi = current_block.AddVariable (type, decl.identifier, decl.Location);
if (vi == null)
continue;
vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Using);
Expression expr = decl.expression_or_array_initializer;
if (expr == null) {
Report.Error (210, l, "You must provide an initializer in a fixed or using statement declaration");
}
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.Add (new DictionaryEntry (var, expr));
// Assign a = new Assign (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.
$$ = new DictionaryEntry (type, vars);
} else {
$$ = $3;
}
}
embedded_statement
{
Using u = new Using ($5, (Statement) $6, (Location) $1);
current_block.AddStatement (u);
$$ = end_block (lexer.Location);
}
;
resource_acquisition
: local_variable_declaration
| expression
;
// LINQ
query_expression
: from_clause query_body
{
lexer.QueryParsing = false;
$$ = new Linq.QueryExpression (current_container, current_block, (Expression)$1, (Linq.AQueryClause)$2);
end_block (lexer.Location);
}
;
from_clause
: FROM IDENTIFIER IN expression opt_join_clauses
{
start_block (lexer.Location);
LocatedToken lt = (LocatedToken) $2;
current_block.AddVariable (Linq.ImplicitArgument.Instance, lt.Value, lt.Location);
$$ = $4;
}
| FROM type IDENTIFIER IN expression opt_join_clauses
{
start_block (lexer.Location);
LocatedToken lt = (LocatedToken) $3;
Expression type = (Expression)$2;
current_block.AddVariable (type, lt.Value, lt.Location);
$$ = new Linq.Cast (type, (Expression)$5, lt.Location);
}
;
opt_join_clauses
: /* empty */
| join_clauses
;
join_clauses
: join_clause
| join_clauses join_clause
;
join_clause
: JOIN join_clause_body
| JOIN join_clause_body INTO IDENTIFIER
| JOIN type join_clause_body
| JOIN type join_clause_body INTO IDENTIFIER
;
join_clause_body
: IDENTIFIER IN expression ON expression EQUALS expression
;
query_body
: opt_from_let_where_clauses opt_orderby_clause SELECT expression opt_query_continuation
{
Linq.AQueryClause ret = new Linq.Select ((Expression)$4, GetLocation ($3));
if ($1 != null) {
((Linq.AQueryClause)$1).Next = ret;
ret = (Linq.AQueryClause)$1;
}
$$ = ret;
}
| opt_from_let_where_clauses opt_orderby_clause group_clause opt_query_continuation
{
Linq.AQueryClause ret = (Linq.AQueryClause)$3;
$$ = ret;
}
;
opt_from_let_where_clauses
: /* empty */
| from_let_where_clauses
;
from_let_where_clauses
: from_let_where_clause
| from_let_where_clauses from_let_where_clause
;
from_let_where_clause
: from_clause
| let_clause
| where_clause
;
let_clause
: LET IDENTIFIER ASSIGN expression
;
where_clause
: WHERE boolean_expression
{
$$ = new Linq.Where ((Expression)$2, GetLocation ($1));
}
;
opt_orderby_clause
: /* empty */
| orderby_clause
;
orderby_clause
: ORDERBY orderings
;
orderings
: ordering
| orderings COMMA ordering
;
ordering
: expression
| expression ASCENDING
| expression DESCENDING
;
group_clause
: GROUP expression BY expression
{
$$ = new Linq.GroupBy ((Expression)$2, (Expression)$4, GetLocation ($1));
}
;
opt_query_continuation
: /* empty */
| query_continuation
;
query_continuation
: INTO IDENTIFIER opt_join_clauses query_body
;
%%
//
// A class used to pass around variable declarations and constants
//
public class VariableDeclaration {
public string identifier;
public Expression expression_or_array_initializer;
public Location Location;
public Attributes OptAttributes;
public string DocComment;
public VariableDeclaration (LocatedToken lt, object eoai, Attributes opt_attrs)
{
this.identifier = lt.Value;
if (eoai is ArrayList) {
this.expression_or_array_initializer = new ArrayCreation (CSharpParser.current_array_type, "", (ArrayList)eoai, lt.Location);
} else {
this.expression_or_array_initializer = (Expression)eoai;
}
this.Location = lt.Location;
this.OptAttributes = opt_attrs;
}
public VariableDeclaration (LocatedToken lt, object eoai) : this (lt, eoai, null)
{
}
}
//
// A class used to hold info about an indexer declarator
//
public class IndexerDeclaration {
public Expression type;
public MemberName interface_type;
public Parameters param_list;
public Location location;
public IndexerDeclaration (Expression type, MemberName interface_type,
Parameters param_list, Location loc)
{
this.type = type;
this.interface_type = interface_type;
this.param_list = param_list;
this.location = loc;
}
}
//
// We use this when we do not have an object in advance that is an IAnonymousHost
//
public class SimpleAnonymousHost : IAnonymousHost {
public static readonly SimpleAnonymousHost Simple = new SimpleAnonymousHost ();
bool yields;
ArrayList anonymous_methods;
public static SimpleAnonymousHost GetSimple () {
Simple.yields = false;
Simple.anonymous_methods = null;
return Simple;
}
public void SetYields ()
{
yields = true;
}
public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
{
if (anonymous_methods == null)
anonymous_methods = new ArrayList ();
anonymous_methods.Add (anonymous);
}
public void Propagate (IAnonymousHost real_host)
{
if (yields)
real_host.SetYields ();
if (anonymous_methods != null) {
foreach (AnonymousMethodExpression ame in anonymous_methods)
real_host.AddAnonymousMethod (ame);
}
}
}
//
// A class used to hold info about an operator declarator
//
public class OperatorDeclaration {
public Operator.OpType optype;
public Expression ret_type, arg1type, arg2type;
public string arg1name, arg2name;
public Location location;
public OperatorDeclaration (Operator.OpType op, Expression ret_type,
Expression arg1type, string arg1name,
Expression arg2type, string arg2name, Location location)
{
optype = op;
this.ret_type = ret_type;
this.arg1type = arg1type;
this.arg1name = arg1name;
this.arg2type = arg2type;
this.arg2name = arg2name;
this.location = location;
}
}
void Error_ExpectingTypeName (Expression expr)
{
if (expr is Invocation){
Report.Error (1002, expr.Location, "Expecting `;'");
} else {
Report.Error (201, expr.Location, "Only assignment, call, increment, decrement, and new object expressions can be used as a statement");
}
}
public static void Error_ParameterModifierNotValid (Location loc)
{
Report.Error (631, loc, "The modifiers `ref' and `out' are not valid in this context");
}
static void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod)
{
Report.Error (1107, loc, "Duplicate parameter modifier `{0}'",
Parameter.GetModifierSignature (mod));
}
static void Error_TypeExpected (Location loc)
{
Report.Error (1031, loc, "Type expected");
}
void push_current_class (TypeContainer tc, object partial_token)
{
if (partial_token != null)
current_container = current_container.AddPartial (tc);
else
current_container = current_container.AddTypeContainer (tc);
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.Name.Length == 0){
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 (Expression type, ArrayList variable_declarators, Location loc)
{
Block implicit_block;
ArrayList inits = null;
//
// We use the `Used' property to check whether statements
// have been added to the current block. If so, we need
// to create another block to contain the new declaration
// otherwise, as an optimization, we use the same block to
// add the declaration.
//
// FIXME: A further optimization is to check if the statements
// that were added were added as part of the initialization
// below. In which case, no other statements have been executed
// and we might be able to reduce the number of blocks for
// situations like this:
//
// int j = 1; int k = j + 1;
//
if (current_block.Used)
implicit_block = new Block (current_block, loc, Location.Null);
else
implicit_block = current_block;
foreach (VariableDeclaration decl in variable_declarators){
if (implicit_block.AddVariable (type, decl.identifier, decl.Location) != null) {
if (decl.expression_or_array_initializer != null){
if (inits == null)
inits = new ArrayList (4);
inits.Add (decl);
}
}
}
if (inits == null)
return implicit_block;
foreach (VariableDeclaration decl in inits){
Assign assign;
Expression expr = decl.expression_or_array_initializer;
LocalVariableReference var;
var = new LocalVariableReference (implicit_block, decl.identifier, loc);
assign = new Assign (var, expr, decl.Location);
implicit_block.AddStatement (new StatementExpression (assign));
}
return implicit_block;
}
Block declare_local_constants (Expression type, ArrayList 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, (Expression) decl.expression_or_array_initializer, 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;
}
void CheckUnaryOperator (Operator.OpType op, Location l)
{
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.Addition:
case Operator.OpType.Subtraction:
break;
default :
Report.Error (1019, l, "Overloadable unary operator expected");
break;
}
}
void CheckBinaryOperator (Operator.OpType op, Location l)
{
switch (op) {
case Operator.OpType.Addition:
case Operator.OpType.Subtraction:
case Operator.OpType.Multiply:
case Operator.OpType.Division:
case Operator.OpType.Modulus:
case Operator.OpType.BitwiseAnd:
case Operator.OpType.BitwiseOr:
case Operator.OpType.ExclusiveOr:
case Operator.OpType.LeftShift:
case Operator.OpType.RightShift:
case Operator.OpType.Equality:
case Operator.OpType.Inequality:
case Operator.OpType.GreaterThan:
case Operator.OpType.LessThan:
case Operator.OpType.GreaterThanOrEqual:
case Operator.OpType.LessThanOrEqual:
break;
default :
Report.Error (1020, l, "Overloadable binary operator expected");
break;
}
}
void syntax_error (Location l, string msg)
{
Report.Error (1003, l, "Syntax error, " + msg);
}
void note (string s)
{
// Used to put annotations
}
Tokenizer lexer;
public Tokenizer Lexer {
get {
return lexer;
}
}
static CSharpParser ()
{
oob_stack = new Stack ();
}
public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines)
{
this.name = file.Name;
this.file = file;
current_namespace = new NamespaceEntry (null, file, null);
current_class = current_namespace.SlaveDeclSpace;
current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes
oob_stack.Clear ();
lexer = new Tokenizer (reader, file, defines);
}
public void parse ()
{
int errors = Report.Errors;
try {
if (yacc_verbose_flag > 1)
yyparse (lexer, new yydebug.yyDebugSimple ());
else
yyparse (lexer);
Tokenizer tokenizer = lexer as Tokenizer;
tokenizer.cleanup ();
} catch (Exception e){
//
// Removed for production use, use parser verbose to get the output.
//
// Console.WriteLine (e);
if (Report.Errors == errors)
Report.Error (-25, lexer.Location, "Parsing error");
if (yacc_verbose_flag > 0)
Console.WriteLine (e);
}
if (RootContext.ToplevelTypes.NamespaceEntry != null)
throw new InternalErrorException ("who set it?");
}
static 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, yyNames [yyToken].ToLower ());
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 MemberCore)
return ((MemberCore) obj).Location;
if (obj is MemberName)
return ((MemberName) obj).Location;
if (obj is LocatedToken)
return ((LocatedToken) obj).Location;
if (obj is Location)
return (Location) obj;
return lexer.Location;
}
void
start_block (Location loc)
{
if (current_block == null || parsing_anonymous_method) {
current_block = new ToplevelBlock (current_block, current_local_parameters, current_generic_method, loc);
parsing_anonymous_method = false;
} else {
current_block = new ExplicitBlock (current_block, loc, Location.Null);
}
}
Block
end_block (Location loc)
{
Block retval = current_block.Explicit;
retval.SetEndLocation (loc);
current_block = retval.Parent;
return retval;
}
void
start_anonymous (bool lambda, Parameters parameters, Location loc)
{
oob_stack.Push (current_anonymous_method);
oob_stack.Push (current_local_parameters);
current_local_parameters = parameters;
ToplevelBlock top_current_block = current_block == null ? null : current_block.Toplevel;
current_anonymous_method = lambda
? new LambdaExpression (
current_anonymous_method, current_generic_method, current_container,
parameters, top_current_block, loc)
: new AnonymousMethodExpression (
current_anonymous_method, current_generic_method, current_container,
parameters, top_current_block, loc);
// Force the next block to be created as a ToplevelBlock
parsing_anonymous_method = true;
}
/*
* Completes the anonymous method processing, if lambda_expr is null, this
* means that we have a Statement instead of an Expression embedded
*/
AnonymousMethodExpression
end_anonymous (ToplevelBlock anon_block, Location loc)
{
AnonymousMethodExpression retval;
if (RootContext.Version == LanguageVersion.ISO_1){
Report.FeatureIsNotISO1 (loc, "anonymous methods");
retval = null;
} else {
current_anonymous_method.Block = anon_block;
if ((anonymous_host != null) && (current_anonymous_method.Parent == null))
anonymous_host.AddAnonymousMethod (current_anonymous_method);
retval = current_anonymous_method;
}
current_local_parameters = (Parameters) oob_stack.Pop ();
current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
return retval;
}
/* end end end */
}