%{
//
// cs-parser.jay: The Parser for the C# compiler
//
// Authors: Miguel de Icaza (miguel@gnu.org)
// Ravi Pratap (ravi@ximian.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, top_current_block;
Delegate current_delegate;
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.
///
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 WHILE
%token ARGLIST
%token PARTIAL
/* 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_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 "->"
/* 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 CLOSE_PARENS_CAST
%token CLOSE_PARENS_NO_CAST
%token CLOSE_PARENS_OPEN_PARENS
%token CLOSE_PARENS_MINUS
/* 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.FeatureIsNotStandardized (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");
}
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
;
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)
CodeGen.Assembly.AddAttributes (((Attributes)$1).Attrs);
$$ = $1;
}
opt_attributes
: /* empty */
{
global_attrs_enabled = false;
$$ = null;
}
| attribute_sections
{
global_attrs_enabled = false;
$$ = $1;
}
;
attribute_sections
: attribute_section
{
ArrayList sect = (ArrayList) $1;
if (global_attrs_enabled) {
if (current_attr_target == "module") {
CodeGen.Module.AddAttributes (sect);
$$ = null;
} else if (current_attr_target != null && current_attr_target.Length > 0) {
CodeGen.Assembly.AddAttributes (sect);
$$ = null;
} else {
$$ = new Attributes (sect);
}
if ($$ == null) {
if (RootContext.Documentation != null) {
Lexer.check_incorrect_doc_comment ();
Lexer.doc_state =
XmlCommentState.Allowed;
}
}
} else {
$$ = new Attributes (sect);
}
current_attr_target = null;
}
| attribute_sections attribute_section
{
Attributes attrs = $1 as Attributes;
ArrayList sect = (ArrayList) $2;
if (global_attrs_enabled) {
if (current_attr_target == "module") {
CodeGen.Module.AddAttributes (sect);
$$ = null;
} else if (current_attr_target == "assembly") {
CodeGen.Assembly.AddAttributes (sect);
$$ = null;
} 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;
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);
$$ = lt.Value; // Location won't be required anymore.
}
| EVENT { $$ = "event"; }
| RETURN { $$ = "return"; }
;
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;
object[] arguments = (object[]) $2;
MemberName left = mname.Left;
string identifier = mname.Name;
Expression left_expr = left == null ? null : left.GetTypeExpression ();
if (current_attr_target == "assembly" || current_attr_target == "module")
// FIXME: supply "nameEscaped" parameter here.
$$ = new GlobalAttribute (current_namespace, current_attr_target,
left_expr, identifier, arguments, mname.Location, lexer.IsEscapedIdentifier (mname.Location));
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 member_name
{
MemberName name = MakeName ((MemberName) $5);
push_current_class (new Struct (
current_namespace, current_class, name, (int) $2,
(Attributes) $1), false, $3);
}
opt_class_base
{
if ($7 != null)
current_container.AddBasesForPart (current_class, (ArrayList) $7);
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_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;
}
}
;
method_header
: opt_attributes
opt_modifiers
type namespace_or_type_name
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
{
MemberName name = (MemberName) $4;
Method method = new Method (current_class, null, (Expression) $3, (int) $2,
false, name, (Parameters) $6, (Attributes) $1);
anonymous_host = method;
current_local_parameters = (Parameters) $6;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = method;
}
| opt_attributes
opt_modifiers
VOID namespace_or_type_name
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
{
MemberName name = (MemberName) $4;
Method method = new Method (current_class, null, TypeManager.system_void_expr,
(int) $2, false, name, (Parameters) $6,
(Attributes) $1);
anonymous_host = method;
current_local_parameters = (Parameters) $6;
if (RootContext.Documentation != null)
method.DocComment = Lexer.consume_doc_comment ();
$$ = method;
}
| opt_attributes
opt_modifiers
type
modifiers namespace_or_type_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) $7, (Attributes) $1);
current_local_parameters = (Parameters) $7;
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;
pars.Add ($3);
$$ = $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_modifier
;
parameter_modifier
: REF { $$ = Parameter.Modifier.REF; }
| OUT { $$ = Parameter.Modifier.OUT; }
;
parameter_array
: opt_attributes PARAMS type IDENTIFIER
{
LocatedToken lt = (LocatedToken) $4;
$$ = new ParamsParameter ((Expression) $3, lt.Value, (Attributes) $1, lt.Location);
note ("type must be a single-dimension array type");
}
| opt_attributes PARAMS parameter_modifier type IDENTIFIER
{
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;
Pair pair = (Pair) $8;
Accessor get_block = (Accessor) pair.First;
Accessor set_block = (Accessor) pair.Second;
MemberName name = (MemberName) $4;
prop = new Property (current_class, (Expression) $3, (int) $2,
false, name, (Attributes) $1, get_block, set_block);
current_container.AddProperty (prop);
implicit_value_parameter_type = null;
if (RootContext.Documentation != null)
prop.DocComment = ConsumeStoredComment ();
}
;
accessor_declarations
: get_accessor_declaration
{
$$ = new Pair ($1, null);
}
| get_accessor_declaration accessor_declarations
{
Pair pair = (Pair) $2;
pair.First = $1;
$$ = pair;
}
| set_accessor_declaration
{
$$ = new Pair (null, $1);
}
| set_accessor_declaration accessor_declarations
{
Pair pair = (Pair) $2;
pair.Second = $1;
$$ = pair;
}
| 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 member_name
{
MemberName name = MakeName ((MemberName) $5);
push_current_class (new Interface (
current_namespace, current_class, name, (int) $2,
(Attributes) $1), true, $3);
}
opt_class_base
{
current_container.AddBasesForPart (current_class, (ArrayList) $7);
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
: opt_attributes opt_new type namespace_or_type_name
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
SEMICOLON
{
$$ = new Method (current_class, null, (Expression) $3, (int) $2, true,
(MemberName) $4, (Parameters) $6, (Attributes) $1);
if (RootContext.Documentation != null)
((Method) $$).DocComment = Lexer.consume_doc_comment ();
}
| opt_attributes opt_new type namespace_or_type_name
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
OPEN_BRACE opt_statement_list CLOSE_BRACE
{
$$ = new Method (current_class, null, (Expression) $3, (int) $2, true,
(MemberName) $4, (Parameters) $6, (Attributes) $1);
Report.Error (531, lexer.Location, "`{0}': interface members cannot have a definition",
((Method)$$).GetSignatureForError ());
}
;
interface_property_declaration
: opt_attributes
opt_new
type IDENTIFIER
OPEN_BRACE
{ lexer.PropertyParsing = true; }
accessor_declarations
{
has_get = has_set = false;
lexer.PropertyParsing = false;
}
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);
Report.Error (548, p.Location, "`{0}': property or indexer must have at least one accessor", p.GetSignatureForError ());
break;
}
Pair pair = (Pair) $7;
p = new Property (current_class, (Expression) $3, (int) $2, true,
name, (Attributes) $1,
(Accessor)pair.First, (Accessor)pair.Second);
if (pair.First != null && ((Accessor)(pair.First)).Block != null) {
Report.Error (531, p.Location, "`{0}.get': interface members cannot have a definition", p.GetSignatureForError ());
$$ = null;
break;
}
if (pair.Second != null && ((Accessor)(pair.Second)).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
{
lexer.EventParsing = true;
}
event_accessor_declarations
{
lexer.EventParsing = false;
}
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; }
accessor_declarations
{
has_get = has_set = false;
lexer.PropertyParsing = false;
}
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);
Report.Error (548, i.Location, "`{0}': property or indexer must have at least one accessor", i.GetSignatureForError ());
break;
}
Pair pair = (Pair) $10;
i = new Indexer (current_class, (Expression) $3,
new MemberName (TypeContainer.DefaultIndexerName, (Location) $4),
(int) $2, true, (Parameters) $6, (Attributes) $1,
(Accessor)pair.First, (Accessor)pair.Second);
if (pair.First != null && ((Accessor)(pair.First)).Block != null) {
Report.Error (531, i.Location, "`{0}.get': interface members cannot have a definition", i.GetSignatureForError ());
$$ = null;
break;
}
if (pair.Second != null && ((Accessor)(pair.Second)).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_parameter_modifier type IDENTIFIER CLOSE_PARENS
{
// TODO: wrong location
if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE)
Error_ParameterModifierNotValid ((Location) $2);
LocatedToken lt = (LocatedToken) $7;
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) $6;
pars [0] = new Parameter (type, 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 (op, (Expression) $1, type, lt.Value,
null, null, (Location) $2);
}
| type OPERATOR overloadable_operator
OPEN_PARENS
opt_parameter_modifier type IDENTIFIER COMMA
opt_parameter_modifier type IDENTIFIER
CLOSE_PARENS
{
// TODO: wrong location
if ((Parameter.Modifier)$5 != Parameter.Modifier.NONE || (Parameter.Modifier)$9 != Parameter.Modifier.NONE)
Error_ParameterModifierNotValid ((Location) $2);
LocatedToken ltParam1 = (LocatedToken) $7;
LocatedToken ltParam2 = (LocatedToken) $11;
CheckBinaryOperator ((Operator.OpType) $3, (Location) $2);
Parameter [] pars = new Parameter [2];
Expression typeL = (Expression) $6;
Expression typeR = (Expression) $10;
pars [0] = new Parameter (typeL, ltParam1.Value, Parameter.Modifier.NONE, null, ltParam1.Location);
pars [1] = new Parameter (typeR, ltParam2.Value, Parameter.Modifier.NONE, null, ltParam2.Location);
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_parameter_modifier type IDENTIFIER COMMA
opt_parameter_modifier type IDENTIFIER COMMA
opt_parameter_modifier type IDENTIFIER
CLOSE_PARENS
{
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
: IDENTIFIER
{
if (RootContext.Documentation != null) {
tmpComment = Lexer.consume_doc_comment ();
Lexer.doc_state = XmlCommentState.Allowed;
}
}
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
{
current_local_parameters = (Parameters) $4;
}
opt_constructor_initializer
{
LocatedToken lt = (LocatedToken) $1;
$$ = new Constructor (current_class, lt.Value, 0, (Parameters) $4,
(ConstructorInitializer) $7, lt.Location);
anonymous_host = (IAnonymousHost) $$;
}
;
constructor_body
: block
| SEMICOLON { $$ = null; }
;
opt_constructor_initializer
: /* empty */ { $$ = null; }
| constructor_initializer
;
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.Basename){
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 {
Pair pair = (Pair) $8;
if (pair.First == null || pair.Second == 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, (Accessor) pair.First, (Accessor) pair.Second);
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 Pair ($1, $2);
}
| remove_accessor_declaration add_accessor_declaration
{
$$ = new Pair ($2, $1);
}
| 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;
}
block
{
$$ = new Accessor ((ToplevelBlock) $4, 0, (Attributes) $1, (Location) $2);
lexer.EventParsing = true;
}
| 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;
Location loc = decl.location;
Pair pair = (Pair) $6;
Accessor get_block = (Accessor) pair.First;
Accessor set_block = (Accessor) pair.Second;
MemberName name;
if (decl.interface_type != null)
name = new MemberName (decl.interface_type, TypeContainer.DefaultIndexerName, loc);
else
name = new MemberName (TypeContainer.DefaultIndexerName, loc);
indexer = new Indexer (current_class, decl.type, name,
(int) $2, false, decl.param_list, (Attributes) $1,
get_block, set_block);
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, (Expression) ev.expression_or_array_initializer,
new MemberName (ev.identifier, ev.Location), ev.OptAttributes);
// if (RootContext.Documentation != null)
em.DocComment = ev.DocComment;
e.AddEnumMember (em);
}
current_container.AddEnum (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 type member_name
OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
SEMICOLON
{
MemberName name = MakeName ((MemberName) $5);
Parameters p = (Parameters) $7;
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) $4,
(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);
$$ = del;
}
;
namespace_or_type_name
: member_name
| 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 {
LocatedToken lt = (LocatedToken) $3;
$$ = new MemberName ((MemberName) $1, lt.Value);
}
;
member_name
: IDENTIFIER {
LocatedToken lt = (LocatedToken) $1;
$$ = new MemberName (lt.Value, lt.Location);
}
;
/*
* 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
{
MemberName name = (MemberName) $1;
$$ = name.GetTypeExpression ();
}
| builtin_types
| 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
| 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
{
$$ = current_array_type = new ComposedCast ((Expression) $1, (string) $2);
}
;
//
// Expressions, section 7.5
//
primary_expression
: literal
{
// 7.5.1: Literals
}
| member_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
| 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
{
LocatedToken lt = (LocatedToken) $3;
$$ = new MemberAccess ((Expression) $1, lt.Value);
}
| predefined_type DOT IDENTIFIER
{
LocatedToken lt = (LocatedToken) $3;
// TODO: Location is wrong as some predefined types doesn't hold a location
$$ = new MemberAccess ((Expression) $1, lt.Value, 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_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
{
$$ = 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 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
{
LocatedToken lt = (LocatedToken) $3;
$$ = new BaseAccess (lt.Value, 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
;
object_or_delegate_creation_expression
: NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
{
$$ = new New ((Expression) $2, (ArrayList) $4, (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 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;
}
;
opt_rank_specifier
: /* empty */
{
$$ = "";
}
| rank_specifiers
{
$$ = $1;
}
;
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;
}
OPEN_PARENS type CLOSE_PARENS
{
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;
}
;
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
{
if (oob_stack == null)
oob_stack = new Stack (6);
oob_stack.Push (current_anonymous_method);
oob_stack.Push (current_local_parameters);
current_local_parameters = (Parameters)$2;
// Force the next block to be created as a ToplevelBlock
oob_stack.Push (current_block);
oob_stack.Push (top_current_block);
Location loc = (Location) $1;
current_anonymous_method = new AnonymousMethodExpression (
current_anonymous_method, null, current_container,
(Parameters) $2, (ToplevelBlock) top_current_block, loc);
parsing_anonymous_method = true;
}
block
{
Location loc = (Location) $1;
top_current_block = (Block) oob_stack.Pop ();
current_block = (Block) oob_stack.Pop ();
if (RootContext.Version == LanguageVersion.ISO_1){
Report.FeatureIsNotStandardized (loc, "anonymous methods");
$$ = null;
} else {
ToplevelBlock anon_block = (ToplevelBlock) $4;
anon_block.Parent = current_block;
current_anonymous_method.Block = anon_block;
if ((anonymous_host != null) && (current_anonymous_method.Parent == null))
anonymous_host.AddAnonymousMethod (current_anonymous_method);
$$ = current_anonymous_method;
}
current_local_parameters = (Parameters) oob_stack.Pop ();
current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
}
;
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;
}
;
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_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);
}
;
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 type
{
$$ = new Is ((Expression) $1, (Expression) $3, (Location) $2);
}
| relational_expression AS type
{
$$ = new As ((Expression) $1, (Expression) $3, (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);
}
;
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);
}
;
expression
: conditional_expression
| assignment_expression
;
constant_expression
: expression
;
boolean_expression
: expression
;
//
// 10 classes
//
class_declaration
: opt_attributes
opt_modifiers
opt_partial
CLASS member_name
{
MemberName name = MakeName ((MemberName) $5);
int mod_flags = (int) $2;
push_current_class (new Class (
current_namespace, current_class, name,
mod_flags, (Attributes) $1), false, $3);
}
opt_class_base
{
if ($7 != 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) $7);
}
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; }
;
//
// 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
{
if (parsing_anonymous_method) {
top_current_block = new ToplevelBlock (
current_block, current_local_parameters, null, (Location) $1);
if (current_block != null)
current_block.AddAnonymousChild ((ToplevelBlock) top_current_block);
current_block = top_current_block;
parsing_anonymous_method = false;
} else if (current_block == null){
current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, (Location) $1);
top_current_block = current_block;
} else {
current_block = new Block (current_block, (Location) $1, Location.Null);
}
}
opt_statement_list CLOSE_BRACE
{
while (current_block.Implicit)
current_block = current_block.Parent;
$$ = current_block;
current_block.SetEndLocation ((Location) $4);
current_block = current_block.Parent;
if (current_block == null)
top_current_block = null;
}
;
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
{
// 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 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
{
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 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)
$$ = new DictionaryEntry ($1, $2);
else
$$ = null;
}
| local_variable_pointer_type opt_rank_specifier 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
{
Block topmost = current_block;
while (topmost.Implicit)
topmost = topmost.Parent;
$$ = new SwitchSection ((ArrayList) $1, topmost);
}
;
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
{
Block assign_block = new Block (current_block);
current_block = assign_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;
Location l = lexer.Location;
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);
while (current_block.Implicit)
current_block = current_block.Parent;
$$ = current_block;
current_block = current_block.Parent;
}
;
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, Block.Flags.Implicit, 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
{
Block foreach_block = new Block (current_block);
current_block = foreach_block;
LocatedToken lt = (LocatedToken) $4;
Location l = lt.Location;
LocalInfo vi;
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);
}
while (current_block.Implicit)
current_block = current_block.Parent;
$$ = current_block;
current_block = current_block.Parent;
}
;
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.FeatureIsNotStandardized (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.FeatureIsNotStandardized (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));
current_block = new Block (current_block);
Block b = declare_local_variables (type, one, lt.Location);
current_block = b;
}
}
} 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;
while (current_block.Implicit)
current_block = current_block.Parent;
var_block = current_block;
current_block = current_block.Parent;
}
}
$$ = 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;
Block assign_block = new Block (current_block);
current_block = assign_block;
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);
while (current_block.Implicit)
current_block = current_block.Parent;
$$ = current_block;
current_block = current_block.Parent;
}
;
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
{
Block assign_block = new Block (current_block);
current_block = assign_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);
while (current_block.Implicit)
current_block = current_block.Parent;
$$ = current_block;
current_block = current_block.Parent;
}
;
resource_acquisition
: local_variable_declaration
| expression
;
%%
//
// 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) {
if (CSharpParser.current_array_type == null)
Report.Error (622, lt.Location,
"Can only use array initializer expressions to assign to array types. Try using a new expression instead.");
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");
}
void push_current_class (TypeContainer tc, bool is_interface, object partial_token)
{
if (partial_token != null)
current_container = current_container.AddPartial (tc, is_interface);
else
current_container = current_container.AddTypeContainer (tc, is_interface);
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, Block.Flags.Implicit, 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, Block.Flags.Implicit);
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;
}
void CheckAttributeTarget (string a, Location l)
{
switch (a) {
case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" :
return;
default :
Report.Error (658, l, "`" + a + "' is an invalid attribute target");
break;
}
}
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;
}
}
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
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;
}
/* end end end */
}