2002-08-19 Martin Baulig <martin@gnome.org>
[mono.git] / mcs / mcs / cs-parser.jay
index a5c4cd0cf3bcbeb4173650c27c4ca0da87c3b208..49b08716d9edced03471596cda0b062a7d981d52 100755 (executable)
@@ -68,6 +68,11 @@ namespace Mono.CSharp
                // An out-of-band stack.
                //
                Stack oob_stack;
+
+               //
+               // Switch stack.
+               //
+               Stack switch_stack;
 %}
 
 %token EOF
@@ -871,7 +876,7 @@ method_body
        ;
 
 opt_formal_parameter_list
-       : /* empty */                   { $$ = Parameters.GetEmptyReadOnlyParameters (); }
+       : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
        | formal_parameter_list
        ;
 
@@ -933,8 +938,8 @@ opt_parameter_modifier
        ;
 
 parameter_modifier
-       : REF                   { $$ = Parameter.Modifier.REF; }
-       | OUT                   { $$ = Parameter.Modifier.OUT; }
+       : REF                   { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
+       | OUT                   { $$ = Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF; }
        ;
 
 parameter_array
@@ -1429,11 +1434,11 @@ opt_constructor_initializer
 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);
          }
        ;
 
@@ -2051,7 +2056,7 @@ expression_list
 this_access
        : THIS
          {
-               $$ = new This (lexer.Location);
+               $$ = new This (current_block, lexer.Location);
          }
        ;
 
@@ -2216,14 +2221,14 @@ sizeof_expression
 checked_expression
        : CHECKED OPEN_PARENS expression CLOSE_PARENS
          {
-               $$ = new CheckedExpr ((Expression) $3);
+               $$ = new CheckedExpr ((Expression) $3, lexer.Location);
          }
        ;
 
 unchecked_expression
        : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
          {
-               $$ = new UnCheckedExpr ((Expression) $3);
+               $$ = new UnCheckedExpr ((Expression) $3, lexer.Location);
          }
        ;
 
@@ -2639,7 +2644,8 @@ class_base
 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 
          { 
@@ -2705,7 +2711,7 @@ empty_statement
 labeled_statement
        : IDENTIFIER COLON 
          {
-               LabeledStatement labeled = new LabeledStatement ((string) $1);
+               LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
 
                if (!current_block.AddLabel ((string) $1, labeled)){
                        Location l = lexer.Location;
@@ -2907,11 +2913,13 @@ switch_statement
        : SWITCH OPEN_PARENS 
          { 
                oob_stack.Push (lexer.Location);
+               switch_stack.Push (current_block);
          }
          expression CLOSE_PARENS 
          switch_block
          {
                $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
+               current_block = (Block) switch_stack.Pop ();
          }
        ;
 
@@ -2959,7 +2967,6 @@ switch_section
                while (current_block.Implicit)
                        current_block = current_block.Parent;
                $$ = new SwitchSection ((ArrayList) $1, current_block);
-               current_block = current_block.Parent;
          }
        ;
 
@@ -3041,29 +3048,24 @@ for_statement
 
                                vi = current_block.AddVariable (
                                        type, decl.identifier, current_local_parameters, decl.Location);
-                               if (vi == null){
-                                       Report.Error (128, decl.Location, 
-                                                     "A local variable `" + decl.identifier + 
-                                                     "' is already defined in this scope");
+                               if (vi == null)
+                                       continue;
+
+                               Location l = lexer.Location;
+                               Expression expr;
+                               if (decl.expression_or_array_initializer is Expression){
+                                       expr = (Expression) decl.expression_or_array_initializer;
                                } else {
-                                       Location l = lexer.Location;
-                                       Expression expr;
-                                       if (decl.expression_or_array_initializer is Expression){
-                                               expr = (Expression) decl.expression_or_array_initializer;
-                                               
-                                       } else {
-                                               ArrayList init = (ArrayList) decl.expression_or_array_initializer;
-                                               expr = new ArrayCreation (type, "", init, decl.Location);
-                                       }
+                                       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);
+                               LocalVariableReference var;
+                               var = new LocalVariableReference (assign_block, decl.identifier, l);
                                        
-                                       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;
@@ -3143,19 +3145,17 @@ foreach_statement
                oob_stack.Push (current_block);
 
                Block foreach_block = new Block (current_block, true);
-               LocalVariableReference v;
+               LocalVariableReference v = null;
                Location l = lexer.Location;
                VariableInfo vi;
 
                vi = foreach_block.AddVariable ((Expression) $3, (string) $4, current_local_parameters, l);
-               vi.ReadOnly = true;
-               if (vi == null){
-                       Report.Error (
-                               128, l, "A local variable `" + (string) $4 + "' is already "+
-                               "defined in this scope");
-               }
+               if (vi != null) {
+                       vi.ReadOnly = true;
 
-               v = new LocalVariableReference (foreach_block, (string) $4, l);
+                       // Get a writable reference to this read-only variable.
+                       v = new LocalVariableReference (foreach_block, (string) $4, l, vi, false);
+               }
                current_block = foreach_block;
 
                oob_stack.Push (v);
@@ -3170,8 +3170,10 @@ foreach_statement
 
                current_block = prev_block;
 
-               Foreach f = new Foreach ((Expression) $3, v, (Expression) $7, (Statement) $10, l);
-               foreach_block.AddStatement (f);
+               if (v != null) {
+                       Foreach f = new Foreach ((Expression) $3, v, (Expression) $7, (Statement) $10, l);
+                       foreach_block.AddStatement (f);
+               }
 
                $$ = foreach_block;
          }
@@ -3240,7 +3242,7 @@ try_statement
                ArrayList s = new ArrayList ();
                
                foreach (Catch cc in (ArrayList) $3) {
-                       if (cc.Type == null)
+                       if (cc.IsGeneral)
                                g = cc;
                        else
                                s.Add (cc);
@@ -3249,7 +3251,7 @@ try_statement
                // Now s contains the list of specific catch clauses
                // and g contains the general one.
                
-               $$ = new Try ((Block) $2, s, g, null);
+               $$ = new Try ((Block) $2, s, g, null, lexer.Location);
        }
        | TRY block opt_catch_clauses FINALLY block
          {
@@ -3259,14 +3261,14 @@ try_statement
 
                if (catch_list != null){
                        foreach (Catch cc in catch_list) {
-                               if (cc.Type == null)
+                               if (cc.IsGeneral)
                                        g = cc;
                                else
                                        s.Add (cc);
                        }
                }
 
-               $$ = new Try ((Block) $2, s, g, (Block) $5);
+               $$ = new Try ((Block) $2, s, g, (Block) $5, lexer.Location);
          }
        | TRY block error 
          {
@@ -3401,11 +3403,8 @@ fixed_statement
                        VariableInfo v;
 
                        v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
-                       if (v == null){
-                               Report.Error (
-                                       128, l, "A local variable `" + (string) p.First + "' is already "+
-                                       "defined in this scope");
-                       }
+                       if (v == null)
+                               continue;
                        v.ReadOnly = true;
                        p.First = v;
                        list [i] = p;
@@ -3474,20 +3473,17 @@ using_statement
                        Expression type = (Expression) de.Key;
                        ArrayList var_declarators = (ArrayList) de.Value;
 
-                       foreach (VariableDeclaration decl in var_declarators){
-                               if (current_block.AddVariable (
-                                       type, decl.identifier, 
-                                       current_local_parameters, decl.Location) == null){
-                                       Report.Error (128, decl.Location, 
-                                       "A local variable `" + decl.identifier + "' is already" +
-                                       "defined in this scope");
-                               }
-                       }
-
                        ArrayList vars = new ArrayList ();
 
                        foreach (VariableDeclaration decl in var_declarators){
 
+                               VariableInfo vi = current_block.AddVariable (
+                                       type, decl.identifier, 
+                                       current_local_parameters, decl.Location);
+                               if (vi == null)
+                                       continue;
+                               vi.ReadOnly = true;
+
                                Expression expr;
                                if (decl.expression_or_array_initializer is Expression){
                                        expr = (Expression) decl.expression_or_array_initializer;
@@ -3498,11 +3494,9 @@ using_statement
                                }
 
                                LocalVariableReference var;
-                               VariableInfo vi;
 
-                               var = new LocalVariableReference (assign_block, decl.identifier, l);
-                               vi = var.VariableInfo;
-                               vi.ReadOnly = true;
+                               // 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;
@@ -3663,45 +3657,19 @@ CheckDef (bool result, string name, Location l)
        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);
-       }
-
-       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);
        }
 }
@@ -3756,9 +3724,6 @@ Block declare_local_variables (Expression type, ArrayList variable_declarators,
                                        inits = new ArrayList ();
                                inits.Add (decl);
                        }
-               } else {
-                       Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
-                                        "' is already defined in this scope");
                }
        }
 
@@ -3800,8 +3765,6 @@ Block declare_local_constant (Expression type, VariableDeclaration decl)
 
        if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
                                          current_local_parameters, decl.Location))){
-               Report.Error (128, decl.Location, "A local variable `" + decl.identifier +
-                             "' is already defined in this scope");
        }
        
        return implicit_block;
@@ -3906,6 +3869,7 @@ public CSharpParser (string name, System.IO.Stream input, ArrayList defines)
        current_container = RootContext.Tree.Types;
        current_container.Namespace = current_namespace;
        oob_stack = new Stack ();
+       switch_stack = new Stack ();
 
        lexer = new Tokenizer (input, name, defines);
 }