2004-01-20 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / cs-parser.jay
index 292afb79c046fae9521b18dd9f949d7c5cfa9a5c..38fb6de96ac9f1f548150757c91eb96a34803757 100755 (executable)
@@ -36,53 +36,59 @@ namespace Mono.CSharp
        
                IIteratorContainer iterator_container;
 
-               // <summary>
-               //   Current block is used to add statements as we find
-               //   them.  
-               // </summary>
-
+               /// <summary>
+               ///   Current block is used to add statements as we find
+               ///   them.  
+               /// </summary>
                Block      current_block;
 
-               // <summary>
-               //   Current interface is used by the various declaration
-               //   productions in the interface declaration to "add"
-               //   the interfaces as we find them.
-               // </summary>
+               /// <summary>
+                ///   If true, creates a toplevel block in the block production
+                ///   This is flagged by the delegate creation
+                /// </summary>
+                bool       create_toplevel_block;
+       
+                /// <summary>
+               /// <summary>
+               ///   Current interface is used by the various declaration
+               ///   productions in the interface declaration to "add"
+               ///   the interfaces as we find them.
+               /// </summary>
                Interface  current_interface;
 
-               // <summary>
-               //   This is used by the unary_expression code to resolve
-               //   a name against a parameter.  
-               // </summary>
+               /// <summary>
+               ///   This is used by the unary_expression code to resolve
+               ///   a name against a parameter.  
+               /// </summary>
                Parameters current_local_parameters;
 
-               // <summary>
-               //   Using during property parsing to describe the implicit
-               //   value parameter that is passed to the "set" and "get"accesor
-               //   methods (properties and indexers).
-               // </summary>
+               /// <summary>
+               ///   Using during property parsing to describe the implicit
+               ///   value parameter that is passed to the "set" and "get"accesor
+               ///   methods (properties and indexers).
+               /// </summary>
                Expression implicit_value_parameter_type;
                Parameters indexer_parameters;
 
-               // <summary>
-               //   Used to determine if we are parsing the get/set pair
-               //   of an indexer or a property
-               // </summmary>
+               /// <summary>
+               ///   Used to determine if we are parsing the get/set pair
+               ///   of an indexer or a property
+               /// </summmary>
                bool  parsing_indexer;
 
-               //
-               // An out-of-band stack.
-               //
+               ///
+               /// An out-of-band stack.
+               ///
                Stack oob_stack;
 
-               //
-               // Switch stack.
-               //
+               ///
+               /// Switch stack.
+               ///
                Stack switch_stack;
 
-               //
-               // The current file.
-               //
+               ///
+               /// The current file.
+               ///
                SourceFile file;
 %}
 
@@ -307,7 +313,7 @@ using_alias_directive
        : USING IDENTIFIER ASSIGN 
          namespace_or_type_name SEMICOLON
          {
-                 current_namespace.UsingAlias ((string) $2, (string) $4, lexer.Location);
+                 current_namespace.UsingAlias ((string) $2, (string) ($4).ToString (), lexer.Location);
          }
        | USING error {
                CheckIdentifierToken (yyToken);
@@ -341,7 +347,7 @@ namespace_declaration
                                        + " Expected class, delegate, enum, interface, or struct");
                }
 
-               current_namespace = RootContext.Tree.RecordNamespace (current_namespace, file, (string) $3, lexer.Location);
+               current_namespace = RootContext.Tree.RecordNamespace (current_namespace, file, (string) ($3).ToString (), lexer.Location);
        } 
          namespace_body opt_semicolon
          { 
@@ -360,14 +366,15 @@ opt_comma
        ;
 
 qualified_identifier
-       : IDENTIFIER
+       : IDENTIFIER { $$ = new QualifiedIdentifier ((string) $1); }
        | qualified_identifier DOT IDENTIFIER { 
-           $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
+               $$ = new QualifiedIdentifier ((QualifiedIdentifier) $1, (string) $3);
+         }
        ;
 
 
 namespace_name
-       : namespace_or_type_name
+       : namespace_or_type_name { $$ = ($1).ToString (); } 
        ;
 
 namespace_body
@@ -422,6 +429,13 @@ namespace_member_declaration
        | namespace_declaration {
                current_namespace.DeclarationFound = true;
          }
+
+       | field_declaration {
+               Report.Error (116, lexer.Location, "A namespace can only contain types and namespace declarations");
+         }
+       | method_declaration {
+               Report.Error (116, lexer.Location, "A namespace can only contain types and namespace declarations");
+         }
        ;
 
 type_declaration
@@ -534,7 +548,7 @@ attribute
          }
          opt_attribute_arguments
          {
-               $$ = new Attribute ((string) $1, (ArrayList) $3, (Location) $2);
+               $$ = new Attribute ((string) ($1).ToString (), (ArrayList) $3, (Location) $2);
          }
        ;
 
@@ -913,6 +927,21 @@ method_header
                current_local_parameters = (Parameters) $6;
                $$ = method;
          }
+       | opt_attributes
+         opt_modifiers
+         type 
+         modifiers member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         {
+               Report.Error (1585, lexer.Location, 
+                       String.Format ("Modifier {0} should appear before type", 
+                               Modifiers.Name ((int) $4)));
+               Method method = new Method (current_container, TypeManager.system_void_expr, 0,
+                                           (string) $5, (Parameters) $7, (Attributes) $1,
+                                           lexer.Location);
+
+               current_local_parameters = (Parameters) $7;
+               $$ = method;
+         }
        ;
 
 method_body
@@ -1007,7 +1036,7 @@ parameter_array
        ;
 
 member_name 
-       : qualified_identifier
+       : qualified_identifier { $$ = ($1).ToString (); } 
        ;
 
 property_declaration
@@ -1172,13 +1201,13 @@ interface_type_list
          {
                ArrayList interfaces = new ArrayList (4);
 
-               interfaces.Add ($1);
+               interfaces.Add (($1).ToString ());
                $$ = interfaces;
          }
        | interface_type_list COMMA interface_type
          {
                ArrayList interfaces = (ArrayList) $1;
-               interfaces.Add ($3);
+               interfaces.Add (($3).ToString ());
                $$ = interfaces;
          }
        ;
@@ -1214,9 +1243,10 @@ interface_member_declaration
           }
        | interface_event_declaration 
           { 
-               InterfaceEvent e = (InterfaceEvent) $1;
-
-               CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
+               if ($1 != null){
+                       InterfaceEvent e = (InterfaceEvent) $1;
+                       CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
+               }
          }
        | interface_indexer_declaration
          { 
@@ -1227,8 +1257,13 @@ interface_member_declaration
        ;
 
 opt_new
-       : /* empty */   { $$ = false; }
-       | NEW           { $$ = true; }
+       : opt_modifiers 
+         {
+               int val = (int) $1;
+               
+               val = Modifiers.Check (Modifiers.NEW, val, 0, lexer.Location);
+               $$ = (bool) (val != 0);
+         }
        ;
 
 interface_method_declaration
@@ -1292,6 +1327,14 @@ interface_event_declaration
                CheckIdentifierToken (yyToken);
                $$ = null;
          }
+       | opt_attributes opt_new EVENT type IDENTIFIER ASSIGN  {
+               Report.Error (68, lexer.Location, "Event declarations on interfaces can not be initialized.");
+               $$ = null;
+         }
+       | opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE event_accessor_declarations CLOSE_BRACE {
+               Report.Error (69, lexer.Location, "Event accessors not valid on interfaces");
+               $$ = null;
+         }
        ;
 
 interface_indexer_declaration 
@@ -1555,7 +1598,7 @@ destructor_declaration
                                 }
                         }
                         
-                       Method d = new Method (
+                       Method d = new Destructor (
                                current_container, TypeManager.system_void_expr, m, "Finalize", 
                                new Parameters (null, null, l), (Attributes) $1, l);
                  
@@ -1597,20 +1640,25 @@ event_declaration
          {
                Location loc = (Location) oob_stack.Pop ();
 
-               Pair pair = (Pair) $8;
-               Accessor add_accessor = null;
-               Accessor rem_accessor = null;
-
-               if (pair.First != null)
-                       add_accessor = (Accessor) pair.First;
-               if (pair.Second != null)
-                       rem_accessor = (Accessor) pair.Second;
-               
-               Event e = new Event ((Expression) $4, (string) $5, null, (int) $2, add_accessor, rem_accessor,
-                                    (Attributes) $1, loc);
-               
-               CheckDef (current_container.AddEvent (e), e.Name, loc);
-               implicit_value_parameter_type = null;
+               if ($8 == null){
+                       Report.Error (65, lexer.Location, "Event must have both add and remove accesors");
+                       $$ = null;
+               } else {
+                       Pair pair = (Pair) $8;
+                       Accessor add_accessor = null;
+                       Accessor rem_accessor = null;
+       
+                       if (pair.First != null)
+                               add_accessor = (Accessor) pair.First;
+                       if (pair.Second != null)
+                               rem_accessor = (Accessor) pair.Second;
+                       
+                       Event e = new Event ((Expression) $4, (string) $5, null, (int) $2, add_accessor, rem_accessor,
+                                            (Attributes) $1, loc);
+                       
+                       CheckDef (current_container.AddEvent (e), e.Name, loc);
+                       implicit_value_parameter_type = null;
+               }
          }
        ;
 
@@ -1623,6 +1671,8 @@ event_accessor_declarations
        {
                $$ = new Pair ($2, $1);
        }       
+       | add_accessor_declaration  { $$ = null; } 
+       | remove_accessor_declaration { $$ = null; } 
        ;
 
 add_accessor_declaration
@@ -1735,7 +1785,7 @@ indexer_declarator
                if (pars.FixedParameters == null && pars.ArrayParameter == null){
                        Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
                }
-               $$ = new IndexerDeclaration ((Expression) $1, (string) $2, pars);
+               $$ = new IndexerDeclaration ((Expression) $1, (string) ($2).ToString (), pars);
          }
        ;
 
@@ -1860,6 +1910,13 @@ namespace_or_type_name
        : qualified_identifier
        ;
 
+type_name_expression
+       : IDENTIFIER { $$ = new SimpleName ((string) $1, lexer.Location);}
+       | type_name_expression DOT IDENTIFIER { 
+               $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
+         }
+       ;
+
 /* 
  * Before you think of adding a return_type, notice that we have been
  * using two rules in the places where it matters (one rule using type
@@ -1867,12 +1924,11 @@ namespace_or_type_name
  * gets rid of a shift/reduce couple
  */
 type
-       : type_name {   /* class_type */
+       : type_name_expression {        /* class_type */
                /* 
                   This does interfaces, delegates, struct_types, class_types, 
                   parent classes, and more! 4.2 
                 */
-               $$ = DecomposeQI ((string) $1, lexer.Location);
          }
        | builtin_types
        | array_type
@@ -1989,13 +2045,7 @@ primary_expression
                // 7.5.1: Literals
          }
  
-       | qualified_identifier
-         {
-               string name = (string) $1;
-
-               $$ = null;
-               $$ = DecomposeQI (name, lexer.Location);
-         }
+       | IDENTIFIER { $$ = new SimpleName ((string) $1, lexer.Location); }
        | parenthesized_expression
        | member_access
        | invocation_expression
@@ -2400,7 +2450,9 @@ anonymous_method_expression
        : DELEGATE opt_anonymous_method_signature {
                oob_stack.Push (current_local_parameters);
                current_local_parameters = (Parameters)$2;
+               create_toplevel_block = true;
          } block {
+               create_toplevel_block = false;
                if (!RootContext.V2){
                        Report.Error (-213, lexer.Location, "Anonymous methods are only supported in V2");
                        $$ = null;
@@ -2869,8 +2921,12 @@ class_base
 block
        : OPEN_BRACE 
          {
-               current_block = new Block (current_block, current_local_parameters,
-                                          lexer.Location, Location.Null);
+               if (current_block == null || create_toplevel_block){
+                       current_block = new ToplevelBlock (current_local_parameters, lexer.Location);
+               } else {
+                       current_block = new Block (current_block, current_local_parameters,
+                               lexer.Location, Location.Null);
+               }
          } 
          opt_statement_list CLOSE_BRACE 
          { 
@@ -2902,9 +2958,6 @@ statement
          }
        | embedded_statement
          {
-               Statement s = (Statement) $1;
-
-
                current_block.AddStatement ((Statement) $1);
          }
        | labeled_statement
@@ -2929,7 +2982,7 @@ embedded_statement
 empty_statement
        : SEMICOLON
          {
-                 $$ = new EmptyStatement ();
+                 $$ = EmptyStatement.Value;
          }
        ;
 
@@ -3135,7 +3188,7 @@ if_statement_rest
                $$ = new If ((Expression) $1, (Statement) $3, l);
 
                if (RootContext.WarningLevel >= 3){
-                       if ($3 is EmptyStatement)
+                       if ($3 == EmptyStatement.Value)
                                Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
                }
 
@@ -3257,7 +3310,7 @@ while_statement
                $$ = new While ((Expression) $4, (Statement) $6, l);
        
                if (RootContext.WarningLevel >= 3){
-                       if ($6 is EmptyStatement)
+                       if ($6 == EmptyStatement.Value)
                                Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
                }
        }
@@ -3332,7 +3385,7 @@ for_statement
                For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
 
                if (RootContext.WarningLevel >= 3){
-                       if ($10 is EmptyStatement)
+                       if ($10 == EmptyStatement.Value)
                                Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
                }
 
@@ -3345,7 +3398,7 @@ for_statement
        ;
 
 opt_for_initializer
-       : /* empty */           { $$ = new EmptyStatement (); }
+       : /* empty */           { $$ = EmptyStatement.Value; }
        | for_initializer       
        ;
 
@@ -3360,7 +3413,7 @@ opt_for_condition
        ;
 
 opt_for_iterator
-       : /* empty */           { $$ = new EmptyStatement (); }
+       : /* empty */           { $$ = EmptyStatement.Value; }
        | for_iterator
        ;
 
@@ -3702,10 +3755,7 @@ fixed_statement
          embedded_statement 
          {
                Location l = (Location) oob_stack.Pop ();
-               Block assign_block = (Block) oob_stack.Pop ();
-
-               ArrayList list = (ArrayList) $4;
-               int top = list.Count;
+               oob_stack.Pop ();
 
                $$ = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l);
          }
@@ -3837,7 +3887,6 @@ public class VariableDeclaration {
 // <summary>
 //   A class used to hold info about an indexer declarator
 // </summary>
-
 public class IndexerDeclaration {
        public Expression type;
        public string interface_type;
@@ -3854,7 +3903,6 @@ public class IndexerDeclaration {
 // <summary>
 //  A class used to hold info about an operator declarator
 // </summary>
-
 public class OperatorDeclaration {
        public Operator.OpType optype;
        public Expression ret_type, arg1type, arg2type;
@@ -3876,6 +3924,51 @@ public class OperatorDeclaration {
 
 }
 
+public class QualifiedIdentifier {
+       public string s;
+       public QualifiedIdentifier prev;
+
+       public QualifiedIdentifier (string s)
+       {       
+               this.s = s;
+               prev = null;
+       }
+
+       public QualifiedIdentifier (QualifiedIdentifier prev, string s)
+       {
+               this.s = s;
+               this.prev = prev;
+       }
+
+       public override string ToString ()
+       {
+               if (prev == null)
+                       return s;
+
+               // Common cases
+
+               if (prev.prev == null)
+                       return prev.s + "." + s;
+               if (prev.prev.prev == null)
+                       return prev.prev.s + "." + prev.s + "." + s;
+
+               // Uncommon cases.
+               QualifiedIdentifier ptr = this.prev;
+               int count = 1;
+               while (ptr != null){
+                       count++;
+                       ptr = ptr.prev;
+               }
+               string [] ss = new string [count];
+               ptr = this;
+               for (int i = count; i-- > 0;){
+                       ss [i] = ptr.s;
+                       ptr = ptr.prev;
+               }
+               return String.Join (".", ss, 0, ss.Length);
+       }
+}
+
 void Error_ExpectingTypeName (Location l, Expression expr)
 {
        if (expr is Invocation){
@@ -3955,20 +4048,15 @@ CheckDef (bool result, string name, Location l)
        CheckDef (DeclSpace.AdditionResult.NameExists, name, l);
 }
 
-Expression DecomposeQI (string name, Location loc)
+Expression DecomposeQI (QualifiedIdentifier qi, Location loc)
 {
        Expression o;
 
-       if (name.IndexOf ('.') == -1){
-               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);
+       if (qi.prev == null)
+               return new SimpleName (qi.s, loc);
+       else {
+               o = DecomposeQI (qi.prev, loc);
+               return new MemberAccess (o, qi.s, loc);
        }
 }