b4_args is more general than only C++.
[bison.git] / src / reader.c
index 4cc6f7b1c04ecb51629bed87fa47c9f3c702458d..7758c772937fd126966ecc13bdf500b21c88de9d 100644 (file)
@@ -1,28 +1,25 @@
 /* Input parser for Bison
 
    Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000, 2001, 2002, 2003,
-   2005, 2006 Free Software Foundation, Inc.
+   2005, 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
-   Bison is free software; you can redistribute it and/or modify
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   Bison is distributed in the hope that it will be useful,
+   This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with Bison; see the file COPYING.  If not, write to
-   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include "system.h"
-#include <assert.h>
 
 #include <quotearg.h>
 
@@ -70,27 +67,6 @@ grammar_start_symbol_set (symbol *sym, location loc)
     }
 }
 
-
-/*---------------------------------------------------------------------.
-| There are two prologues: one before the first %union and one after.  |
-|  Augment the one specified by POST.                                  |
-`---------------------------------------------------------------------*/
-
-void
-prologue_augment (const char *prologue, location loc, bool post)
-{
-  struct obstack *oout =
-    !post ? &pre_prologue_obstack : &post_prologue_obstack;
-
-  obstack_fgrow1 (oout, "]b4_syncline(%d, [[", loc.start.line);
-  /* FIXME: Protection of M4 characters missing here.  See
-     output.c:escaped_output.  */
-  MUSCLE_OBSTACK_SGROW (oout,
-                       quotearg_style (c_quoting_style, loc.start.file));
-  obstack_sgrow (oout, "]])[\n");
-  obstack_sgrow (oout, prologue);
-}
-
 \f
 
 /*------------------------------------------------------------------------.
@@ -148,7 +124,7 @@ record_merge_function_type (int merger, uniqstr type, location declaration_loc)
        merge_function != NULL && merger_find != merger;
        merge_function = merge_function->next)
     merger_find += 1;
-  assert (merge_function != NULL && merger_find == merger);
+  aver (merge_function != NULL && merger_find == merger);
   if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
     {
       complain_at (declaration_loc,
@@ -244,16 +220,25 @@ grammar_current_rule_begin (symbol *lhs, location loc)
 
 
 /*----------------------------------------------------------------------.
-| A symbol should be used if it has a destructor, or if it is a         |
-| mid-rule symbol (i.e., the generated LHS replacing a mid-rule         |
-| action) that was assigned to, as in "exp: { $$ = 1; } { $$ = $1; }".  |
+| A symbol should be used if either:                                    |
+|   1. It has a destructor.                                             |
+|   2. --warnings=midrule-values and the symbol is a mid-rule symbol    |
+|      (i.e., the generated LHS replacing a mid-rule action) that was   |
+|      assigned to or used, as in "exp: { $$ = 1; } { $$ = $1; }".      |
 `----------------------------------------------------------------------*/
 
 static bool
 symbol_should_be_used (symbol_list const *s)
 {
-  return (symbol_destructor_get (s->content.sym)
-         || (s->midrule && s->midrule->used));
+  if (symbol_destructor_get (s->content.sym)->code)
+    return true;
+  if (warnings_flag & warnings_midrule_values)
+    return ((s->midrule && s->midrule->action_props.is_value_used)
+           || (s->midrule_parent_rule
+               && symbol_list_n_get (s->midrule_parent_rule,
+                                     s->midrule_parent_rhs_index)
+                     ->action_props.is_value_used));
+  return false;
 }
 
 /*----------------------------------------------------------------.
@@ -271,7 +256,7 @@ grammar_rule_check (const symbol_list *r)
 
      Don't worry about the default action if $$ is untyped, since $$'s
      value can't be used.  */
-  if (!r->action && r->content.sym->type_name)
+  if (!r->action_props.code && r->content.sym->type_name)
     {
       symbol *first_rhs = r->next->content.sym;
       /* If $$ is being set in default way, report if any type mismatch.  */
@@ -296,10 +281,10 @@ grammar_rule_check (const symbol_list *r)
     symbol_list const *l = r;
     int n = 0;
     for (; l && l->content.sym; l = l->next, ++n)
-      if (! (l->used
+      if (! (l->action_props.is_value_used
             || !symbol_should_be_used (l)
             /* The default action, $$ = $1, `uses' both.  */
-            || (!r->action && (n == 0 || n == 1))))
+            || (!r->action_props.code && (n == 0 || n == 1))))
        {
          if (n)
            warn_at (r->location, _("unused value: $%d"), n);
@@ -339,7 +324,7 @@ grammar_midrule_action (void)
 
   /* Make a DUMMY nonterminal, whose location is that of the midrule
      action.  Create the MIDRULE.  */
-  location dummy_location = current_rule->action_location;
+  location dummy_location = current_rule->action_props.location;
   symbol *dummy = dummy_symbol_get (dummy_location);
   symbol_list *midrule = symbol_list_sym_new (dummy, dummy_location);
 
@@ -349,12 +334,11 @@ grammar_midrule_action (void)
   ++nritems;
   /* Attach its location and actions to that of the DUMMY.  */
   midrule->location = dummy_location;
-  midrule->action = current_rule->action;
-  midrule->action_location = dummy_location;
-  current_rule->action = NULL;
-  /* The action has not been translated yet, so $$ use hasn't been
-     detected yet.  */
-  midrule->used = false;
+  code_props_rule_action_init (&midrule->action_props,
+                               current_rule->action_props.code,
+                               current_rule->action_props.location,
+                               midrule);
+  code_props_none_init (&current_rule->action_props);
 
   if (previous_rule_end)
     previous_rule_end->next = midrule;
@@ -380,6 +364,7 @@ grammar_midrule_action (void)
 void
 grammar_current_rule_prec_set (symbol *precsym, location loc)
 {
+  symbol_class_set (precsym, token_sym, loc, false);
   if (current_rule->ruleprec)
     complain_at (loc, _("only one %s allowed per rule"), "%prec");
   current_rule->ruleprec = precsym;
@@ -419,7 +404,7 @@ grammar_current_rule_merge_set (uniqstr name, location loc)
 void
 grammar_current_rule_symbol_append (symbol *sym, location loc)
 {
-  if (current_rule->action)
+  if (current_rule->action_props.code)
     grammar_midrule_action ();
   grammar_symbol_append (sym, loc);
 }
@@ -429,12 +414,12 @@ grammar_current_rule_symbol_append (symbol *sym, location loc)
 void
 grammar_current_rule_action_append (const char *action, location loc)
 {
-  if (current_rule->action)
+  if (current_rule->action_props.code)
     grammar_midrule_action ();
   /* After all symbol declarations have been parsed, packgram invokes
-     translate_rule_action.  */
-  current_rule->action = action;
-  current_rule->action_location = loc;
+     code_props_translate_code.  */
+  code_props_rule_action_init (&current_rule->action_props, action, loc,
+                               current_rule);
 }
 
 \f
@@ -473,14 +458,19 @@ packgram (void)
       rules[ruleno].precsym = NULL;
       rules[ruleno].location = p->location;
       rules[ruleno].useful = true;
-      rules[ruleno].action = p->action ? translate_rule_action (p) : NULL;
-      rules[ruleno].action_location = p->action_location;
-
-      /* If this rule contains midrules, rest assured that
-        grammar_midrule_action inserted the midrules into grammar before this
-        rule.  Thus, the midrule actions have already been scanned in order to
-        set `used' flags for this rule's rhs, so grammar_rule_check will work
-        properly.  */
+      rules[ruleno].action = p->action_props.code;
+      rules[ruleno].action_location = p->action_props.location;
+
+      /* If the midrule's $$ is set or its $n is used, remove the `$' from the
+        symbol name so that it's a user-defined symbol so that the default
+        %destructor and %printer apply.  */
+      if (p->midrule_parent_rule
+          && (p->action_props.is_value_used
+             || symbol_list_n_get (p->midrule_parent_rule,
+                                   p->midrule_parent_rhs_index)
+                   ->action_props.is_value_used))
+       p->content.sym->tag += 1;
+
       /* Don't check the generated rule 0.  It has no action, so some rhs
         symbols may appear unused, but the parsing algorithm ensures that
         %destructor's are invoked appropriately.  */
@@ -515,15 +505,15 @@ packgram (void)
        }
       /* An item ends by the rule number (negated).  */
       ritem[itemno++] = rule_number_as_item_number (ruleno);
-      assert (itemno < ITEM_NUMBER_MAX);
+      aver (itemno < ITEM_NUMBER_MAX);
       ++ruleno;
-      assert (ruleno < RULE_NUMBER_MAX);
+      aver (ruleno < RULE_NUMBER_MAX);
 
       if (p)
        p = p->next;
     }
 
-  assert (itemno == nritems);
+  aver (itemno == nritems);
 
   if (trace_flag & trace_sets)
     ritem_print (stderr);
@@ -558,10 +548,6 @@ reader (void)
   undeftoken->class = token_sym;
   undeftoken->number = ntokens++;
 
-  /* Initialize the obstacks. */
-  obstack_init (&pre_prologue_obstack);
-  obstack_init (&post_prologue_obstack);
-
   gram_in = xfopen (grammar_file, "r");
 
   gram__flex_debug = trace_flag & trace_scan;
@@ -614,7 +600,7 @@ check_and_convert_grammar (void)
                node = node->next)
             ;
         }
-      assert (node != NULL);
+      aver (node != NULL);
       grammar_start_symbol_set (node->content.sym,
                                 node->content.sym->location);
     }
@@ -635,15 +621,32 @@ check_and_convert_grammar (void)
     grammar = p;
   }
 
-  assert (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars);
+  aver (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars);
 
   /* Assign the symbols their symbol numbers.  Write #defines for the
      token symbols into FDEFINES if requested.  */
   symbols_pack ();
 
+  /* Scan rule actions after invoking symbol_check_alias_consistency (in
+     symbols_pack above) so that token types are set correctly before the rule
+     action type checking.
+
+     Before invoking grammar_rule_check (in packgram below) on any rule, make
+     sure all actions have already been scanned in order to set `used' flags.
+     Otherwise, checking that a midrule's $$ should be set will not always work
+     properly because the check must forward-reference the midrule's parent
+     rule.  For the same reason, all the `used' flags must be set before
+     checking whether to remove `$' from any midrule symbol name (also in
+     packgram).  */
+  {
+    symbol_list *sym;
+    for (sym = grammar; sym; sym = sym->next)
+      code_props_translate_code (&sym->action_props);
+  }
+
   /* Convert the grammar into the format described in gram.h.  */
   packgram ();
 
   /* The grammar as a symbol_list is no longer needed. */
-  LIST_FREE (symbol_list, grammar);
+  symbol_list_free (grammar);
 }