-static void
-readgram (void)
-{
- token_t t;
- symbol_t *lhs = NULL;
-
- t = lex ();
-
- while (t != tok_two_percents && t != tok_eof)
- if (t == tok_identifier || t == tok_bar)
- {
- int action_flag = 0;
- /* Number of symbols in rhs of this rule so far */
- int rulelength = 0;
- int xactions = 0; /* JF for error checking */
- symbol_t *first_rhs = 0;
-
- if (t == tok_identifier)
- {
- lhs = symval;
-
- t = lex ();
- if (t != tok_colon)
- {
- complain (_("ill-formed rule: initial symbol not followed by colon"));
- unlex (t);
- }
- }
- if (nrules == 0 && t == tok_bar)
- {
- complain (_("grammar starts with vertical bar"));
- lhs = symval; /* BOGUS: use a random symval */
- }
-
- grammar_rule_begin (lhs);
- /* read the rhs of the rule. */
-
- for (;;)
- {
- t = lex ();
- if (t == tok_prec)
- {
- t = lex ();
- current_rule->ruleprec = symval;
- t = lex ();
- }
-
- if (!(t == tok_identifier || t == tok_left_curly))
- break;
-
- /* If next token is an identifier, see if a colon follows it.
- If one does, exit this rule now. */
- if (t == tok_identifier)
- {
- symbol_t *ssave;
- token_t t1;
-
- ssave = symval;
- t1 = lex ();
- unlex (t1);
- symval = ssave;
- if (t1 == tok_colon)
- {
- warn (_("previous rule lacks an ending `;'"));
- break;
- }
-
- if (!first_rhs) /* JF */
- first_rhs = symval;
- /* Not followed by colon =>
- process as part of this rule's rhs. */
- }
-
- /* If we just passed an action, that action was in the middle
- of a rule, so make a dummy rule to reduce it to a
- non-terminal. */
- if (action_flag)
- {
- grammar_midrule_action ();
- action_flag = 0;
- }
-
- if (t == tok_identifier)
- {
- ++nritems;
- grammar_symbol_append (symval);
- }
- else /* handle an action. */
- {
- parse_action (current_rule, rulelength);
- action_flag = 1;
- ++xactions; /* JF */
- }
- ++rulelength;
- } /* end of read rhs of rule */
-
- /* Put an empty link in the list to mark the end of this rule */
- grammar_symbol_append (NULL);
-
- if (t == tok_prec)
- {
- complain (_("two @prec's in a row"));
- t = lex ();
- current_rule->ruleprec = symval;
- t = lex ();
- }
-
- if (t == tok_left_curly)
- {
- /* This case never occurs -wjh */
- if (action_flag)
- complain (_("two actions at end of one rule"));
- parse_action (current_rule, rulelength);
- action_flag = 1;
- ++xactions; /* -wjh */
- t = lex ();
- }
- /* If $$ is being set in default way, report if any type
- mismatch. */
- else if (!xactions
- && first_rhs && lhs->type_name != first_rhs->type_name)
- {
- if (lhs->type_name == 0
- || first_rhs->type_name == 0
- || strcmp (lhs->type_name, first_rhs->type_name))
- complain (_("type clash (`%s' `%s') on default action"),
- lhs->type_name ? lhs->type_name : "",
- first_rhs->type_name ? first_rhs->type_name : "");
- }
- /* Warn if there is no default for $$ but we need one. */
- else if (!xactions && !first_rhs && lhs->type_name != 0)
- complain (_("empty rule for typed nonterminal, and no action"));
- if (t == tok_two_percents || t == tok_eof)
- warn (_("previous rule lacks an ending `;'"));
- if (t == tok_semicolon)
- t = lex ();
- }
- else
- {
- complain (_("invalid input: %s"), quote (token_buffer));
- t = lex ();
- }
-
- /* grammar has been read. Do some checking */
-
- if (nrules == 0)
- fatal (_("no rules in the input grammar"));
-
- /* Report any undefined symbols and consider them nonterminals. */
- symbols_check_defined ();
+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");
+ current_rule->ruleprec = precsym;
+}