// 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
Namespace current_namespace;
TypeContainer current_container;
+ IIteratorContainer iterator_container;
+
// <summary>
// Current block is used to add statements as we find
// them.
// Switch stack.
//
Stack switch_stack;
+
+ //
+ // The current file.
+ //
+ SourceFile file;
%}
%token EOF
%token VOLATILE
%token WHILE
+/* v2 tokens */
+%token YIELD
+
/* C# keywords which are not really keywords */
%token GET "get"
%token SET "set"
: outer_declarations opt_EOF
| outer_declarations attribute_sections opt_EOF
| attribute_sections opt_EOF
+ | opt_EOF /* allow empty files */
;
opt_EOF
if (attrs != null) {
foreach (AttributeSection asec in attrs.AttributeSections)
if (asec.Target == "assembly")
- RootContext.AddGlobalAttribute (
- current_container, asec, lexer.Location);
+ RootContext.AddGlobalAttributeSection (current_container, asec);
+ else
+ Report.Error(1518, Lexer.Location,
+ "Attributes cannot be applied to namespaces."
+ + " Expected class, delegate, enum, interface, or struct");
}
- current_namespace = RootContext.Tree.RecordNamespace (current_namespace, name, (string) $3);
+ current_namespace = RootContext.Tree.RecordNamespace (current_namespace, file, (string) $3);
}
namespace_body opt_semicolon
{
}
current_namespace.DeclarationFound = true;
}
- | namespace_declaration
+ | namespace_declaration {
+ current_namespace.DeclarationFound = true;
+ }
;
type_declaration
{
AttributeSection sect = (AttributeSection) $1;
- if (sect.Target == "assembly")
- RootContext.AddGlobalAttribute (current_container, sect, lexer.Location);
-
- $$ = new Attributes ((AttributeSection) $1, lexer.Location);
+ if (sect.Target == "assembly")
+ RootContext.AddGlobalAttributeSection (current_container, sect);
+
+
+ $$ = new Attributes ((AttributeSection) $1);
}
| attribute_sections attribute_section
{
AttributeSection sect = (AttributeSection) $2;
if (sect.Target == "assembly")
- RootContext.AddGlobalAttribute (current_container, sect, lexer.Location);
+ RootContext.AddGlobalAttributeSection (current_container, sect);
if ($1 != null) {
attrs = (Attributes) $1;
- attrs.AddAttribute (sect);
+ attrs.AddAttributeSection (sect);
}
$$ = attrs;
;
attribute_section
- : OPEN_BRACKET attribute_target_specifier attribute_list CLOSE_BRACKET
+ : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
{
string target = null;
$$ = new AttributeSection (target, (ArrayList) $3);
}
- | OPEN_BRACKET attribute_list CLOSE_BRACKET
+ | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
{
$$ = new AttributeSection (null, (ArrayList) $2);
}
;
method_declaration
- : method_header
+ : method_header {
+ iterator_container = (IIteratorContainer) $1;
+ }
method_body
{
Method method = (Method) $1;
- Block b = (Block) $2;
+ Block b = (Block) $3;
const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT);
if (b == null){
}
}
- method.Block = (Block) $2;
+ method.Block = (Block) $3;
CheckDef (current_container.AddMethod (method), method.Name, method.Location);
current_local_parameters = null;
+ iterator_container = null;
}
;
{
Constructor c = (Constructor) $3;
c.Block = (Block) $4;
- c.ModFlags = (int) $2;
c.OptAttributes = (Attributes) $1;
-
- if ((c.ModFlags & Modifiers.STATIC) != 0){
- if ((c.ModFlags & Modifiers.Accessibility) != 0) {
- Report.Error (
- 515, c.Location,
- "Access modifiers are not allowed on static constructors");
- }
-
- if (c.Initializer != null){
- Report.Error (
- 514, c.Location,
- "Static constructors can not have an explicit this or base " +
- "constructor invocations");
+ c.ModFlags = (int) $2;
+
+ if (c.Name == current_container.Basename){
+ if ((c.ModFlags & Modifiers.STATIC) != 0){
+ if ((c.ModFlags & Modifiers.Accessibility) != 0){
+ Report.Error (
+ 515, c.Location, String.Format (
+ "`{0}.{1}': static constructor can not have access modifiers",
+ c.Name, current_container.Name));
+ }
+
+ c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
+
+ if (c.Initializer != null){
+ Report.Error (
+ 514, c.Location,
+ "Static constructors can not have an explicit this or base " +
+ "constructor invocations");
+ }
+
+ if (!c.Parameters.Empty){
+ Report.Error (
+ 132, c.Location, "Static constructors should not have parameters");
+ }
+ } 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);
+ }
- if (!c.Parameters.Empty){
- Report.Error (
- 132, c.Location, "Static constructors should not have parameters");
- }
- }
-
CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
current_local_parameters = null;
constructor_initializer
: COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
{
- $$ = new ConstructorBaseInitializer ((ArrayList) $4, lexer.Location);
+ $$ = new ConstructorBaseInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
}
| COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
{
- $$ = new ConstructorThisInitializer ((ArrayList) $4, lexer.Location);
+ $$ = new ConstructorThisInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
}
;
$$ = new Accessor ((Block) $4, (Attributes) $1);
lexer.EventParsing = true;
}
+ | opt_attributes ADD error {
+ Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
+ $$ = null;
+ }
;
remove_accessor_declaration
$$ = new Accessor ((Block) $4, (Attributes) $1);
lexer.EventParsing = true;
}
+ | opt_attributes REMOVE error {
+ Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
+ $$ = null;
+ }
;
indexer_declaration
{
$$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
}
+
+ //
+ // We need this because the parser will happily go and reduce IDENTIFIER STAR
+ // through this different path
+ //
+ | multiplicative_expression STAR
+ {
+ $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+ }
;
type_list
{
if ($1 == null) {
Location l = lexer.Location;
- Report.Error (1, l, "THIS IS CRAZY");
+ Report.Error (1, l, "Parse error");
}
$$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
}
// Blah i;
Expression expr = (Expression) $1;
- if (!(expr is SimpleName || expr is MemberAccess)) {
- Location l = lexer.Location;
- Report.Error (-1, l, "Invalid Type definition");
- $$ = "System.Object";
+ if (expr is ComposedCast){
+ $$ = new ComposedCast (expr, (string) $2, lexer.Location);
+ } else if (!(expr is SimpleName || expr is MemberAccess)){
+ Error_ExpectingTypeName (lexer.Location, expr);
+ $$ = TypeManager.system_object_expr;
+ } else {
+ //
+ // So we extract the string corresponding to the SimpleName
+ // or MemberAccess
+ //
+ $$ = new ComposedCast (expr, (string) $2, lexer.Location);
}
-
- //
- // So we extract the string corresponding to the SimpleName
- // or MemberAccess
- //
- $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
}
;
this_access
: THIS
{
- $$ = new This (lexer.Location);
+ $$ = new This (current_block, lexer.Location);
}
;
;
rank_specifiers
- : rank_specifier
- {
- $$ = $1;
- }
- | rank_specifiers rank_specifier
+ : rank_specifier opt_rank_specifier
{
$$ = (string) $2 + (string) $1;
- }
+ }
;
rank_specifier
{
$$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
}
- | OPEN_PARENS expression CLOSE_PARENS unary_expression
+ | cast_expression
+ ;
+
+cast_expression
+ : OPEN_PARENS expression CLOSE_PARENS unary_expression
{
$$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
}
block
: OPEN_BRACE
{
- current_block = new Block (current_block, lexer.Location, Location.Null);
+ current_block = new Block (current_block, current_local_parameters,
+ lexer.Location, Location.Null);
}
opt_statement_list CLOSE_BRACE
{
statement
: declaration_statement
{
- if ((Block) $1 != current_block){
+ if ($1 != null && (Block) $1 != current_block){
current_block.AddStatement ((Statement) $1);
current_block = (Block) $1;
}
declaration_statement
: local_variable_declaration SEMICOLON
{
- DictionaryEntry de = (DictionaryEntry) $1;
+ if ($1 != null){
+ DictionaryEntry de = (DictionaryEntry) $1;
- $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
+ $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
+ }
}
| local_constant_declaration SEMICOLON
{
- DictionaryEntry de = (DictionaryEntry) $1;
+ if ($1 != null){
+ DictionaryEntry de = (DictionaryEntry) $1;
- $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
+ $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
+ }
}
;
// Blah i;
Expression expr = (Expression) $1;
- if (!(expr is SimpleName || expr is MemberAccess)) {
- Location l = lexer.Location;
- Report.Error (-1, l, "Invalid Type definition");
- $$ = TypeManager.system_object_expr;
+ if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
+ Error_ExpectingTypeName (lexer.Location, 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, lexer.Location);
}
-
- //
- // So we extract the string corresponding to the SimpleName
- // or MemberAccess
- //
- if ((string) $2 == "")
- $$ = $1;
- else
- $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
}
| builtin_types opt_rank_specifier
{
: primary_expression STAR
{
Expression expr = (Expression) $1;
- if (!(expr is SimpleName || expr is MemberAccess)) {
- Location l = lexer.Location;
- Report.Error (-1, l, "Invalid Type definition");
- $$ = "System.Object";
- }
-
- $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+ Location l = lexer.Location;
+
+ if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
+ Error_ExpectingTypeName (l, expr);
+
+ $$ = null;
+ } else
+ $$ = new ComposedCast ((Expression) $1, "*", l);
}
| builtin_types STAR
{
local_variable_declaration
: local_variable_type variable_declarators
{
- $$ = new DictionaryEntry ($1, $2);
+ if ($1 != null)
+ $$ = new DictionaryEntry ($1, $2);
+ else
+ $$ = null;
}
| local_variable_pointer_type opt_rank_specifier variable_declarators
{
- Expression t;
+ if ($1 != null){
+ Expression t;
- if ((string) $2 == "")
- t = (Expression) $1;
- else
- t = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
- $$ = new DictionaryEntry (t, $3);
+ if ((string) $2 == "")
+ t = (Expression) $1;
+ else
+ t = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+ $$ = new DictionaryEntry (t, $3);
+ } else
+ $$ = null;
}
;
local_constant_declaration
: CONST local_variable_type constant_declarator
{
- $$ = new DictionaryEntry ($2, $3);
+ if ($2 != null)
+ $$ = new DictionaryEntry ($2, $3);
+ else
+ $$ = null;
}
;
switch_section
: switch_labels
{
- current_block = new Block (current_block);
+ current_block = new Block (current_block, lexer.Location, lexer.Location);
}
statement_list
{
- while (current_block.Implicit)
- current_block = current_block.Parent;
- $$ = new SwitchSection ((ArrayList) $1, current_block);
+ Block topmost = current_block;
+
+ while (topmost.Implicit)
+ topmost = topmost.Parent;
+ $$ = new SwitchSection ((ArrayList) $1, topmost);
}
;
do_statement
: DO embedded_statement
- WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
+ WHILE OPEN_PARENS {
+ oob_stack.Push (lexer.Location);
+ }
+ boolean_expression CLOSE_PARENS SEMICOLON
{
- $$ = new Do ((Statement) $2, (Expression) $5, lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ $$ = new Do ((Statement) $2, (Expression) $6, l);
}
;
Expression expr;
if (decl.expression_or_array_initializer is Expression){
expr = (Expression) decl.expression_or_array_initializer;
+ } else if (decl.expression_or_array_initializer == null) {
+ expr = null;
} else {
ArrayList init = (ArrayList) decl.expression_or_array_initializer;
expr = new ArrayCreation (type, "", init, decl.Location);
LocalVariableReference var;
var = new LocalVariableReference (assign_block, decl.identifier, l);
+
+ if (expr != null) {
+ Assign a = new Assign (var, expr, decl.Location);
- Assign a = new Assign (var, expr, decl.Location);
-
- assign_block.AddStatement (new StatementExpression (a, lexer.Location));
+ assign_block.AddStatement (new StatementExpression (a, lexer.Location));
+ }
}
$3 = null;
: statement_expression
{
// CHANGE: was `null'
- Block b = new Block (current_block, true);
+ Block b = new Block (current_block, Block.Flags.Implicit);
b.AddStatement ((Statement) $1);
$$ = b;
{
oob_stack.Push (current_block);
- Block foreach_block = new Block (current_block, true);
+ Block foreach_block = new Block (current_block, Block.Flags.Implicit);
LocalVariableReference v = null;
Location l = lexer.Location;
VariableInfo vi;
| goto_statement
| return_statement
| throw_statement
+ | yield_statement
;
break_statement
}
;
+yield_statement
+ : YIELD expression SEMICOLON
+ {
+ if (iterator_container == null){
+ Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
+ $$ = null;
+ } else {
+ iterator_container.SetYields ();
+ $$ = new Yield ((Expression) $2, lexer.Location);
+ }
+ }
+ | YIELD BREAK SEMICOLON
+ {
+ if (iterator_container == null){
+ Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
+ $$ = null;
+ } else {
+ iterator_container.SetYields ();
+ $$ = new YieldBreak (lexer.Location);
+ }
+ }
+ ;
+
opt_expression
: /* empty */
| expression
fixed_statement
: FIXED OPEN_PARENS
- pointer_type fixed_pointer_declarators
+ type fixed_pointer_declarators
CLOSE_PARENS
{
- Block assign_block = new Block (current_block, true);
+ Block assign_block = new Block (current_block, Block.Flags.Implicit);
ArrayList list = (ArrayList) $4;
Expression type = (Expression) $3;
Location l = lexer.Location;
}
+void Error_ExpectingTypeName (Location l, Expression expr)
+{
+ if (expr is Invocation){
+ Report.Error (1002, l, "; expected");
+ } else {
+ Report.Error (-1, l, "Invalid Type definition");
+ }
+}
+
// <summary>
// Given the @class_name name, it creates a fully qualified name
// based on the containing declaration space
CheckDef (AdditionResult.NameExists, name, l);
}
-//
-// This routine should be removed soon. I am in the process of making
-// changes to never keep anything but SimpleNames during parsing, as
-// that breaks some kinds of code (documented in the ChangeLog).
-//
-Expression
-SimpleLookup (string name, Location loc)
-{
- //
- // we need to check against current_block not being null
- // as `expression' is allowed in argument_lists, which
- // do not exist inside a block.
- //
-
- if (current_local_parameters != null){
- int idx;
- Parameter par = current_local_parameters.GetParameterByName (name, out idx);
- if (par != null)
- return new ParameterReference (current_local_parameters, idx, name, lexer.Location);
- }
-
- return null;
-}
-
Expression DecomposeQI (string name, Location loc)
{
Expression o;
if (name.IndexOf ('.') == -1){
- o = SimpleLookup (name, loc);
- if (o == null)
- return new SimpleName (name, loc);
- return o;
+ return new SimpleName (name, loc);
} else {
int pos = name.LastIndexOf (".");
string left = name.Substring (0, pos);
string right = name.Substring (pos + 1);
o = DecomposeQI (left, loc);
+
return new MemberAccess (o, right, loc);
}
}
// This is necessary because local_variable_type admits primary_expression
// as the type of the variable. So we do some extra checking
// </summary>
+#if false
string GetQualifiedIdentifier (Expression expr)
{
if (expr is SimpleName)
throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
}
+#endif
Block declare_local_variables (Expression type, ArrayList variable_declarators, Location loc)
{
//
// int j = 1; int k = j + 1;
//
- if (current_block.Used)
- implicit_block = new Block (current_block, true, loc, Location.Null);
- else
+ if (current_block.Used) {
+ implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
+ implicit_block.AddChildVariableNames (current_block);
+ } else
implicit_block = current_block;
foreach (VariableDeclaration decl in variable_declarators){
Block implicit_block;
if (current_block.Used)
- implicit_block = new Block (current_block, true);
+ implicit_block = new Block (current_block, Block.Flags.Implicit);
else
implicit_block = current_block;
}
}
-public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
+public CSharpParser (StreamReader reader, SourceFile file, ArrayList defines)
{
- current_namespace = new Namespace (null, "");
- this.name = name;
- this.input = input;
+ current_namespace = new Namespace (null, file, "");
+ this.name = file.Name;
+ this.file = file;
current_container = RootContext.Tree.Types;
current_container.Namespace = current_namespace;
oob_stack = new Stack ();
switch_stack = new Stack ();
- lexer = new Tokenizer (input, name, defines);
+ lexer = new Tokenizer (reader, file, defines);
}
public override void parse ()
yyparse (lexer, new yydebug.yyDebugSimple ());
else
yyparse (lexer);
+ Tokenizer tokenizer = lexer as Tokenizer;
+ tokenizer.cleanup ();
} catch (Exception e){
// Please do not remove this, it is used during debugging
// of the grammar
//
- Console.WriteLine (lexer.location + " : Parsing error ");
+ Report.Error (-25, lexer.Location, ": Parsing error ");
Console.WriteLine (e);
}
}