X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/872b52bc24b5590ac8bdec7db882cdbefc0ec3ff..882be728b2481ed2f83805ab8d2cbbab2830f39c:/src/reader.c diff --git a/src/reader.c b/src/reader.c index 275d7c4c..3f007541 100644 --- a/src/reader.c +++ b/src/reader.c @@ -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, 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) + complain_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. */ @@ -383,7 +393,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 +405,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 +454,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) { 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, named_ref); + current_rule, name); } @@ -589,36 +610,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")) + 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. */ + /* Check %define front-end variables. */ { static char const * const values[] = { - "lr.type", "LALR", "IELR", "canonical LR", NULL, + "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 (); - - xfclose (gram_in); } @@ -634,9 +660,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 +670,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) {