remove experimental code in #if false .. #endif
[mono.git] / mcs / mcs / cs-parser.jay
old mode 100755 (executable)
new mode 100644 (file)
index 1313dd8..36e524f
@@ -89,9 +89,7 @@ namespace Mono.CSharp
                ///
                string tmpComment;
                string enumTypeComment;
-
-               
-               
+                       
                /// Current attribute target
                string current_attr_target;
                
@@ -334,7 +332,8 @@ using_alias_directive
        : USING IDENTIFIER ASSIGN 
          namespace_or_type_name SEMICOLON
          {
-               current_namespace.UsingAlias ((string) $2, (MemberName) $4, lexer.Location);
+               MemberName name = (MemberName) $4;
+               current_namespace.UsingAlias ((string) $2, name.GetTypeExpression (lexer.Location), lexer.Location);
          }
        | USING error {
                CheckIdentifierToken (yyToken);
@@ -344,7 +343,8 @@ using_alias_directive
 using_namespace_directive
        : USING namespace_name SEMICOLON 
          {
-               current_namespace.Using ((string) $2, lexer.Location);
+               MemberName ns_name = (MemberName) $2;
+               current_namespace.Using (ns_name.GetTypeExpression (lexer.Location), lexer.Location);
           }
        ;
 
@@ -389,11 +389,7 @@ opt_comma
        ;
 
 namespace_name
-       : namespace_or_type_name {
-               MemberName name = (MemberName) $1;
-
-               $$ = name.GetName ();
-         }
+       : namespace_or_type_name
        ;
 
 namespace_body
@@ -613,14 +609,18 @@ attribute
          }
          opt_attribute_arguments
          {
+                 Location loc = (Location) $2;
                MemberName mname = (MemberName) $1;
-               string name = mname.GetName ();
+               MemberName left = mname.Left;
+               string identifier = mname.Name;
+
+               Expression left_expr = left == null ? null : left.GetTypeExpression (loc);
+
                if (current_attr_target == "assembly" || current_attr_target == "module")
                        $$ = new GlobalAttribute (current_container, current_attr_target,
-                                                 name, (ArrayList) $3, (Location) $2);
+                                                 left_expr, identifier, (ArrayList) $3, loc);
                else
-                       $$ = new Attribute (current_attr_target, name, (ArrayList) $3,
-                                           (Location) $2);
+                       $$ = new Attribute (current_attr_target, left_expr, identifier, (ArrayList) $3, loc);
          }
        ;
 
@@ -910,11 +910,9 @@ field_declaration
                int mod = (int) $2;
 
                foreach (VariableDeclaration var in (ArrayList) $4){
-                       Location l = var.Location;
-
                        Field field = new Field (current_class, type, mod, var.identifier, 
                                                 var.expression_or_array_initializer, 
-                                                (Attributes) $1, l);
+                                                (Attributes) $1, var.Location);
 
                        if (RootContext.Documentation != null) {
                                field.DocComment = Lexer.consume_doc_comment ();
@@ -923,6 +921,27 @@ field_declaration
                        current_container.AddField (field);
                }
          }
+       | opt_attributes
+         opt_modifiers
+         FIXED
+         type 
+         fixed_variable_declarators
+         SEMICOLON
+         { 
+                       Expression type = (Expression) $4;
+                       int mod = (int) $2;
+
+                       foreach (VariableDeclaration var in (ArrayList) $5) {
+                               FixedField field = new FixedField (current_class, type, mod, var.identifier,
+                                       (Expression)var.expression_or_array_initializer, (Attributes) $1, var.Location);
+
+                               if (RootContext.Documentation != null) {
+                                       field.DocComment = Lexer.consume_doc_comment ();
+                                       Lexer.doc_state = XmlCommentState.Allowed;
+                               }
+                               current_container.AddField (field);
+                       }
+         }
        | opt_attributes
          opt_modifiers
          VOID  
@@ -932,6 +951,28 @@ field_declaration
          }
        ;
 
+fixed_variable_declarators
+       : fixed_variable_declarator
+               {
+                       ArrayList decl = new ArrayList (2);
+                       decl.Add ($1);
+                       $$ = decl;
+               }
+       | fixed_variable_declarators COMMA fixed_variable_declarator
+               {
+                       ArrayList decls = (ArrayList) $1;
+                       decls.Add ($3);
+                       $$ = $1;
+               }
+       ;
+
+fixed_variable_declarator
+       : IDENTIFIER OPEN_BRACKET expression CLOSE_BRACKET
+               {
+                       $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
+               }
+       ;
+
 variable_declarators
        : variable_declarator 
          {
@@ -1442,6 +1483,10 @@ interface_member_declaration
          { 
                Method m = (Method) $1;
 
+               if (m.IsExplicitImpl)
+                       Report.Error (541, lexer.Location, 
+                               "Explicit interface declaration can only be declared in a class or struct");
+
                current_container.AddMethod (m);
 
                if (RootContext.Documentation != null)
@@ -1451,6 +1496,10 @@ interface_member_declaration
          { 
                Property p = (Property) $1;
 
+               if (p.IsExplicitImpl)
+                       Report.Error (541, lexer.Location, 
+                               "Explicit interface declaration can only be declared in a class or struct");
+
                current_container.AddProperty (p);
 
                if (RootContext.Documentation != null)
@@ -1460,6 +1509,11 @@ interface_member_declaration
           { 
                if ($1 != null){
                        Event e = (Event) $1;
+
+                       if (e.IsExplicitImpl)
+                               Report.Error (541, lexer.Location, 
+                                   "Explicit interface declaration can only be declared in a class or struct");
+                       
                        current_container.AddEvent (e);
                }
 
@@ -1470,11 +1524,35 @@ interface_member_declaration
          { 
                Indexer i = (Indexer) $1;
 
+               if (i.IsExplicitImpl)
+                       Report.Error (541, lexer.Location, 
+                               "Explicit interface declaration can only be declared in a class or struct");
+
                current_container.AddIndexer (i);
 
                if (RootContext.Documentation != null)
                        Lexer.doc_state = XmlCommentState.Allowed;
          }
+       | delegate_declaration
+         {
+               Report.Error (524, lexer.Location, "Interfaces can not declare delegates");
+         }
+       | class_declaration
+         {
+               Report.Error (524, lexer.Location, "Interfaces can not declare classes");
+         }
+       | struct_declaration
+         {
+               Report.Error (524, lexer.Location, "Interfaces can not declare structures");
+         }
+       | enum_declaration 
+         {
+               Report.Error (524, lexer.Location, "Interfaces can not declare enumerations");
+         }
+       | interface_declaration 
+         {
+               Report.Error (524, lexer.Location, "Interfaces can not declare interfaces");
+         } 
        ;
 
 opt_new
@@ -1611,8 +1689,10 @@ operator_declaration
                        new Parameters (param_list, null, decl.location),
                        (ToplevelBlock) $5, (Attributes) $1, decl.location);
 
-               if (RootContext.Documentation != null)
-                       op.DocComment = ConsumeStoredComment ();
+               if (RootContext.Documentation != null) {
+                       op.DocComment = tmpComment;
+                       Lexer.doc_state = XmlCommentState.Allowed;
+               }
 
                if (SimpleIteratorContainer.Simple.Yields)
                        op.SetYields ();
@@ -1651,7 +1731,7 @@ operator_declarator
 
                if (RootContext.Documentation != null) {
                        tmpComment = Lexer.consume_doc_comment ();
-                       Lexer.doc_state = XmlCommentState.Allowed;
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
                }
 
                $$ = new OperatorDeclaration (op, (Expression) $1, type, (string) $6,
@@ -1677,7 +1757,7 @@ operator_declarator
 
                if (RootContext.Documentation != null) {
                        tmpComment = Lexer.consume_doc_comment ();
-                       Lexer.doc_state = XmlCommentState.Allowed;
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
                }
               
               $$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1, 
@@ -1724,6 +1804,11 @@ conversion_operator_declarator
 
                current_local_parameters = new Parameters (pars, null, lexer.Location);  
                  
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+
                $$ = new OperatorDeclaration (Operator.OpType.Implicit, (Expression) $3, (Expression) $5, (string) $6,
                                              null, null, lexer.Location);
          }
@@ -1735,6 +1820,11 @@ conversion_operator_declarator
 
                current_local_parameters = new Parameters (pars, null, lexer.Location);  
                  
+               if (RootContext.Documentation != null) {
+                       tmpComment = Lexer.consume_doc_comment ();
+                       Lexer.doc_state = XmlCommentState.NotAllowed;
+               }
+
                $$ = new OperatorDeclaration (Operator.OpType.Explicit, (Expression) $3, (Expression) $5, (string) $6,
                                              null, null, lexer.Location);
          }
@@ -1808,17 +1898,14 @@ constructor_declarator
                        Lexer.doc_state = XmlCommentState.Allowed;
                }
          }
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS _mark_
          {
-               oob_stack.Push (lexer.Location);
-
                current_local_parameters = (Parameters) $4;
          }
          opt_constructor_initializer
          {
-               Location l = (Location) oob_stack.Pop ();
                $$ = new Constructor (current_class, (string) $1, 0, (Parameters) $4,
-                                     (ConstructorInitializer) $7, l);
+                                     (ConstructorInitializer) $8, (Location) $6);
          }
        ;
 
@@ -1865,7 +1952,7 @@ destructor_declaration
          {
                if ((string) $5 != current_container.Basename){
                        Report.Error (574, lexer.Location, "Name of destructor must match name of class");
-               } else if (!(current_container is Class)){
+               } else if (current_container.Kind != Kind.Class){
                        Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
                } else {
                        Location l = lexer.Location;
@@ -1921,11 +2008,10 @@ event_declaration
        | opt_attributes
          opt_modifiers
          EVENT type namespace_or_type_name
-         OPEN_BRACE
+         OPEN_BRACE _mark_
          {
                implicit_value_parameter_type = (Expression) $4;  
                lexer.EventParsing = true;
-               oob_stack.Push (lexer.Location);
          }
          event_accessor_declarations
          {
@@ -1933,13 +2019,13 @@ event_declaration
          }
          CLOSE_BRACE
          {
-               Location loc = (Location) oob_stack.Pop ();
+               Location loc = (Location) $7;
 
-               if ($8 == null){
+               if ($9 == null){
                        Report.Error (65, lexer.Location, "Event must have both add and remove accesors");
                        $$ = null;
                } else {
-                       Pair pair = (Pair) $8;
+                       Pair pair = (Pair) $9;
                        
                        MemberName name = (MemberName) $5;
 
@@ -2038,7 +2124,7 @@ remove_accessor_declaration
 
 indexer_declaration
        : opt_attributes opt_modifiers indexer_declarator 
-         OPEN_BRACE 
+         OPEN_BRACE _mark_
          {
                IndexerDeclaration decl = (IndexerDeclaration) $3;
 
@@ -2048,7 +2134,6 @@ indexer_declaration
                parsing_indexer  = true;
                
                indexer_parameters = decl.param_list;
-               oob_stack.Push (lexer.Location);
          }
           accessor_declarations 
          {
@@ -2059,10 +2144,10 @@ indexer_declaration
          { 
                // The signature is computed from the signature of the indexer.  Look
                // at section 3.6 on the spec
-               Location loc = (Location) oob_stack.Pop ();
+               Location loc = (Location) $5;
                Indexer indexer;
                IndexerDeclaration decl = (IndexerDeclaration) $3;
-               Pair pair = (Pair) $6;
+               Pair pair = (Pair) $7;
                Accessor get_block = (Accessor) pair.First;
                Accessor set_block = (Accessor) pair.Second;
 
@@ -2536,6 +2621,18 @@ invocation_expression
          {
                $$ = new InvocationOrCast ((Expression) $1, (Expression) $3, lexer.Location);
          }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS non_simple_argument CLOSE_PARENS
+         {
+               ArrayList args = new ArrayList (1);
+               args.Add ($4);
+               $$ = new Invocation ((Expression) $1, args, lexer.Location);
+         }
+       | parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS argument_list COMMA argument CLOSE_PARENS
+         {
+               ArrayList args = ((ArrayList) $4);
+               args.Add ($6);
+               $$ = new Invocation ((Expression) $1, args, lexer.Location);
+         }
        ;
 
 opt_argument_list
@@ -2566,7 +2663,14 @@ argument
          {
                $$ = new Argument ((Expression) $1, Argument.AType.Expression);
          }
-       | REF variable_reference 
+       | non_simple_argument
+         {
+               $$ = $1;
+         }
+       ;
+
+non_simple_argument
+       : REF variable_reference 
          { 
                $$ = new Argument ((Expression) $2, Argument.AType.Ref);
          }
@@ -2837,24 +2941,26 @@ pointer_member_access
        ;
 
 anonymous_method_expression
-       : DELEGATE opt_anonymous_method_signature {
+       : DELEGATE opt_anonymous_method_signature _mark_
+         {
                oob_stack.Push (current_local_parameters);
                current_local_parameters = (Parameters)$2;
 
                // Force the next block to be created as a ToplevelBlock
                oob_stack.Push (current_block);
                oob_stack.Push (top_current_block);
-               oob_stack.Push (lexer.Location);
                current_block = null;
-         } block {
-               Location loc = (Location) oob_stack.Pop ();
+         } 
+         block
+         {
+               Location loc = (Location) $3;
                top_current_block = (Block) oob_stack.Pop ();
                current_block = (Block) oob_stack.Pop ();
                if (RootContext.Version == LanguageVersion.ISO_1){
                        Report.FeatureIsNotStandardized (lexer.Location, "anonymous methods");
                        $$ = null;
                } else  {
-                       ToplevelBlock anon_block = (ToplevelBlock) $4;
+                       ToplevelBlock anon_block = (ToplevelBlock) $5;
 
                        anon_block.Parent = current_block;
                        $$ = new AnonymousMethod ((Parameters) $2, (ToplevelBlock) top_current_block, 
@@ -3626,52 +3732,37 @@ selection_statement
        ; 
 
 if_statement
-       : if_statement_open if_statement_rest
-         {
-               $$ = $2;
-         }
-       ;
-
-if_statement_open
-       : IF OPEN_PARENS 
-         {
-               oob_stack.Push (lexer.Location);
-         }
-       ;
-
-if_statement_rest
-       : boolean_expression CLOSE_PARENS 
+       : IF OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS 
          embedded_statement
          { 
-               Location l = (Location) oob_stack.Pop ();
+               Location l = (Location) $3;
 
-               $$ = new If ((Expression) $1, (Statement) $3, l);
+               $$ = new If ((Expression) $4, (Statement) $6, l);
 
-               if (RootContext.WarningLevel >= 3){
-                       if ($3 == EmptyStatement.Value)
+               if (RootContext.WarningLevel >= 4){
+                       if ($6 == EmptyStatement.Value)
                                Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
                }
 
          }
-       | boolean_expression CLOSE_PARENS
+       | IF OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS
          embedded_statement ELSE embedded_statement
          {
-               Location l = (Location) oob_stack.Pop ();
+               Location l = (Location) $3;
 
-               $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l);
+               $$ = new If ((Expression) $4, (Statement) $6, (Statement) $8, l);
          }
        ;
 
 switch_statement
-       : SWITCH OPEN_PARENS 
+       : SWITCH OPEN_PARENS _mark_
          { 
-               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 ());
+               $$ = new Switch ((Expression) $5, (ArrayList) $7, (Location) $3);
                current_block = (Block) switch_stack.Pop ();
          }
        ;
@@ -3760,16 +3851,12 @@ iteration_statement
        ;
 
 while_statement
-       : WHILE OPEN_PARENS 
+       : WHILE OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS embedded_statement
        {
-               oob_stack.Push (lexer.Location);
-       }
-       boolean_expression CLOSE_PARENS embedded_statement
-       {
-               Location l = (Location) oob_stack.Pop ();
+               Location l = (Location) $3;
                $$ = new While ((Expression) $4, (Statement) $6, l);
        
-               if (RootContext.WarningLevel >= 3){
+               if (RootContext.WarningLevel >= 4){
                        if ($6 == EmptyStatement.Value)
                                Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
                }
@@ -3778,12 +3865,9 @@ while_statement
 
 do_statement
        : DO embedded_statement 
-         WHILE OPEN_PARENS {
-               oob_stack.Push (lexer.Location);
-         }
-         boolean_expression CLOSE_PARENS SEMICOLON
+         WHILE OPEN_PARENS _mark_ boolean_expression CLOSE_PARENS SEMICOLON
          {
-               Location l = (Location) oob_stack.Pop ();
+               Location l = (Location) $5;
 
                $$ = new Do ((Statement) $2, (Expression) $6, l);
          }
@@ -3791,7 +3875,7 @@ do_statement
 
 for_statement
        : FOR OPEN_PARENS 
-         opt_for_initializer SEMICOLON
+         opt_for_initializer SEMICOLON _mark_
          {
                Block assign_block = new Block (current_block);
                current_block = assign_block;
@@ -3832,20 +3916,23 @@ for_statement
                                }
                        }
                        
-                       $3 = null;
-               } 
-               oob_stack.Push (lexer.Location);
+                       // Note: the $$ below refers to the value of this code block, not of the LHS non-terminal.
+                       // This can be referred to as $6 below.
+                       $$ = null;
+               } else {
+                       $$ = $3;
+               }
          } 
          opt_for_condition SEMICOLON
          opt_for_iterator CLOSE_PARENS 
          embedded_statement
          {
-               Location l = (Location) oob_stack.Pop ();
+               Location l = (Location) $5;
 
-               For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
+               For f = new For ((Statement) $6, (Expression) $7, (Statement) $9, (Statement) $11, l);
 
-               if (RootContext.WarningLevel >= 3){
-                       if ($10 == EmptyStatement.Value)
+               if (RootContext.WarningLevel >= 4){
+                       if ($11 == EmptyStatement.Value)
                                Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
                }
 
@@ -3905,16 +3992,12 @@ foreach_statement
                Report.Error (230, lexer.Location, "Type and identifier are both required in a foreach statement");
                $$ = null;
        }
-       | FOREACH OPEN_PARENS type IDENTIFIER IN 
-         {
-               oob_stack.Push (lexer.Location);
-         }
+       | FOREACH OPEN_PARENS type IDENTIFIER IN _mark_
          expression CLOSE_PARENS 
          {
-               oob_stack.Push (current_block);
-
                Block foreach_block = new Block (current_block);
-               LocalVariableReference v = null;
+               current_block = foreach_block;
+
                Location l = lexer.Location;
                LocalInfo vi;
 
@@ -3923,28 +4006,28 @@ foreach_statement
                        vi.ReadOnly = true;
 
                        // Get a writable reference to this read-only variable.
-                       v = new LocalVariableReference (foreach_block, (string) $4, l, vi, false);
+                       //
+                       // Note that the $$ here refers to the value of _this_ code block,
+                       // not the value of the LHS non-terminal.  This can be referred to as $9 below.
+                       $$ = new LocalVariableReference (foreach_block, (string) $4, l, vi, false);
+               } else {
+                       $$ = null;
                }
-               current_block = foreach_block;
-
-               oob_stack.Push (v);
-               oob_stack.Push (current_block);
          } 
          embedded_statement 
          {
-               Block foreach_block = (Block) oob_stack.Pop ();
-               LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
-               Block prev_block = (Block) oob_stack.Pop ();
-               Location l = (Location) oob_stack.Pop ();
-
-               current_block = prev_block;
+               LocalVariableReference v = (LocalVariableReference) $9;
+               Location l = (Location) $6;
 
                if (v != null) {
                        Foreach f = new Foreach ((Expression) $3, v, (Expression) $7, (Statement) $10, l);
-                       foreach_block.AddStatement (f);
+                       current_block.AddStatement (f);
                }
 
-               $$ = foreach_block;
+               while (current_block.Implicit)
+                         current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
          }
        ;
 
@@ -4135,7 +4218,6 @@ catch_clause
 
                                one.Add (new VariableDeclaration (id, null, loc));
 
-                               $1 = current_block;
                                current_block = new Block (current_block);
                                Block b = declare_local_variables (type, one, loc);
                                current_block = b;
@@ -4150,17 +4232,14 @@ catch_clause
                        type = (Expression) cc.Key;
                        id   = (string) cc.Value;
 
-                       if ($1 != null){
-                               //
-                               // FIXME: I can change this for an assignment.
-                               //
-                               while (current_block != (Block) $1)
+                       if (id != null){
+                               while (current_block.Implicit)
                                        current_block = current_block.Parent;
+                               current_block = current_block.Parent;
                        }
                }
 
-
-               $$ = new Catch (type, id , (Block) $4, ((Block) $4).loc);
+               $$ = new Catch (type, id, (Block) $4, ((Block) $4).loc);
        }
         ;
 
@@ -4205,7 +4284,7 @@ unsafe_statement
 fixed_statement
        : FIXED OPEN_PARENS 
          type fixed_pointer_declarators 
-         CLOSE_PARENS 
+         CLOSE_PARENS _mark_
          {
                ArrayList list = (ArrayList) $4;
                Expression type = (Expression) $3;
@@ -4228,17 +4307,15 @@ fixed_statement
                        p.First = v;
                        list [i] = p;
                }
-
-               oob_stack.Push (l);
          }
          embedded_statement 
          {
-               Location l = (Location) oob_stack.Pop ();
+               Location l = (Location) $6;
 
-               Fixed f = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l);
+               Fixed f = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $8, l);
 
-               if (RootContext.WarningLevel >= 3){
-                       if ($7 == EmptyStatement.Value)
+               if (RootContext.WarningLevel >= 4){
+                       if ($8 == EmptyStatement.Value)
                                Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
                }
 
@@ -4290,13 +4367,11 @@ lock_statement
        ;
 
 using_statement
-       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS 
+       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS _mark_
          {
                Block assign_block = new Block (current_block);
                current_block = assign_block;
 
-               oob_stack.Push (lexer.Location);
-               
                if ($3 is DictionaryEntry){
                        DictionaryEntry de = (DictionaryEntry) $3;
                        Location l = lexer.Location;
@@ -4340,12 +4415,17 @@ using_statement
                                // Assign a = new Assign (var, expr, decl.Location);
                                // assign_block.AddStatement (new StatementExpression (a, lexer.Location));
                        }
-                       $3 = new DictionaryEntry (type, vars);
+
+                       // Note: the $$ here refers to the value of this code block and not of the LHS non-terminal.
+                       // It can be referred to as $6 below.
+                       $$ = new DictionaryEntry (type, vars);
+                } else {
+                       $$ = $3;
                 }
          } 
          embedded_statement
          {
-               Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
+               Using u = new Using ($6, (Statement) $7, (Location) $5);
                current_block.AddStatement (u);
                while (current_block.Implicit)
                        current_block = current_block.Parent;
@@ -4359,6 +4439,11 @@ resource_acquisition
        | expression
        ;
 
+// Utility rule to save location information
+_mark_
+       : /* empty */
+       { $$ = lexer.Location; }
+
 %%
 
 // <summary>