2003-05-27 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
index e8c5a659fcef62b26333db558ba4da479182cc8e..9550f25894bb4ac941e4e0ca82ac9f9eb372d09d 100755 (executable)
 //       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
@@ -30,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.  
@@ -73,6 +79,11 @@ namespace Mono.CSharp
                // Switch stack.
                //
                Stack switch_stack;
+
+               //
+               // The current file.
+               //
+               SourceFile file;
 %}
 
 %token EOF
@@ -164,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"
@@ -254,6 +268,7 @@ compilation_unit
         : outer_declarations opt_EOF
         | outer_declarations attribute_sections opt_EOF
         | attribute_sections opt_EOF
+       | opt_EOF /* allow empty files */
         ;
        
 opt_EOF
@@ -309,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
          { 
@@ -391,7 +409,9 @@ namespace_member_declaration
                }
                current_namespace.DeclarationFound = true;
          }
-       | namespace_declaration
+       | namespace_declaration {
+               current_namespace.DeclarationFound = true;
+         }
        ;
 
 type_declaration
@@ -422,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
          {
@@ -433,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;
@@ -445,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;
                
@@ -454,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);
          }
@@ -751,6 +772,13 @@ field_declaration
                        CheckDef (current_container.AddField (field), field.Name, l);
                }
          }
+       | opt_attributes
+         opt_modifiers
+         VOID  
+         variable_declarators
+         SEMICOLON {
+               Report.Error (670, lexer.Location, "void type is not allowed for fields");
+         }
        ;
 
 variable_declarators
@@ -795,11 +823,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){
@@ -816,10 +846,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;
          }
        ;
 
@@ -1377,29 +1408,39 @@ constructor_declaration
          { 
                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;
@@ -1440,6 +1481,10 @@ constructor_initializer
          {
                $$ = new ConstructorThisInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
          }
+       | COLON error {
+               Report.Error (1018, lexer.Location, "Keyword this or base expected");
+               $$ = null;
+         }
        ;
 
 destructor_declaration
@@ -1546,6 +1591,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
@@ -1566,6 +1615,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
@@ -1813,6 +1866,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
@@ -1964,7 +2026,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);
          }
@@ -2024,17 +2086,18 @@ element_access
                // 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);
          }
        ;
 
@@ -2056,7 +2119,7 @@ expression_list
 this_access
        : THIS
          {
-               $$ = new This (lexer.Location);
+               $$ = new This (current_block, lexer.Location);
          }
        ;
 
@@ -2128,14 +2191,10 @@ opt_rank_specifier
        ;
 
 rank_specifiers
-       : rank_specifier
-         {
-                 $$ = $1;
-         }
-       | rank_specifiers rank_specifier
+       : rank_specifier opt_rank_specifier
          {
                  $$ = (string) $2 + (string) $1;
-         }             
+         }
         ;
 
 rank_specifier
@@ -2251,7 +2310,11 @@ unary_expression
          {
                $$ = 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);
          }
@@ -2670,7 +2733,7 @@ statement_list
 statement
        : declaration_statement
          {
-               if ((Block) $1 != current_block){
+               if ($1 != null && (Block) $1 != current_block){
                        current_block.AddStatement ((Statement) $1);
                        current_block = (Block) $1;
                }
@@ -2725,16 +2788,20 @@ labeled_statement
 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);
+               }
          }
        ;
 
@@ -2764,20 +2831,20 @@ local_variable_type
                // 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
          {
@@ -2792,13 +2859,14 @@ local_variable_pointer_type
        : 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
          {
@@ -2817,24 +2885,33 @@ local_variable_pointer_type
 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;
          }
        ;
 
@@ -2960,13 +3037,15 @@ switch_sections
 switch_section
        : switch_labels
          {
-               current_block = new Block (current_block);
+               current_block = current_block.CreateSwitchBlock (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);
          }
        ;
 
@@ -3023,9 +3102,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);
          }
        ;
 
@@ -3044,7 +3128,7 @@ for_statement
 
                        foreach (VariableDeclaration decl in var_declarators){
 
-                               VariableInfo vi;
+                               LocalInfo vi;
 
                                vi = current_block.AddVariable (
                                        type, decl.identifier, current_local_parameters, decl.Location);
@@ -3055,6 +3139,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);
@@ -3062,10 +3148,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;
@@ -3121,7 +3209,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;
@@ -3144,10 +3232,10 @@ 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;
+               LocalInfo vi;
 
                vi = foreach_block.AddVariable ((Expression) $3, (string) $4, current_local_parameters, l);
                if (vi != null) {
@@ -3185,6 +3273,7 @@ jump_statement
        | goto_statement
        | return_statement
        | throw_statement
+       | yield_statement
        ;
 
 break_statement
@@ -3230,6 +3319,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
@@ -3389,10 +3501,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;
@@ -3400,7 +3512,7 @@ fixed_statement
 
                for (int i = 0; i < top; i++){
                        Pair p = (Pair) list [i];
-                       VariableInfo v;
+                       LocalInfo v;
 
                        v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
                        if (v == null)
@@ -3477,7 +3589,7 @@ using_statement
 
                        foreach (VariableDeclaration decl in var_declarators){
 
-                               VariableInfo vi = current_block.AddVariable (
+                               LocalInfo vi    = current_block.AddVariable (
                                        type, decl.identifier, 
                                        current_local_parameters, decl.Location);
                                if (vi == null)
@@ -3591,6 +3703,15 @@ public class OperatorDeclaration {
 
 }
 
+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
@@ -3680,6 +3801,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)
@@ -3690,6 +3812,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)
 {
@@ -3711,9 +3834,10 @@ 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);
-       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){
@@ -3759,7 +3883,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;
 
@@ -3861,17 +3985,17 @@ public Tokenizer Lexer {
        }
 }                 
 
-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 ()
@@ -3881,11 +4005,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);
        }
 }