#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;
}
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;
}
void
grammar_current_rule_begin (symbol *lhs, location loc,
- named_ref *lhs_named_ref)
+ named_ref *lhs_name)
{
symbol_list* p;
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;
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);
}
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. */
/* 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);
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");
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);
}
\f
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);
}
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)
{
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)
{