X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/76290368d48b584808a120dfbd415be93aef04f6..992e874a7c2c243e4b83752235a26ccdb9b1ef0a:/src/reader.c diff --git a/src/reader.c b/src/reader.c index ce23f48c..1b2dcfce 100644 --- a/src/reader.c +++ b/src/reader.c @@ -1,28 +1,27 @@ /* Input parser for Bison Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000, 2001, 2002, 2003, - 2005, 2006 Free Software Foundation, Inc. + 2005, 2006, 2007, 2009 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 . */ #include #include "system.h" +#include #include #include "complain.h" @@ -69,27 +68,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); -} - /*------------------------------------------------------------------------. @@ -192,7 +170,7 @@ free_merger_functions (void) static symbol_list *grammar_end = NULL; /* Append SYM to the grammar. */ -static void +static symbol_list * grammar_symbol_append (symbol *sym, location loc) { symbol_list *p = symbol_list_sym_new (sym, loc); @@ -208,8 +186,27 @@ grammar_symbol_append (symbol *sym, location loc) part of it. */ if (sym) ++nritems; + + return p; } +static void +assign_named_ref (symbol_list *p, named_ref *name) +{ + symbol *sym = p->content.sym; + + if (name->id == sym->tag) + { + warn_at (name->loc, + _("duplicated symbol name for %s ignored"), + quote (sym->tag)); + named_ref_free (name); + } + else + p->named_ref = name; +} + + /* The rule currently being defined, and the previous rule. CURRENT_RULE points to the first LHS of the current rule, while PREVIOUS_RULE_END points to the *end* of the previous rule (NULL). */ @@ -222,12 +219,19 @@ static symbol_list *previous_rule_end = NULL; `----------------------------------------------*/ void -grammar_current_rule_begin (symbol *lhs, location loc) +grammar_current_rule_begin (symbol *lhs, location loc, + named_ref *lhs_name) { + symbol_list* p; + /* Start a new rule and record its lhs. */ ++nrules; previous_rule_end = grammar_end; - grammar_symbol_append (lhs, loc); + + p = grammar_symbol_append (lhs, loc); + if (lhs_name) + assign_named_ref(p, lhs_name); + current_rule = grammar_end; /* Mark the rule's lhs as a nonterminal if not already so. */ @@ -253,21 +257,14 @@ grammar_current_rule_begin (symbol *lhs, location loc) static bool symbol_should_be_used (symbol_list const *s) { - if (code_props_code_get (symbol_destructor_get (s->content.sym))) + if (symbol_destructor_get (s->content.sym)->code) return true; if (warnings_flag & warnings_midrule_values) - { - if (s->midrule && code_props_is_value_used (s->midrule->action_props)) - return true; - if (s->midrule_parent_rule) - { - symbol_list *rhs_node = - symbol_list_n_get (s->midrule_parent_rule, - s->midrule_parent_rhs_index); - if (code_props_is_value_used (rhs_node->action_props)) - return true; - } - } + 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; } @@ -286,7 +283,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 (!code_props_code_get (r->action_props) && 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. */ @@ -311,11 +308,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 (! (code_props_is_value_used (l->action_props) + if (! (l->action_props.is_value_used || !symbol_should_be_used (l) /* The default action, $$ = $1, `uses' both. */ - || (!code_props_code_get (r->action_props) - && (n == 0 || n == 1)))) + || (!r->action_props.code && (n == 0 || n == 1)))) { if (n) warn_at (r->location, _("unused value: $%d"), n); @@ -355,22 +351,23 @@ grammar_midrule_action (void) /* Make a DUMMY nonterminal, whose location is that of the midrule action. Create the MIDRULE. */ - location dummy_location = - code_props_location_get (current_rule->action_props); + 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); + /* Remember named_ref of previous action. */ + 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. */ ++nrules; ++nritems; /* Attach its location and actions to that of the DUMMY. */ midrule->location = dummy_location; - code_props_rule_action_init ( - &midrule->action_props, - code_props_code_get (current_rule->action_props), - code_props_location_get (current_rule->action_props), - midrule); + code_props_rule_action_init (&midrule->action_props, + current_rule->action_props.code, + current_rule->action_props.location, + midrule, 0); code_props_none_init (¤t_rule->action_props); if (previous_rule_end) @@ -386,7 +383,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); + 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); @@ -397,6 +395,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; @@ -434,24 +433,29 @@ grammar_current_rule_merge_set (uniqstr name, location loc) action as a mid-rule action. */ void -grammar_current_rule_symbol_append (symbol *sym, location loc) +grammar_current_rule_symbol_append (symbol *sym, location loc, + named_ref *name) { - if (code_props_code_get (current_rule->action_props)) + symbol_list *p; + if (current_rule->action_props.code) grammar_midrule_action (); - grammar_symbol_append (sym, loc); + p = grammar_symbol_append (sym, loc); + 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) +grammar_current_rule_action_append (const char *action, location loc, + named_ref *name) { - if (code_props_code_get (current_rule->action_props)) + 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 (¤t_rule->action_props, action, loc, - current_rule); + current_rule, name); } @@ -474,20 +478,6 @@ packgram (void) rules = xnmalloc (nrules, sizeof *rules); - /* Before invoking grammar_rule_check 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. */ - while (p) - { - code_props_translate_code (&p->action_props); - if (p) - p = p->next; - } - - p = grammar; while (p) { int rule_length = 0; @@ -504,20 +494,17 @@ packgram (void) rules[ruleno].precsym = NULL; rules[ruleno].location = p->location; rules[ruleno].useful = true; - rules[ruleno].action = code_props_code_get (p->action_props); - if (rules[ruleno].action) - rules[ruleno].action_location = - code_props_location_get (p->action_props); + 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 - && (code_props_is_value_used (p->action_props) - || code_props_is_value_used ( - symbol_list_n_get ( - p->midrule_parent_rule, - p->midrule_parent_rhs_index)->action_props))) + && (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 @@ -597,10 +584,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; @@ -608,6 +591,31 @@ reader (void) gram_scanner_initialize (); gram_parse (); + /* Set front-end %define 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"); + lr_type = muscle_percent_define_get ("lr.type"); + if (0 != strcmp (lr_type, "canonical LR")) + muscle_percent_define_default ("lr.default-reductions", "all"); + else + muscle_percent_define_default ("lr.default-reductions", "accepting"); + free (lr_type); + } + + /* Check front-end %define variables. */ + { + static char const * const values[] = { + "lr.type", "LALR", "IELR", "canonical LR", NULL, + "lr.default-reductions", "all", "consistent", "accepting", NULL, + NULL + }; + muscle_percent_define_check_values (values); + } + if (! complaint_issued) check_and_convert_grammar (); @@ -680,6 +688,23 @@ check_and_convert_grammar (void) 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 ();