2003-04-28 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
index 7a90ba2950eb21c9f0d912e561d95660bfee1f4e..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"
@@ -311,11 +324,14 @@ namespace_declaration
                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
          { 
@@ -393,7 +409,9 @@ namespace_member_declaration
                }
                current_namespace.DeclarationFound = true;
          }
-       | namespace_declaration
+       | namespace_declaration {
+               current_namespace.DeclarationFound = true;
+         }
        ;
 
 type_declaration
@@ -424,10 +442,11 @@ attribute_sections
           {
                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
          {
@@ -435,11 +454,11 @@ attribute_sections
                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;
@@ -447,7 +466,7 @@ attribute_sections
        ;
 
 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;
                
@@ -456,7 +475,7 @@ attribute_section
                
                $$ = new AttributeSection (target, (ArrayList) $3);
          }
-        | OPEN_BRACKET attribute_list CLOSE_BRACKET
+        | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
          {
                $$ = new AttributeSection (null, (ArrayList) $2);
          }
@@ -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;
          }
        ;
 
@@ -1380,31 +1402,38 @@ constructor_declaration
                Constructor c = (Constructor) $3;
                c.Block = (Block) $4;
                c.OptAttributes = (Attributes) $1;
+               c.ModFlags = (int) $2;
        
-               if ((c.ModFlags & Modifiers.STATIC) != 0){
-                       c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, 0, c.Location);   
-
-                       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");
-                       }
-
-                       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;
@@ -1551,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
@@ -1571,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
@@ -1818,6 +1855,15 @@ non_expression_type
          {
                $$ = 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
@@ -1969,7 +2015,7 @@ invocation_expression
          {
                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);
          }
@@ -2029,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 {
@@ -2037,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);
                }
          }
        ;
@@ -2132,14 +2180,10 @@ opt_rank_specifier
        ;
 
 rank_specifiers
-       : rank_specifier
-         {
-                 $$ = $1;
-         }
-       | rank_specifiers rank_specifier
+       : rank_specifier opt_rank_specifier
          {
                  $$ = (string) $2 + (string) $1;
-         }             
+         }
         ;
 
 rank_specifier
@@ -2776,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 {
@@ -2784,6 +2828,7 @@ local_variable_type
                        // So we extract the string corresponding to the SimpleName
                        // or MemberAccess
                        // 
+
                        if ((string) $2 == "")
                                $$ = $1;
                        else
@@ -2805,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;
@@ -2985,9 +3030,11 @@ switch_section
          }
          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);
          }
        ;
 
@@ -3044,9 +3091,14 @@ while_statement
 
 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);
          }
        ;
 
@@ -3076,6 +3128,8 @@ for_statement
                                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);
@@ -3083,10 +3137,12 @@ for_statement
                                        
                                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;
@@ -3142,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;
@@ -3165,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;
@@ -3206,6 +3262,7 @@ jump_statement
        | goto_statement
        | return_statement
        | throw_statement
+       | yield_statement
        ;
 
 break_statement
@@ -3251,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
@@ -3410,10 +3490,10 @@ unsafe_statement
 
 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;
@@ -3710,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)
@@ -3720,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)
 {
@@ -3742,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;
@@ -3790,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;
 
@@ -3892,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 ()
@@ -3911,11 +3994,13 @@ 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);
        }
 }