+/* The (currently) last symbol of GRAMMAR. */
+symbol_list *grammar_end = NULL;
+
+/* Append S to the GRAMMAR. */
+static void
+grammar_symbol_append (symbol_t *s)
+{
+ symbol_list *p = symbol_list_new (s);
+
+ if (grammar_end)
+ grammar_end->next = p;
+ else
+ grammar = p;
+
+ grammar_end = p;
+}
+
+/* The rule currently being defined, and the previous rule. Point to
+ the first symbol of each list: their lhs. */
+symbol_list *current_rule = NULL;
+symbol_list *previous_rule = NULL;
+
+
+/* Create a new rule for LHS in to the GRAMMAR. */
+
+static void
+grammar_rule_begin (symbol_t *lhs)
+{
+ if (!start_flag)
+ {
+ startsymbol = lhs;
+ start_flag = 1;
+ }
+
+ /* Start a new rule and record its lhs. */
+ ++nrules;
+ ++nritems;
+
+ previous_rule = grammar_end;
+ grammar_symbol_append (lhs);
+ current_rule = grammar_end;
+
+ /* Mark the rule's lhs as a nonterminal if not already so. */
+
+ if (lhs->class == unknown_sym)
+ {
+ lhs->class = nterm_sym;
+ lhs->number = nvars;
+ ++nvars;
+ }
+ else if (lhs->class == token_sym)
+ complain (_("rule given for %s, which is a token"), lhs->tag);
+}
+
+/* The previous action turns out the be a mid-rule action. Attach it
+ to the current rule, i.e., create a dummy symbol, attach it this
+ mid-rule action, and append this dummy nonterminal to the current
+ rule. */
+
+static void
+grammar_midrule_action (void)
+{
+ /* Since the action was written out with this rule's number, we must
+ give the new rule this number by inserting the new rule before
+ it. */
+
+ /* Make a dummy nonterminal, a gensym. */
+ symbol_t *sdummy = gensym ();
+ symbol_list *midrule_action = symbol_list_new (sdummy);
+
+ /* 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 lineno to that of the host rule. */
+ midrule_action->line = current_rule->line;
+ /* Move the action from the host rule to this one. */
+ midrule_action->action = current_rule->action;
+ midrule_action->action_line = current_rule->action_line;
+ current_rule->action = NULL;
+
+ if (previous_rule)
+ previous_rule->next = midrule_action;
+ else
+ grammar = midrule_action;
+
+ /* End of the rule. */
+ previous_rule = symbol_list_new (NULL);
+ previous_rule->next = current_rule;
+
+ midrule_action->next = previous_rule;
+
+ /* Insert the dummy generated by that rule into this rule. */
+ ++nritems;
+ grammar_symbol_append (sdummy);
+}
+
+