2003-04-28 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
index 9bbe9550dc44b9139bf56be7cc394d97d0f2648c..005def9fa45a8608bce2ffa6a55904997d37358b 100755 (executable)
@@ -14,6 +14,9 @@
 //       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;
@@ -31,6 +34,8 @@ namespace Mono.CSharp
                Namespace     current_namespace;
                TypeContainer current_container;
        
+               IIteratorContainer iterator_container;
+
                // <summary>
                //   Current block is used to add statements as we find
                //   them.  
@@ -74,6 +79,11 @@ namespace Mono.CSharp
                // Switch stack.
                //
                Stack switch_stack;
+
+               //
+               // The current file.
+               //
+               SourceFile file;
 %}
 
 %token EOF
@@ -165,6 +175,9 @@ namespace Mono.CSharp
 %token VOLATILE
 %token WHILE   
 
+/* v2 tokens */
+%token YIELD
+
 /* C# keywords which are not really keywords */
 %token GET           "get"
 %token SET           "set"
@@ -312,9 +325,13 @@ namespace_declaration
                        foreach (AttributeSection asec in attrs.AttributeSections)
                                if (asec.Target == "assembly")
                                        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
          { 
@@ -392,7 +409,9 @@ namespace_member_declaration
                }
                current_namespace.DeclarationFound = true;
          }
-       | namespace_declaration
+       | namespace_declaration {
+               current_namespace.DeclarationFound = true;
+         }
        ;
 
 type_declaration
@@ -797,11 +816,13 @@ variable_initializer
        ;
 
 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){
@@ -818,10 +839,11 @@ method_declaration
                        }
                }
 
-               method.Block = (Block) $2;
+               method.Block = (Block) $3;
                CheckDef (current_container.AddMethod (method), method.Name, method.Location);
 
                current_local_parameters = null;
+               iterator_container = null;
          }
        ;
 
@@ -1382,31 +1404,36 @@ constructor_declaration
                c.OptAttributes = (Attributes) $1;
                c.ModFlags = (int) $2;
        
-               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, 0, 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");
+               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 {
-                       c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
+                       // We let another layer check the validity of the constructor.
+                       Console.WriteLine ("{0} and {1}", c.Name, current_container.Basename);
                }
-               
+
                CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
 
                current_local_parameters = null;
@@ -1553,6 +1580,10 @@ add_accessor_declaration
                $$ = 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
@@ -1573,6 +1604,10 @@ 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
@@ -2040,7 +2075,9 @@ element_access
                // Blah i;
                  
                Expression expr = (Expression) $1;  
-               if (!(expr is SimpleName || expr is MemberAccess)) {
+               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 {
@@ -2048,7 +2085,7 @@ element_access
                        // So we extract the string corresponding to the SimpleName
                        // or MemberAccess
                        // 
-                       $$ = new SimpleName (GetQualifiedIdentifier (expr) + (string) $2, lexer.Location);
+                       $$ = new ComposedCast (expr, (string) $2, lexer.Location);
                }
          }
        ;
@@ -2783,7 +2820,7 @@ local_variable_type
                // Blah i;
                  
                Expression expr = (Expression) $1;  
-               if (!(expr is SimpleName || expr is MemberAccess)) {
+               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
                        Error_ExpectingTypeName (lexer.Location, expr);
                        $$ = null;
                } else {
@@ -2791,6 +2828,7 @@ local_variable_type
                        // So we extract the string corresponding to the SimpleName
                        // or MemberAccess
                        // 
+
                        if ((string) $2 == "")
                                $$ = $1;
                        else
@@ -2812,7 +2850,7 @@ local_variable_pointer_type
                Expression expr = (Expression) $1;  
                Location l = lexer.Location;
 
-               if (!(expr is SimpleName || expr is MemberAccess)) {
+               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
                        Error_ExpectingTypeName (l, expr);
 
                        $$ = null;
@@ -3160,7 +3198,7 @@ statement_expression_list
        : 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;
@@ -3183,7 +3221,7 @@ foreach_statement
          {
                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;
@@ -3224,6 +3262,7 @@ jump_statement
        | goto_statement
        | return_statement
        | throw_statement
+       | yield_statement
        ;
 
 break_statement
@@ -3269,6 +3308,29 @@ throw_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
@@ -3431,7 +3493,7 @@ fixed_statement
          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;
@@ -3728,6 +3790,7 @@ Expression DecomposeQI (string name, Location 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)
@@ -3738,6 +3801,7 @@ string GetQualifiedIdentifier (Expression expr)
                throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
        
 }
+#endif
 
 Block declare_local_variables (Expression type, ArrayList variable_declarators, Location loc)
 {
@@ -3760,7 +3824,7 @@ Block declare_local_variables (Expression type, ArrayList variable_declarators,
        // int j = 1;  int k = j + 1;
        //
        if (current_block.Used) {
-               implicit_block = new Block (current_block, true, loc, Location.Null);
+               implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
                implicit_block.AddChildVariableNames (current_block);
        } else
                implicit_block = current_block;
@@ -3808,7 +3872,7 @@ Block declare_local_constant (Expression type, VariableDeclaration decl)
        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;
 
@@ -3910,16 +3974,17 @@ public Tokenizer Lexer {
        }
 }                 
 
-public CSharpParser (StreamReader reader, string name, ArrayList defines)
+public CSharpParser (StreamReader reader, SourceFile file, ArrayList defines)
 {
-       current_namespace = new Namespace (null, "");
-       this.name = name;
+       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 (reader, name, defines);
+       lexer = new Tokenizer (reader, file, defines);
 }
 
 public override void parse ()
@@ -3929,6 +3994,8 @@ 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