]> git.saurik.com Git - bison.git/blobdiff - src/reader.c
named references: fix double free.
[bison.git] / src / reader.c
index 275d7c4ce1c1b767edd3dd883f66456232f06ba0..2289d26e80c66ee23db8048c996dbd14c60f0741 100644 (file)
@@ -1,7 +1,7 @@
 /* Input parser for Bison
 
-   Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000, 2001, 2002, 2003,
-   2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000-2003, 2005-2007,
+   2009-2011 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -36,6 +36,7 @@
 #include "scan-gram.h"
 #include "scan-code.h"
 
+static void prepare_percent_define_front_end_variables (void);
 static void check_and_convert_grammar (void);
 
 static symbol_list *grammar = NULL;
@@ -191,19 +192,19 @@ grammar_symbol_append (symbol *sym, location loc)
 }
 
 static void
-assign_named_ref (symbol_list *p, named_ref *named_ref)
+assign_named_ref (symbol_list *p, named_ref *name)
 {
   symbol *sym = p->content.sym;
 
-  if (named_ref->id == sym->tag)
+  if (name->id == sym->tag)
     {
-      warn_at (named_ref->loc,
+      warn_at (name->loc,
               _("duplicated symbol name for %s ignored"),
               quote (sym->tag));
-      named_ref_free (named_ref);
+      named_ref_free (name);
     }
   else
-    p->named_ref = named_ref;
+    p->named_ref = name;
 }
 
 
@@ -220,7 +221,7 @@ static symbol_list *previous_rule_end = NULL;
 
 void
 grammar_current_rule_begin (symbol *lhs, location loc,
-                           named_ref *lhs_named_ref)
+                           named_ref *lhs_name)
 {
   symbol_list* p;
 
@@ -229,8 +230,8 @@ grammar_current_rule_begin (symbol *lhs, location loc,
   previous_rule_end = grammar_end;
 
   p = grammar_symbol_append (lhs, loc);
-  if (lhs_named_ref)
-    assign_named_ref(p, lhs_named_ref);
+  if (lhs_name)
+    assign_named_ref (p, named_ref_copy (lhs_name));
 
   current_rule = grammar_end;
 
@@ -319,6 +320,15 @@ grammar_rule_check (const symbol_list *r)
            warn_at (r->location, _("unset value: $$"));
        }
   }
+
+  /* See comments in grammar_current_rule_prec_set for how POSIX
+     mandates this complaint.  It's only for identifiers, so skip
+     it for char literals and strings, which are always tokens.  */
+  if (r->ruleprec
+      && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
+      && !r->ruleprec->declared && !r->ruleprec->prec)
+    warn_at (r->location, _("token for %%prec is not defined: %s"),
+             r->ruleprec->tag);
 }
 
 
@@ -356,7 +366,7 @@ grammar_midrule_action (void)
   symbol_list *midrule = symbol_list_sym_new (dummy, dummy_location);
 
   /* Remember named_ref of previous action. */
-  named_ref *named_ref = current_rule->action_props.named_ref;
+  named_ref *action_name = current_rule->action_props.named_ref;
 
   /* Make a new rule, whose body is empty, before the current one, so
      that the action just read can belong to it.  */
@@ -367,7 +377,8 @@ grammar_midrule_action (void)
   code_props_rule_action_init (&midrule->action_props,
                                current_rule->action_props.code,
                                current_rule->action_props.location,
-                               midrule, 0);
+                               midrule, 0,
+                              current_rule->action_props.is_predicate);
   code_props_none_init (&current_rule->action_props);
 
   if (previous_rule_end)
@@ -383,7 +394,8 @@ grammar_midrule_action (void)
 
   /* Insert the dummy nonterminal replacing the midrule action into
      the current rule.  Bind it to its dedicated rule.  */
-  grammar_current_rule_symbol_append (dummy, dummy_location, named_ref);
+  grammar_current_rule_symbol_append (dummy, dummy_location,
+                                      action_name);
   grammar_end->midrule = midrule;
   midrule->midrule_parent_rule = current_rule;
   midrule->midrule_parent_rhs_index = symbol_list_length (current_rule->next);
@@ -394,6 +406,16 @@ grammar_midrule_action (void)
 void
 grammar_current_rule_prec_set (symbol *precsym, location loc)
 {
+  /* POSIX says that any identifier is a nonterminal if it does not
+     appear on the LHS of a grammar rule and is not defined by %token
+     or by one of the directives that assigns precedence to a token.  We
+     ignore this here because the only kind of identifier that POSIX
+     allows to follow a %prec is a token and because assuming it's a
+     token now can produce more logical error messages.  Nevertheless,
+     grammar_rule_check does obey what we believe is the real intent of
+     POSIX here: that an error be reported for any identifier that
+     appears after %prec but that is not defined separately as a
+     token.  */
   symbol_class_set (precsym, token_sym, loc, false);
   if (current_rule->ruleprec)
     complain_at (loc, _("only one %s allowed per rule"), "%prec");
@@ -433,28 +455,28 @@ grammar_current_rule_merge_set (uniqstr name, location loc)
 
 void
 grammar_current_rule_symbol_append (symbol *sym, location loc,
-                                   named_ref *named_ref)
+                                   named_ref *name)
 {
   symbol_list *p;
   if (current_rule->action_props.code)
     grammar_midrule_action ();
   p = grammar_symbol_append (sym, loc);
-  if (named_ref)
-    assign_named_ref(p, named_ref);
+  if (name)
+    assign_named_ref(p, name);
 }
 
 /* Attach an ACTION to the current rule.  */
 
 void
 grammar_current_rule_action_append (const char *action, location loc,
-                                   named_ref *named_ref)
+                                   named_ref *name, bool is_predicate)
 {
   if (current_rule->action_props.code)
     grammar_midrule_action ();
   /* After all symbol declarations have been parsed, packgram invokes
      code_props_translate_code.  */
   code_props_rule_action_init (&current_rule->action_props, action, loc,
-                               current_rule, named_ref);
+                               current_rule, name, is_predicate);
 }
 
 \f
@@ -495,6 +517,7 @@ packgram (void)
       rules[ruleno].useful = true;
       rules[ruleno].action = p->action_props.code;
       rules[ruleno].action_location = p->action_props.location;
+      rules[ruleno].is_predicate = p->action_props.is_predicate;
 
       /* 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
@@ -589,36 +612,41 @@ reader (void)
   gram_debug = trace_flag & trace_parse;
   gram_scanner_initialize ();
   gram_parse ();
+  prepare_percent_define_front_end_variables ();
+
+  if (! complaint_issued)
+    check_and_convert_grammar ();
+
+  xfclose (gram_in);
+}
 
-  /* Set front-end %define variable defaults.  */
+static void
+prepare_percent_define_front_end_variables (void)
+{
+  /* Set %define front-end variable defaults.  */
   muscle_percent_define_default ("lr.keep-unreachable-states", "false");
   {
     char *lr_type;
     /* IELR would be a better default, but LALR is historically the
        default.  */
-    muscle_percent_define_default ("lr.type", "LALR");
+    muscle_percent_define_default ("lr.type", "lalr");
     lr_type = muscle_percent_define_get ("lr.type");
-    if (0 != strcmp (lr_type, "canonical LR"))
-      muscle_percent_define_default ("lr.default-reductions", "all");
+    if (0 != strcmp (lr_type, "canonical-lr"))
+      muscle_percent_define_default ("lr.default-reductions", "full");
     else
       muscle_percent_define_default ("lr.default-reductions", "accepting");
     free (lr_type);
   }
 
-  /* Check front-end %define variables.  */
+  /* Check %define front-end variables.  */
   {
     static char const * const values[] = {
-      "lr.type", "LALR", "IELR", "canonical LR", NULL,
-      "lr.default-reductions", "all", "consistent", "accepting", NULL,
+      "lr.type", "lalr", "ielr", "canonical-lr", NULL,
+      "lr.default-reductions", "full", "consistent", "accepting", NULL,
       NULL
     };
     muscle_percent_define_check_values (values);
   }
-
-  if (! complaint_issued)
-    check_and_convert_grammar ();
-
-  xfclose (gram_in);
 }
 
 
@@ -634,9 +662,6 @@ check_and_convert_grammar (void)
   if (nrules == 0)
     fatal (_("no rules in the input grammar"));
 
-  /* Report any undefined symbols and consider them nonterminals.  */
-  symbols_check_defined ();
-
   /* If the user did not define her ENDTOKEN, do it now. */
   if (!endtoken)
     {
@@ -647,6 +672,9 @@ check_and_convert_grammar (void)
       endtoken->user_token_number = 0;
     }
 
+  /* Report any undefined symbols and consider them nonterminals.  */
+  symbols_check_defined ();
+
   /* Find the start symbol if no %start.  */
   if (!start_flag)
     {