Home | History | Annotate | Download | only in src
      1 /* Input parser for Bison
      2 
      3    Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000-2003, 2005-2007,
      4    2009-2012 Free Software Foundation, Inc.
      5 
      6    This file is part of Bison, the GNU Compiler Compiler.
      7 
      8    This program is free software: you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation, either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20 
     21 #include <config.h>
     22 #include "system.h"
     23 
     24 #include <quote.h>
     25 
     26 #include "complain.h"
     27 #include "conflicts.h"
     28 #include "files.h"
     29 #include "getargs.h"
     30 #include "gram.h"
     31 #include "muscle-tab.h"
     32 #include "reader.h"
     33 #include "symlist.h"
     34 #include "symtab.h"
     35 #include "scan-gram.h"
     36 #include "scan-code.h"
     37 
     38 static void prepare_percent_define_front_end_variables (void);
     39 static void check_and_convert_grammar (void);
     40 
     41 static symbol_list *grammar = NULL;
     42 static bool start_flag = false;
     43 merger_list *merge_functions;
     44 
     45 /* Was %union seen?  */
     46 bool union_seen = false;
     47 
     48 /* Was a tag seen?  */
     49 bool tag_seen = false;
     50 
     51 /* Should rules have a default precedence?  */
     52 bool default_prec = true;
     53 
     54 /*-----------------------.
     56 | Set the start symbol.  |
     57 `-----------------------*/
     58 
     59 void
     60 grammar_start_symbol_set (symbol *sym, location loc)
     61 {
     62   if (start_flag)
     63     complain_at (loc, _("multiple %s declarations"), "%start");
     64   else
     65     {
     66       start_flag = true;
     67       startsymbol = sym;
     68       startsymbol_location = loc;
     69     }
     70 }
     71 
     72 
     73 
     75 /*------------------------------------------------------------------------.
     76 | Return the merger index for a merging function named NAME.  Records the |
     77 | function, if new, in MERGER_LIST.                                       |
     78 `------------------------------------------------------------------------*/
     79 
     80 static int
     81 get_merge_function (uniqstr name)
     82 {
     83   merger_list *syms;
     84   merger_list head;
     85   int n;
     86 
     87   if (! glr_parser)
     88     return 0;
     89 
     90   head.next = merge_functions;
     91   for (syms = &head, n = 1; syms->next; syms = syms->next, n += 1)
     92     if (UNIQSTR_EQ (name, syms->next->name))
     93       break;
     94   if (syms->next == NULL)
     95     {
     96       syms->next = xmalloc (sizeof syms->next[0]);
     97       syms->next->name = uniqstr_new (name);
     98       /* After all symbol type declarations have been parsed, packgram invokes
     99 	 record_merge_function_type to set the type.  */
    100       syms->next->type = NULL;
    101       syms->next->next = NULL;
    102       merge_functions = head.next;
    103     }
    104   return n;
    105 }
    106 
    107 /*-------------------------------------------------------------------------.
    108 | For the existing merging function with index MERGER, record the result   |
    109 | type as TYPE as required by the lhs of the rule whose %merge declaration |
    110 | is at DECLARATION_LOC.                                                   |
    111 `-------------------------------------------------------------------------*/
    112 
    113 static void
    114 record_merge_function_type (int merger, uniqstr type, location declaration_loc)
    115 {
    116   int merger_find;
    117   merger_list *merge_function;
    118 
    119   if (merger <= 0)
    120     return;
    121 
    122   if (type == NULL)
    123     type = uniqstr_new ("");
    124 
    125   merger_find = 1;
    126   for (merge_function = merge_functions;
    127        merge_function != NULL && merger_find != merger;
    128        merge_function = merge_function->next)
    129     merger_find += 1;
    130   aver (merge_function != NULL && merger_find == merger);
    131   if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
    132     {
    133       unsigned indent = 0;
    134       complain_at_indent (declaration_loc, &indent,
    135                           _("result type clash on merge function %s: "
    136                             "<%s> != <%s>"),
    137                           quote (merge_function->name), type,
    138                           merge_function->type);
    139       indent += SUB_INDENT;
    140       complain_at_indent (merge_function->type_declaration_location, &indent,
    141                           _("previous declaration"));
    142    }
    143   merge_function->type = uniqstr_new (type);
    144   merge_function->type_declaration_location = declaration_loc;
    145 }
    146 
    147 /*--------------------------------------.
    148 | Free all merge-function definitions.	|
    149 `--------------------------------------*/
    150 
    151 void
    152 free_merger_functions (void)
    153 {
    154   merger_list *L0 = merge_functions;
    155   while (L0)
    156     {
    157       merger_list *L1 = L0->next;
    158       free (L0);
    159       L0 = L1;
    160     }
    161 }
    162 
    163 
    164 /*-------------------------------------------------------------------.
    166 | Parse the input grammar into a one symbol_list structure.  Each    |
    167 | rule is represented by a sequence of symbols: the left hand side   |
    168 | followed by the contents of the right hand side, followed by a     |
    169 | null pointer instead of a symbol to terminate the rule.  The next  |
    170 | symbol is the lhs of the following rule.                           |
    171 |                                                                    |
    172 | All actions are copied out, labelled by the rule number they apply |
    173 | to.                                                                |
    174 `-------------------------------------------------------------------*/
    175 
    176 /* The (currently) last symbol of GRAMMAR. */
    177 static symbol_list *grammar_end = NULL;
    178 
    179 /* Append SYM to the grammar.  */
    180 static symbol_list *
    181 grammar_symbol_append (symbol *sym, location loc)
    182 {
    183   symbol_list *p = symbol_list_sym_new (sym, loc);
    184 
    185   if (grammar_end)
    186     grammar_end->next = p;
    187   else
    188     grammar = p;
    189 
    190   grammar_end = p;
    191 
    192   /* A null SYM stands for an end of rule; it is not an actual
    193      part of it.  */
    194   if (sym)
    195     ++nritems;
    196 
    197   return p;
    198 }
    199 
    200 static void
    201 assign_named_ref (symbol_list *p, named_ref *name)
    202 {
    203   symbol *sym = p->content.sym;
    204 
    205   if (name->id == sym->tag)
    206     {
    207       warn_at (name->loc,
    208 	       _("duplicated symbol name for %s ignored"),
    209 	       quote (sym->tag));
    210       named_ref_free (name);
    211     }
    212   else
    213     p->named_ref = name;
    214 }
    215 
    216 
    217 /* The rule currently being defined, and the previous rule.
    218    CURRENT_RULE points to the first LHS of the current rule, while
    219    PREVIOUS_RULE_END points to the *end* of the previous rule (NULL).  */
    220 static symbol_list *current_rule = NULL;
    221 static symbol_list *previous_rule_end = NULL;
    222 
    223 
    224 /*----------------------------------------------.
    225 | Create a new rule for LHS in to the GRAMMAR.  |
    226 `----------------------------------------------*/
    227 
    228 void
    229 grammar_current_rule_begin (symbol *lhs, location loc,
    230 			    named_ref *lhs_name)
    231 {
    232   symbol_list* p;
    233 
    234   /* Start a new rule and record its lhs.  */
    235   ++nrules;
    236   previous_rule_end = grammar_end;
    237 
    238   p = grammar_symbol_append (lhs, loc);
    239   if (lhs_name)
    240     assign_named_ref (p, named_ref_copy (lhs_name));
    241 
    242   current_rule = grammar_end;
    243 
    244   /* Mark the rule's lhs as a nonterminal if not already so.  */
    245   if (lhs->class == unknown_sym)
    246     {
    247       lhs->class = nterm_sym;
    248       lhs->number = nvars;
    249       ++nvars;
    250     }
    251   else if (lhs->class == token_sym)
    252     complain_at (loc, _("rule given for %s, which is a token"), lhs->tag);
    253 }
    254 
    255 
    256 /*----------------------------------------------------------------------.
    257 | A symbol should be used if either:                                    |
    258 |   1. It has a destructor.                                             |
    259 |   2. The symbol is a mid-rule symbol (i.e., the generated LHS         |
    260 |      replacing a mid-rule action) that was assigned to or used, as in |
    261 |      "exp: { $$ = 1; } { $$ = $1; }".                                 |
    262 `----------------------------------------------------------------------*/
    263 
    264 static bool
    265 symbol_should_be_used (symbol_list const *s, bool *midrule_warning)
    266 {
    267   if (symbol_destructor_get (s->content.sym)->code)
    268     return true;
    269   if ((s->midrule && s->midrule->action_props.is_value_used)
    270       || (s->midrule_parent_rule
    271           && symbol_list_n_get (s->midrule_parent_rule,
    272                                 s->midrule_parent_rhs_index)
    273                ->action_props.is_value_used))
    274     {
    275       *midrule_warning = true;
    276       return true;
    277     }
    278   return false;
    279 }
    280 
    281 /*----------------------------------------------------------------.
    282 | Check that the rule R is properly defined.  For instance, there |
    283 | should be no type clash on the default action.                  |
    284 `----------------------------------------------------------------*/
    285 
    286 static void
    287 grammar_rule_check (const symbol_list *r)
    288 {
    289   /* Type check.
    290 
    291      If there is an action, then there is nothing we can do: the user
    292      is allowed to shoot herself in the foot.
    293 
    294      Don't worry about the default action if $$ is untyped, since $$'s
    295      value can't be used.  */
    296   if (!r->action_props.code && r->content.sym->type_name)
    297     {
    298       symbol *first_rhs = r->next->content.sym;
    299       /* If $$ is being set in default way, report if any type mismatch.  */
    300       if (first_rhs)
    301 	{
    302 	  char const *lhs_type = r->content.sym->type_name;
    303 	  const char *rhs_type =
    304 	    first_rhs->type_name ? first_rhs->type_name : "";
    305 	  if (!UNIQSTR_EQ (lhs_type, rhs_type))
    306 	    warn_at (r->location,
    307 		     _("type clash on default action: <%s> != <%s>"),
    308 		     lhs_type, rhs_type);
    309 	}
    310       /* Warn if there is no default for $$ but we need one.  */
    311       else
    312 	warn_at (r->location,
    313 		 _("empty rule for typed nonterminal, and no action"));
    314     }
    315 
    316   /* Check that symbol values that should be used are in fact used.  */
    317   {
    318     symbol_list const *l = r;
    319     int n = 0;
    320     for (; l && l->content.sym; l = l->next, ++n)
    321       {
    322         bool midrule_warning = false;
    323         if (!l->action_props.is_value_used
    324             && symbol_should_be_used (l, &midrule_warning)
    325             /* The default action, $$ = $1, `uses' both.  */
    326             && (r->action_props.code || (n != 0 && n != 1)))
    327           {
    328             void (*warn_at_ptr)(location, char const*, ...) =
    329               midrule_warning ? midrule_value_at : warn_at;
    330             if (n)
    331               warn_at_ptr (l->location, _("unused value: $%d"), n);
    332             else
    333               warn_at_ptr (l->location, _("unset value: $$"));
    334           }
    335       }
    336   }
    337 
    338   /* See comments in grammar_current_rule_prec_set for how POSIX
    339      mandates this complaint.  It's only for identifiers, so skip
    340      it for char literals and strings, which are always tokens.  */
    341   if (r->ruleprec
    342       && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
    343       && !r->ruleprec->declared && !r->ruleprec->prec)
    344     warn_at (r->location, _("token for %%prec is not defined: %s"),
    345              r->ruleprec->tag);
    346 }
    347 
    348 
    349 /*-------------------------------------.
    350 | End the currently being grown rule.  |
    351 `-------------------------------------*/
    352 
    353 void
    354 grammar_current_rule_end (location loc)
    355 {
    356   /* Put an empty link in the list to mark the end of this rule  */
    357   grammar_symbol_append (NULL, grammar_end->location);
    358   current_rule->location = loc;
    359 }
    360 
    361 
    362 /*-------------------------------------------------------------------.
    363 | The previous action turns out the be a mid-rule action.  Attach it |
    364 | to the current rule, i.e., create a dummy symbol, attach it this   |
    365 | mid-rule action, and append this dummy nonterminal to the current  |
    366 | rule.                                                              |
    367 `-------------------------------------------------------------------*/
    368 
    369 void
    370 grammar_midrule_action (void)
    371 {
    372   /* Since the action was written out with this rule's number, we must
    373      give the new rule this number by inserting the new rule before
    374      it.  */
    375 
    376   /* Make a DUMMY nonterminal, whose location is that of the midrule
    377      action.  Create the MIDRULE.  */
    378   location dummy_location = current_rule->action_props.location;
    379   symbol *dummy = dummy_symbol_get (dummy_location);
    380   symbol_list *midrule = symbol_list_sym_new (dummy, dummy_location);
    381 
    382   /* Remember named_ref of previous action. */
    383   named_ref *action_name = current_rule->action_props.named_ref;
    384 
    385   /* Make a new rule, whose body is empty, before the current one, so
    386      that the action just read can belong to it.  */
    387   ++nrules;
    388   ++nritems;
    389   /* Attach its location and actions to that of the DUMMY.  */
    390   midrule->location = dummy_location;
    391   code_props_rule_action_init (&midrule->action_props,
    392                                current_rule->action_props.code,
    393                                current_rule->action_props.location,
    394                                midrule, 0);
    395   code_props_none_init (&current_rule->action_props);
    396 
    397   if (previous_rule_end)
    398     previous_rule_end->next = midrule;
    399   else
    400     grammar = midrule;
    401 
    402   /* End the dummy's rule.  */
    403   midrule->next = symbol_list_sym_new (NULL, dummy_location);
    404   midrule->next->next = current_rule;
    405 
    406   previous_rule_end = midrule->next;
    407 
    408   /* Insert the dummy nonterminal replacing the midrule action into
    409      the current rule.  Bind it to its dedicated rule.  */
    410   grammar_current_rule_symbol_append (dummy, dummy_location,
    411                                       action_name);
    412   grammar_end->midrule = midrule;
    413   midrule->midrule_parent_rule = current_rule;
    414   midrule->midrule_parent_rhs_index = symbol_list_length (current_rule->next);
    415 }
    416 
    417 /* Set the precedence symbol of the current rule to PRECSYM. */
    418 
    419 void
    420 grammar_current_rule_prec_set (symbol *precsym, location loc)
    421 {
    422   /* POSIX says that any identifier is a nonterminal if it does not
    423      appear on the LHS of a grammar rule and is not defined by %token
    424      or by one of the directives that assigns precedence to a token.  We
    425      ignore this here because the only kind of identifier that POSIX
    426      allows to follow a %prec is a token and because assuming it's a
    427      token now can produce more logical error messages.  Nevertheless,
    428      grammar_rule_check does obey what we believe is the real intent of
    429      POSIX here: that an error be reported for any identifier that
    430      appears after %prec but that is not defined separately as a
    431      token.  */
    432   symbol_class_set (precsym, token_sym, loc, false);
    433   if (current_rule->ruleprec)
    434     complain_at (loc, _("only one %s allowed per rule"), "%prec");
    435   current_rule->ruleprec = precsym;
    436 }
    437 
    438 /* Attach dynamic precedence DPREC to the current rule. */
    439 
    440 void
    441 grammar_current_rule_dprec_set (int dprec, location loc)
    442 {
    443   if (! glr_parser)
    444     warn_at (loc, _("%s affects only GLR parsers"), "%dprec");
    445   if (dprec <= 0)
    446     complain_at (loc, _("%s must be followed by positive number"), "%dprec");
    447   else if (current_rule->dprec != 0)
    448     complain_at (loc, _("only one %s allowed per rule"), "%dprec");
    449   current_rule->dprec = dprec;
    450 }
    451 
    452 /* Attach a merge function NAME with argument type TYPE to current
    453    rule. */
    454 
    455 void
    456 grammar_current_rule_merge_set (uniqstr name, location loc)
    457 {
    458   if (! glr_parser)
    459     warn_at (loc, _("%s affects only GLR parsers"), "%merge");
    460   if (current_rule->merger != 0)
    461     complain_at (loc, _("only one %s allowed per rule"), "%merge");
    462   current_rule->merger = get_merge_function (name);
    463   current_rule->merger_declaration_location = loc;
    464 }
    465 
    466 /* Attach SYM to the current rule.  If needed, move the previous
    467    action as a mid-rule action.  */
    468 
    469 void
    470 grammar_current_rule_symbol_append (symbol *sym, location loc,
    471 				    named_ref *name)
    472 {
    473   symbol_list *p;
    474   if (current_rule->action_props.code)
    475     grammar_midrule_action ();
    476   p = grammar_symbol_append (sym, loc);
    477   if (name)
    478     assign_named_ref(p, name);
    479 }
    480 
    481 /* Attach an ACTION to the current rule.  */
    482 
    483 void
    484 grammar_current_rule_action_append (const char *action, location loc,
    485 				    named_ref *name)
    486 {
    487   if (current_rule->action_props.code)
    488     grammar_midrule_action ();
    489   /* After all symbol declarations have been parsed, packgram invokes
    490      code_props_translate_code.  */
    491   code_props_rule_action_init (&current_rule->action_props, action, loc,
    492                                current_rule, name);
    493 }
    494 
    495 
    496 /*---------------------------------------------------------------.
    498 | Convert the rules into the representation using RRHS, RLHS and |
    499 | RITEM.                                                         |
    500 `---------------------------------------------------------------*/
    501 
    502 static void
    503 packgram (void)
    504 {
    505   unsigned int itemno = 0;
    506   rule_number ruleno = 0;
    507   symbol_list *p = grammar;
    508 
    509   ritem = xnmalloc (nritems + 1, sizeof *ritem);
    510 
    511   /* This sentinel is used by build_relations in gram.c.  */
    512   *ritem++ = 0;
    513 
    514   rules = xnmalloc (nrules, sizeof *rules);
    515 
    516   while (p)
    517     {
    518       int rule_length = 0;
    519       symbol *ruleprec = p->ruleprec;
    520       record_merge_function_type (p->merger, p->content.sym->type_name,
    521 				  p->merger_declaration_location);
    522       rules[ruleno].user_number = ruleno;
    523       rules[ruleno].number = ruleno;
    524       rules[ruleno].lhs = p->content.sym;
    525       rules[ruleno].rhs = ritem + itemno;
    526       rules[ruleno].prec = NULL;
    527       rules[ruleno].dprec = p->dprec;
    528       rules[ruleno].merger = p->merger;
    529       rules[ruleno].precsym = NULL;
    530       rules[ruleno].location = p->location;
    531       rules[ruleno].useful = true;
    532       rules[ruleno].action = p->action_props.code;
    533       rules[ruleno].action_location = p->action_props.location;
    534 
    535       /* If the midrule's $$ is set or its $n is used, remove the `$' from the
    536 	 symbol name so that it's a user-defined symbol so that the default
    537 	 %destructor and %printer apply.  */
    538       if (p->midrule_parent_rule
    539           && (p->action_props.is_value_used
    540 	      || symbol_list_n_get (p->midrule_parent_rule,
    541 				    p->midrule_parent_rhs_index)
    542                    ->action_props.is_value_used))
    543 	p->content.sym->tag += 1;
    544 
    545       /* Don't check the generated rule 0.  It has no action, so some rhs
    546 	 symbols may appear unused, but the parsing algorithm ensures that
    547 	 %destructor's are invoked appropriately.  */
    548       if (p != grammar)
    549 	grammar_rule_check (p);
    550 
    551       for (p = p->next; p && p->content.sym; p = p->next)
    552 	{
    553 	  ++rule_length;
    554 
    555 	  /* Don't allow rule_length == INT_MAX, since that might
    556 	     cause confusion with strtol if INT_MAX == LONG_MAX.  */
    557 	  if (rule_length == INT_MAX)
    558 	      fatal_at (rules[ruleno].location, _("rule is too long"));
    559 
    560 	  /* item_number = symbol_number.
    561 	     But the former needs to contain more: negative rule numbers. */
    562 	  ritem[itemno++] =
    563             symbol_number_as_item_number (p->content.sym->number);
    564 	  /* A rule gets by default the precedence and associativity
    565 	     of its last token.  */
    566 	  if (p->content.sym->class == token_sym && default_prec)
    567 	    rules[ruleno].prec = p->content.sym;
    568 	}
    569 
    570       /* If this rule has a %prec,
    571          the specified symbol's precedence replaces the default.  */
    572       if (ruleprec)
    573 	{
    574 	  rules[ruleno].precsym = ruleprec;
    575 	  rules[ruleno].prec = ruleprec;
    576 	}
    577       /* An item ends by the rule number (negated).  */
    578       ritem[itemno++] = rule_number_as_item_number (ruleno);
    579       aver (itemno < ITEM_NUMBER_MAX);
    580       ++ruleno;
    581       aver (ruleno < RULE_NUMBER_MAX);
    582 
    583       if (p)
    584 	p = p->next;
    585     }
    586 
    587   aver (itemno == nritems);
    588 
    589   if (trace_flag & trace_sets)
    590     ritem_print (stderr);
    591 }
    592 
    593 /*------------------------------------------------------------------.
    595 | Read in the grammar specification and record it in the format     |
    596 | described in gram.h.  All actions are copied into ACTION_OBSTACK, |
    597 | in each case forming the body of a C function (YYACTION) which    |
    598 | contains a switch statement to decide which action to execute.    |
    599 `------------------------------------------------------------------*/
    600 
    601 void
    602 reader (void)
    603 {
    604   /* Initialize the symbol table.  */
    605   symbols_new ();
    606 
    607   /* Construct the accept symbol. */
    608   accept = symbol_get ("$accept", empty_location);
    609   accept->class = nterm_sym;
    610   accept->number = nvars++;
    611 
    612   /* Construct the error token */
    613   errtoken = symbol_get ("error", empty_location);
    614   errtoken->class = token_sym;
    615   errtoken->number = ntokens++;
    616 
    617   /* Construct a token that represents all undefined literal tokens.
    618      It is always token number 2.  */
    619   undeftoken = symbol_get ("$undefined", empty_location);
    620   undeftoken->class = token_sym;
    621   undeftoken->number = ntokens++;
    622 
    623   gram_in = xfopen (grammar_file, "r");
    624 
    625   gram__flex_debug = trace_flag & trace_scan;
    626   gram_debug = trace_flag & trace_parse;
    627   gram_scanner_initialize ();
    628   gram_parse ();
    629   prepare_percent_define_front_end_variables ();
    630 
    631   if (! complaint_issued)
    632     check_and_convert_grammar ();
    633 
    634   xfclose (gram_in);
    635 }
    636 
    637 static void
    638 prepare_percent_define_front_end_variables (void)
    639 {
    640   /* Set %define front-end variable defaults.  */
    641   muscle_percent_define_default ("lr.keep-unreachable-states", "false");
    642   {
    643     char *lr_type;
    644     /* IELR would be a better default, but LALR is historically the
    645        default.  */
    646     muscle_percent_define_default ("lr.type", "lalr");
    647     lr_type = muscle_percent_define_get ("lr.type");
    648     if (0 != strcmp (lr_type, "canonical-lr"))
    649       muscle_percent_define_default ("lr.default-reductions", "most");
    650     else
    651       muscle_percent_define_default ("lr.default-reductions", "accepting");
    652     free (lr_type);
    653   }
    654 
    655   /* Check %define front-end variables.  */
    656   {
    657     static char const * const values[] = {
    658       "lr.type", "lalr", "ielr", "canonical-lr", NULL,
    659       "lr.default-reductions", "most", "consistent", "accepting", NULL,
    660       NULL
    661     };
    662     muscle_percent_define_check_values (values);
    663   }
    664 }
    665 
    666 
    667 /*-------------------------------------------------------------.
    668 | Check the grammar that has just been read, and convert it to |
    669 | internal form.					       |
    670 `-------------------------------------------------------------*/
    671 
    672 static void
    673 check_and_convert_grammar (void)
    674 {
    675   /* Grammar has been read.  Do some checking.  */
    676   if (nrules == 0)
    677     fatal (_("no rules in the input grammar"));
    678 
    679   /* If the user did not define her ENDTOKEN, do it now. */
    680   if (!endtoken)
    681     {
    682       endtoken = symbol_get ("$end", empty_location);
    683       endtoken->class = token_sym;
    684       endtoken->number = 0;
    685       /* Value specified by POSIX.  */
    686       endtoken->user_token_number = 0;
    687     }
    688 
    689   /* Report any undefined symbols and consider them nonterminals.  */
    690   symbols_check_defined ();
    691 
    692   /* Find the start symbol if no %start.  */
    693   if (!start_flag)
    694     {
    695       symbol_list *node;
    696       for (node = grammar;
    697            node != NULL && symbol_is_dummy (node->content.sym);
    698            node = node->next)
    699         {
    700           for (node = node->next;
    701                node != NULL && node->content.sym != NULL;
    702                node = node->next)
    703             ;
    704         }
    705       aver (node != NULL);
    706       grammar_start_symbol_set (node->content.sym,
    707                                 node->content.sym->location);
    708     }
    709 
    710   /* Insert the initial rule, whose line is that of the first rule
    711      (not that of the start symbol):
    712 
    713      accept: %start EOF.  */
    714   {
    715     symbol_list *p = symbol_list_sym_new (accept, empty_location);
    716     p->location = grammar->location;
    717     p->next = symbol_list_sym_new (startsymbol, empty_location);
    718     p->next->next = symbol_list_sym_new (endtoken, empty_location);
    719     p->next->next->next = symbol_list_sym_new (NULL, empty_location);
    720     p->next->next->next->next = grammar;
    721     nrules += 1;
    722     nritems += 3;
    723     grammar = p;
    724   }
    725 
    726   aver (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars);
    727 
    728   /* Assign the symbols their symbol numbers.  Write #defines for the
    729      token symbols into FDEFINES if requested.  */
    730   symbols_pack ();
    731 
    732   /* Scan rule actions after invoking symbol_check_alias_consistency (in
    733      symbols_pack above) so that token types are set correctly before the rule
    734      action type checking.
    735 
    736      Before invoking grammar_rule_check (in packgram below) on any rule, make
    737      sure all actions have already been scanned in order to set `used' flags.
    738      Otherwise, checking that a midrule's $$ should be set will not always work
    739      properly because the check must forward-reference the midrule's parent
    740      rule.  For the same reason, all the `used' flags must be set before
    741      checking whether to remove `$' from any midrule symbol name (also in
    742      packgram).  */
    743   {
    744     symbol_list *sym;
    745     for (sym = grammar; sym; sym = sym->next)
    746       code_props_translate_code (&sym->action_props);
    747   }
    748 
    749   /* Convert the grammar into the format described in gram.h.  */
    750   packgram ();
    751 
    752   /* The grammar as a symbol_list is no longer needed. */
    753   symbol_list_free (grammar);
    754 }
    755