]> git.saurik.com Git - bison.git/blame - src/reader.c
Don't depend on C99 features.
[bison.git] / src / reader.c
CommitLineData
35dcf428 1/* Input parser for Bison
9c4637fa 2
05ac60f3 3 Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000, 2001, 2002, 2003,
f6857bbf 4 2005, 2006, 2007 Free Software Foundation, Inc.
1ff442ca 5
41aca2e0 6 This file is part of Bison, the GNU Compiler Compiler.
1ff442ca 7
41aca2e0
AD
8 Bison 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 2, or (at your option)
11 any later version.
1ff442ca 12
41aca2e0
AD
13 Bison 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.
1ff442ca 17
41aca2e0
AD
18 You should have received a copy of the GNU General Public License
19 along with Bison; see the file COPYING. If not, write to
0fb669f9
PE
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
1ff442ca 22
2cec9080 23#include <config.h>
1ff442ca 24#include "system.h"
17ee7397
PE
25
26#include <quotearg.h>
27
28#include "complain.h"
29#include "conflicts.h"
1ff442ca 30#include "files.h"
17ee7397 31#include "getargs.h"
1ff442ca 32#include "gram.h"
17ee7397 33#include "muscle_tab.h"
b2ca4022 34#include "reader.h"
17ee7397
PE
35#include "symlist.h"
36#include "symtab.h"
e9071366
AD
37#include "scan-gram.h"
38#include "scan-code.h"
1ff442ca 39
02d12d0d
PE
40static void check_and_convert_grammar (void);
41
17ee7397 42static symbol_list *grammar = NULL;
d0829076 43static bool start_flag = false;
676385e2 44merger_list *merge_functions;
1ff442ca 45
34f98f46 46/* Was %union seen? */
ddc8ede1
PE
47bool union_seen = false;
48
49/* Was a tag seen? */
50bool tag_seen = false;
39a06c25
PE
51
52/* Should rules have a default precedence? */
53bool default_prec = true;
0d533154 54\f
e9955c83
AD
55/*-----------------------.
56| Set the start symbol. |
57`-----------------------*/
1ff442ca 58
e9955c83 59void
a737b216 60grammar_start_symbol_set (symbol *sym, location loc)
1ff442ca
NF
61{
62 if (start_flag)
17ee7397 63 complain_at (loc, _("multiple %s declarations"), "%start");
943819bf
RS
64 else
65 {
d0829076 66 start_flag = true;
a737b216 67 startsymbol = sym;
17ee7397 68 startsymbol_location = loc;
943819bf 69 }
1ff442ca
NF
70}
71
a70083a3
AD
72\f
73
8ee5b538
JD
74/*------------------------------------------------------------------------.
75| Return the merger index for a merging function named NAME. Records the |
76| function, if new, in MERGER_LIST. |
77`------------------------------------------------------------------------*/
676385e2
PH
78
79static int
8ee5b538 80get_merge_function (uniqstr name)
676385e2
PH
81{
82 merger_list *syms;
83 merger_list head;
84 int n;
85
86 if (! glr_parser)
87 return 0;
88
676385e2 89 head.next = merge_functions;
affac613 90 for (syms = &head, n = 1; syms->next; syms = syms->next, n += 1)
17ee7397 91 if (UNIQSTR_EQ (name, syms->next->name))
676385e2 92 break;
a5d50994
AD
93 if (syms->next == NULL)
94 {
da2a7671 95 syms->next = xmalloc (sizeof syms->next[0]);
17ee7397 96 syms->next->name = uniqstr_new (name);
8ee5b538
JD
97 /* After all symbol type declarations have been parsed, packgram invokes
98 record_merge_function_type to set the type. */
99 syms->next->type = NULL;
a5d50994
AD
100 syms->next->next = NULL;
101 merge_functions = head.next;
102 }
676385e2
PH
103 return n;
104}
105
8ee5b538
JD
106/*-------------------------------------------------------------------------.
107| For the existing merging function with index MERGER, record the result |
108| type as TYPE as required by the lhs of the rule whose %merge declaration |
109| is at DECLARATION_LOC. |
110`-------------------------------------------------------------------------*/
111
112static void
113record_merge_function_type (int merger, uniqstr type, location declaration_loc)
114{
115 int merger_find;
116 merger_list *merge_function;
117
118 if (merger <= 0)
119 return;
120
121 if (type == NULL)
122 type = uniqstr_new ("");
123
124 merger_find = 1;
125 for (merge_function = merge_functions;
126 merge_function != NULL && merger_find != merger;
127 merge_function = merge_function->next)
128 merger_find += 1;
4f82b42a 129 aver (merge_function != NULL && merger_find == merger);
dd60572a 130 if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
8ee5b538 131 {
3b452f4e
JD
132 complain_at (declaration_loc,
133 _("result type clash on merge function `%s': <%s> != <%s>"),
134 merge_function->name, type, merge_function->type);
135 complain_at (merge_function->type_declaration_location,
136 _("previous declaration"));
8ee5b538 137 }
dd60572a
JD
138 merge_function->type = uniqstr_new (type);
139 merge_function->type_declaration_location = declaration_loc;
8ee5b538
JD
140}
141
676385e2
PH
142/*--------------------------------------.
143| Free all merge-function definitions. |
144`--------------------------------------*/
145
146void
147free_merger_functions (void)
148{
affac613
AD
149 merger_list *L0 = merge_functions;
150 while (L0)
676385e2
PH
151 {
152 merger_list *L1 = L0->next;
153 free (L0);
154 L0 = L1;
155 }
156}
157
a70083a3 158\f
107f7dfb 159/*-------------------------------------------------------------------.
17ee7397 160| Parse the input grammar into a one symbol_list structure. Each |
107f7dfb
AD
161| rule is represented by a sequence of symbols: the left hand side |
162| followed by the contents of the right hand side, followed by a |
163| null pointer instead of a symbol to terminate the rule. The next |
164| symbol is the lhs of the following rule. |
165| |
fdbcd8e2
AD
166| All actions are copied out, labelled by the rule number they apply |
167| to. |
107f7dfb 168`-------------------------------------------------------------------*/
1ff442ca 169
f6d0f937 170/* The (currently) last symbol of GRAMMAR. */
04098407 171static symbol_list *grammar_end = NULL;
f6d0f937 172
52328c6e 173/* Append SYM to the grammar. */
8f3596a6 174static void
17ee7397 175grammar_symbol_append (symbol *sym, location loc)
f6d0f937 176{
3be03b13 177 symbol_list *p = symbol_list_sym_new (sym, loc);
f6d0f937
AD
178
179 if (grammar_end)
180 grammar_end->next = p;
181 else
182 grammar = p;
183
184 grammar_end = p;
8f3596a6 185
e3233bf6 186 /* A null SYM stands for an end of rule; it is not an actual
8f3596a6
AD
187 part of it. */
188 if (sym)
189 ++nritems;
f6d0f937
AD
190}
191
8efe435c
AD
192/* The rule currently being defined, and the previous rule.
193 CURRENT_RULE points to the first LHS of the current rule, while
194 PREVIOUS_RULE_END points to the *end* of the previous rule (NULL). */
e256e17f 195static symbol_list *current_rule = NULL;
04098407 196static symbol_list *previous_rule_end = NULL;
da4160c3
AD
197
198
8efe435c
AD
199/*----------------------------------------------.
200| Create a new rule for LHS in to the GRAMMAR. |
201`----------------------------------------------*/
da4160c3 202
e9955c83 203void
8f3596a6 204grammar_current_rule_begin (symbol *lhs, location loc)
da4160c3 205{
da4160c3
AD
206 /* Start a new rule and record its lhs. */
207 ++nrules;
8efe435c 208 previous_rule_end = grammar_end;
17ee7397 209 grammar_symbol_append (lhs, loc);
da4160c3
AD
210 current_rule = grammar_end;
211
212 /* Mark the rule's lhs as a nonterminal if not already so. */
da4160c3
AD
213 if (lhs->class == unknown_sym)
214 {
215 lhs->class = nterm_sym;
216 lhs->number = nvars;
217 ++nvars;
218 }
219 else if (lhs->class == token_sym)
17ee7397 220 complain_at (loc, _("rule given for %s, which is a token"), lhs->tag);
da4160c3
AD
221}
222
affac613 223
d40ba6c2 224/*----------------------------------------------------------------------.
17bd8a73
JD
225| A symbol should be used if either: |
226| 1. It has a destructor. |
227| 2. --warnings=midrule-values and the symbol is a mid-rule symbol |
228| (i.e., the generated LHS replacing a mid-rule action) that was |
229| assigned to or used, as in "exp: { $$ = 1; } { $$ = $1; }". |
d40ba6c2 230`----------------------------------------------------------------------*/
84866159
AD
231
232static bool
d40ba6c2 233symbol_should_be_used (symbol_list const *s)
84866159 234{
95021767 235 if (symbol_destructor_get (s->content.sym)->code)
17bd8a73
JD
236 return true;
237 if (warnings_flag & warnings_midrule_values)
f6857bbf 238 return ((s->midrule && s->midrule->action_props.is_value_used)
b0f4c4ea
JD
239 || (s->midrule_parent_rule
240 && symbol_list_n_get (s->midrule_parent_rule,
f6857bbf
JD
241 s->midrule_parent_rhs_index)
242 ->action_props.is_value_used));
17bd8a73 243 return false;
84866159
AD
244}
245
8f3596a6
AD
246/*----------------------------------------------------------------.
247| Check that the rule R is properly defined. For instance, there |
248| should be no type clash on the default action. |
249`----------------------------------------------------------------*/
e9955c83
AD
250
251static void
8f3596a6 252grammar_rule_check (const symbol_list *r)
e9955c83 253{
affac613 254 /* Type check.
e9955c83 255
affac613
AD
256 If there is an action, then there is nothing we can do: the user
257 is allowed to shoot herself in the foot.
3f4c0f80 258
affac613
AD
259 Don't worry about the default action if $$ is untyped, since $$'s
260 value can't be used. */
f6857bbf 261 if (!r->action_props.code && r->content.sym->type_name)
e9955c83 262 {
3be03b13 263 symbol *first_rhs = r->next->content.sym;
affac613
AD
264 /* If $$ is being set in default way, report if any type mismatch. */
265 if (first_rhs)
266 {
3be03b13 267 char const *lhs_type = r->content.sym->type_name;
affac613
AD
268 const char *rhs_type =
269 first_rhs->type_name ? first_rhs->type_name : "";
270 if (!UNIQSTR_EQ (lhs_type, rhs_type))
8f3596a6 271 warn_at (r->location,
affac613
AD
272 _("type clash on default action: <%s> != <%s>"),
273 lhs_type, rhs_type);
274 }
275 /* Warn if there is no default for $$ but we need one. */
276 else
8f3596a6 277 warn_at (r->location,
affac613
AD
278 _("empty rule for typed nonterminal, and no action"));
279 }
e3233bf6 280
d40ba6c2 281 /* Check that symbol values that should be used are in fact used. */
8f3596a6 282 {
668c5d19 283 symbol_list const *l = r;
8f3596a6 284 int n = 0;
3be03b13 285 for (; l && l->content.sym; l = l->next, ++n)
f6857bbf 286 if (! (l->action_props.is_value_used
d40ba6c2 287 || !symbol_should_be_used (l)
8f3596a6 288 /* The default action, $$ = $1, `uses' both. */
f6857bbf 289 || (!r->action_props.code && (n == 0 || n == 1))))
668c5d19
PE
290 {
291 if (n)
292 warn_at (r->location, _("unused value: $%d"), n);
293 else
294 warn_at (r->location, _("unset value: $$"));
295 }
8f3596a6 296 }
e9955c83
AD
297}
298
299
8efe435c
AD
300/*-------------------------------------.
301| End the currently being grown rule. |
302`-------------------------------------*/
e9955c83
AD
303
304void
8f3596a6 305grammar_current_rule_end (location loc)
e9955c83
AD
306{
307 /* Put an empty link in the list to mark the end of this rule */
8efe435c 308 grammar_symbol_append (NULL, grammar_end->location);
17ee7397 309 current_rule->location = loc;
e9955c83
AD
310}
311
312
8efe435c
AD
313/*-------------------------------------------------------------------.
314| The previous action turns out the be a mid-rule action. Attach it |
315| to the current rule, i.e., create a dummy symbol, attach it this |
316| mid-rule action, and append this dummy nonterminal to the current |
317| rule. |
318`-------------------------------------------------------------------*/
1485e106 319
6b702268 320void
1485e106
AD
321grammar_midrule_action (void)
322{
323 /* Since the action was written out with this rule's number, we must
324 give the new rule this number by inserting the new rule before
325 it. */
326
8efe435c
AD
327 /* Make a DUMMY nonterminal, whose location is that of the midrule
328 action. Create the MIDRULE. */
f6857bbf 329 location dummy_location = current_rule->action_props.location;
17ee7397 330 symbol *dummy = dummy_symbol_get (dummy_location);
3be03b13 331 symbol_list *midrule = symbol_list_sym_new (dummy, dummy_location);
1485e106
AD
332
333 /* Make a new rule, whose body is empty, before the current one, so
334 that the action just read can belong to it. */
335 ++nrules;
336 ++nritems;
8efe435c
AD
337 /* Attach its location and actions to that of the DUMMY. */
338 midrule->location = dummy_location;
f6857bbf
JD
339 code_props_rule_action_init (&midrule->action_props,
340 current_rule->action_props.code,
341 current_rule->action_props.location,
342 midrule);
343 code_props_none_init (&current_rule->action_props);
1485e106 344
8efe435c
AD
345 if (previous_rule_end)
346 previous_rule_end->next = midrule;
1485e106 347 else
8efe435c 348 grammar = midrule;
1485e106 349
8efe435c 350 /* End the dummy's rule. */
3be03b13 351 midrule->next = symbol_list_sym_new (NULL, dummy_location);
84866159 352 midrule->next->next = current_rule;
1485e106 353
84866159 354 previous_rule_end = midrule->next;
1485e106 355
8efe435c 356 /* Insert the dummy nonterminal replacing the midrule action into
84866159 357 the current rule. Bind it to its dedicated rule. */
8efe435c 358 grammar_current_rule_symbol_append (dummy, dummy_location);
6ec2c0f2 359 grammar_end->midrule = midrule;
ffa4ba3a
JD
360 midrule->midrule_parent_rule = current_rule;
361 midrule->midrule_parent_rhs_index = symbol_list_length (current_rule->next);
1485e106
AD
362}
363
9af3fbce
AD
364/* Set the precedence symbol of the current rule to PRECSYM. */
365
e9955c83 366void
17ee7397 367grammar_current_rule_prec_set (symbol *precsym, location loc)
9af3fbce 368{
26b8a438 369 symbol_class_set (precsym, token_sym, loc, false);
9af3fbce 370 if (current_rule->ruleprec)
17ee7397 371 complain_at (loc, _("only one %s allowed per rule"), "%prec");
9af3fbce
AD
372 current_rule->ruleprec = precsym;
373}
374
676385e2
PH
375/* Attach dynamic precedence DPREC to the current rule. */
376
377void
17ee7397 378grammar_current_rule_dprec_set (int dprec, location loc)
676385e2
PH
379{
380 if (! glr_parser)
17ee7397 381 warn_at (loc, _("%s affects only GLR parsers"), "%dprec");
676385e2 382 if (dprec <= 0)
17ee7397 383 complain_at (loc, _("%s must be followed by positive number"), "%dprec");
39f41916 384 else if (current_rule->dprec != 0)
17ee7397 385 complain_at (loc, _("only one %s allowed per rule"), "%dprec");
676385e2
PH
386 current_rule->dprec = dprec;
387}
388
389/* Attach a merge function NAME with argument type TYPE to current
390 rule. */
391
392void
17ee7397 393grammar_current_rule_merge_set (uniqstr name, location loc)
676385e2
PH
394{
395 if (! glr_parser)
17ee7397 396 warn_at (loc, _("%s affects only GLR parsers"), "%merge");
39f41916 397 if (current_rule->merger != 0)
17ee7397 398 complain_at (loc, _("only one %s allowed per rule"), "%merge");
8ee5b538
JD
399 current_rule->merger = get_merge_function (name);
400 current_rule->merger_declaration_location = loc;
676385e2
PH
401}
402
17ee7397 403/* Attach SYM to the current rule. If needed, move the previous
2e047461
AD
404 action as a mid-rule action. */
405
e9955c83 406void
17ee7397 407grammar_current_rule_symbol_append (symbol *sym, location loc)
2e047461 408{
f6857bbf 409 if (current_rule->action_props.code)
2e047461 410 grammar_midrule_action ();
17ee7397 411 grammar_symbol_append (sym, loc);
2e047461
AD
412}
413
6b702268 414/* Attach an ACTION to the current rule. */
2e047461 415
e9955c83 416void
17ee7397 417grammar_current_rule_action_append (const char *action, location loc)
2e047461 418{
f6857bbf 419 if (current_rule->action_props.code)
381ecb06 420 grammar_midrule_action ();
ffa4ba3a 421 /* After all symbol declarations have been parsed, packgram invokes
f6857bbf
JD
422 code_props_translate_code. */
423 code_props_rule_action_init (&current_rule->action_props, action, loc,
424 current_rule);
2e047461
AD
425}
426
a70083a3 427\f
a70083a3
AD
428/*---------------------------------------------------------------.
429| Convert the rules into the representation using RRHS, RLHS and |
d9b739c3 430| RITEM. |
a70083a3 431`---------------------------------------------------------------*/
1ff442ca 432
4a120d45 433static void
118fb205 434packgram (void)
1ff442ca 435{
9222837b 436 unsigned int itemno = 0;
17ee7397
PE
437 rule_number ruleno = 0;
438 symbol_list *p = grammar;
1ff442ca 439
e9ad4aec
PE
440 ritem = xnmalloc (nritems + 1, sizeof *ritem);
441
442 /* This sentinel is used by build_relations in gram.c. */
443 *ritem++ = 0;
444
da2a7671 445 rules = xnmalloc (nrules, sizeof *rules);
1ff442ca 446
1ff442ca
NF
447 while (p)
448 {
e9071366 449 int rule_length = 0;
17ee7397 450 symbol *ruleprec = p->ruleprec;
3be03b13 451 record_merge_function_type (p->merger, p->content.sym->type_name,
8ee5b538 452 p->merger_declaration_location);
d7e1f00c 453 rules[ruleno].user_number = ruleno;
c3b407f4 454 rules[ruleno].number = ruleno;
3be03b13 455 rules[ruleno].lhs = p->content.sym;
99013900 456 rules[ruleno].rhs = ritem + itemno;
da2a7671
PE
457 rules[ruleno].prec = NULL;
458 rules[ruleno].dprec = p->dprec;
459 rules[ruleno].merger = p->merger;
460 rules[ruleno].precsym = NULL;
8efe435c 461 rules[ruleno].location = p->location;
b4afb6bb 462 rules[ruleno].useful = true;
f6857bbf
JD
463 rules[ruleno].action = p->action_props.code;
464 rules[ruleno].action_location = p->action_props.location;
1ff442ca 465
f91b1629
JD
466 /* If the midrule's $$ is set or its $n is used, remove the `$' from the
467 symbol name so that it's a user-defined symbol so that the default
468 %destructor and %printer apply. */
469 if (p->midrule_parent_rule
f6857bbf 470 && (p->action_props.is_value_used
b0f4c4ea 471 || symbol_list_n_get (p->midrule_parent_rule,
f6857bbf
JD
472 p->midrule_parent_rhs_index)
473 ->action_props.is_value_used))
f91b1629
JD
474 p->content.sym->tag += 1;
475
868d2d96
JD
476 /* Don't check the generated rule 0. It has no action, so some rhs
477 symbols may appear unused, but the parsing algorithm ensures that
478 %destructor's are invoked appropriately. */
479 if (p != grammar)
480 grammar_rule_check (p);
ffa4ba3a 481
3be03b13 482 for (p = p->next; p && p->content.sym; p = p->next)
1ff442ca 483 {
e9071366
AD
484 ++rule_length;
485
486 /* Don't allow rule_length == INT_MAX, since that might
487 cause confusion with strtol if INT_MAX == LONG_MAX. */
488 if (rule_length == INT_MAX)
489 fatal_at (rules[ruleno].location, _("rule is too long"));
490
17ee7397 491 /* item_number = symbol_number.
5fbb0954 492 But the former needs to contain more: negative rule numbers. */
3be03b13
JD
493 ritem[itemno++] =
494 symbol_number_as_item_number (p->content.sym->number);
1ff442ca 495 /* A rule gets by default the precedence and associativity
e9071366 496 of its last token. */
3be03b13
JD
497 if (p->content.sym->class == token_sym && default_prec)
498 rules[ruleno].prec = p->content.sym;
1ff442ca
NF
499 }
500
501 /* If this rule has a %prec,
a70083a3 502 the specified symbol's precedence replaces the default. */
1ff442ca
NF
503 if (ruleprec)
504 {
03b31c0c
AD
505 rules[ruleno].precsym = ruleprec;
506 rules[ruleno].prec = ruleprec;
1ff442ca 507 }
e9071366 508 /* An item ends by the rule number (negated). */
4b3d3a8e 509 ritem[itemno++] = rule_number_as_item_number (ruleno);
4f82b42a 510 aver (itemno < ITEM_NUMBER_MAX);
f3849179 511 ++ruleno;
4f82b42a 512 aver (ruleno < RULE_NUMBER_MAX);
1ff442ca 513
a70083a3
AD
514 if (p)
515 p = p->next;
1ff442ca
NF
516 }
517
4f82b42a 518 aver (itemno == nritems);
3067fbef 519
273a74fa 520 if (trace_flag & trace_sets)
3067fbef 521 ritem_print (stderr);
1ff442ca 522}
a70083a3 523\f
fdbcd8e2
AD
524/*------------------------------------------------------------------.
525| Read in the grammar specification and record it in the format |
526| described in gram.h. All actions are copied into ACTION_OBSTACK, |
527| in each case forming the body of a C function (YYACTION) which |
528| contains a switch statement to decide which action to execute. |
529`------------------------------------------------------------------*/
a70083a3
AD
530
531void
532reader (void)
533{
a70083a3 534 /* Initialize the symbol table. */
db8837cb 535 symbols_new ();
b6610515 536
88bce5a2
AD
537 /* Construct the accept symbol. */
538 accept = symbol_get ("$accept", empty_location);
539 accept->class = nterm_sym;
540 accept->number = nvars++;
30171f79 541
a70083a3 542 /* Construct the error token */
39f41916 543 errtoken = symbol_get ("error", empty_location);
d7020c20 544 errtoken->class = token_sym;
72a23c97 545 errtoken->number = ntokens++;
b6610515 546
a70083a3
AD
547 /* Construct a token that represents all undefined literal tokens.
548 It is always token number 2. */
88bce5a2 549 undeftoken = symbol_get ("$undefined", empty_location);
d7020c20 550 undeftoken->class = token_sym;
72a23c97 551 undeftoken->number = ntokens++;
a70083a3 552
2b81e969 553 gram_in = xfopen (grammar_file, "r");
e9955c83 554
473d0a75
AD
555 gram__flex_debug = trace_flag & trace_scan;
556 gram_debug = trace_flag & trace_parse;
e9071366 557 gram_scanner_initialize ();
78c3da9e 558 gram_parse ();
331dbc1b 559
02d12d0d
PE
560 if (! complaint_issued)
561 check_and_convert_grammar ();
562
563 xfclose (gram_in);
564}
565
b275314e 566
02d12d0d
PE
567/*-------------------------------------------------------------.
568| Check the grammar that has just been read, and convert it to |
569| internal form. |
570`-------------------------------------------------------------*/
571
572static void
573check_and_convert_grammar (void)
574{
575 /* Grammar has been read. Do some checking. */
e9955c83
AD
576 if (nrules == 0)
577 fatal (_("no rules in the input grammar"));
578
579 /* Report any undefined symbols and consider them nonterminals. */
580 symbols_check_defined ();
b7c49edf 581
88bce5a2
AD
582 /* If the user did not define her ENDTOKEN, do it now. */
583 if (!endtoken)
b7c49edf 584 {
88bce5a2
AD
585 endtoken = symbol_get ("$end", empty_location);
586 endtoken->class = token_sym;
587 endtoken->number = 0;
b7c49edf 588 /* Value specified by POSIX. */
88bce5a2 589 endtoken->user_token_number = 0;
b7c49edf
AD
590 }
591
4d7370cb
JD
592 /* Find the start symbol if no %start. */
593 if (!start_flag)
594 {
595 symbol_list *node;
596 for (node = grammar;
3be03b13 597 node != NULL && symbol_is_dummy (node->content.sym);
4d7370cb
JD
598 node = node->next)
599 {
600 for (node = node->next;
3be03b13 601 node != NULL && node->content.sym != NULL;
4d7370cb
JD
602 node = node->next)
603 ;
604 }
4f82b42a 605 aver (node != NULL);
3be03b13
JD
606 grammar_start_symbol_set (node->content.sym,
607 node->content.sym->location);
4d7370cb
JD
608 }
609
02d12d0d 610 /* Insert the initial rule, whose line is that of the first rule
e9955c83
AD
611 (not that of the start symbol):
612
88bce5a2 613 accept: %start EOF. */
e9955c83 614 {
3be03b13 615 symbol_list *p = symbol_list_sym_new (accept, empty_location);
8efe435c 616 p->location = grammar->location;
3be03b13
JD
617 p->next = symbol_list_sym_new (startsymbol, empty_location);
618 p->next->next = symbol_list_sym_new (endtoken, empty_location);
619 p->next->next->next = symbol_list_sym_new (NULL, empty_location);
e9955c83
AD
620 p->next->next->next->next = grammar;
621 nrules += 1;
622 nritems += 3;
623 grammar = p;
624 }
625
4f82b42a 626 aver (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars);
b0c4483e 627
a70083a3
AD
628 /* Assign the symbols their symbol numbers. Write #defines for the
629 token symbols into FDEFINES if requested. */
2f1afb73 630 symbols_pack ();
93ede233 631
574add85
JD
632 /* Scan rule actions after invoking symbol_check_alias_consistency (in
633 symbols_pack above) so that token types are set correctly before the rule
634 action type checking.
635
636 Before invoking grammar_rule_check (in packgram below) on any rule, make
637 sure all actions have already been scanned in order to set `used' flags.
638 Otherwise, checking that a midrule's $$ should be set will not always work
639 properly because the check must forward-reference the midrule's parent
640 rule. For the same reason, all the `used' flags must be set before
641 checking whether to remove `$' from any midrule symbol name (also in
642 packgram). */
14462c2b
JD
643 {
644 symbol_list *sym;
645 for (sym = grammar; sym; sym = sym->next)
646 code_props_translate_code (&sym->action_props);
647 }
574add85 648
a70083a3 649 /* Convert the grammar into the format described in gram.h. */
6d0ef4ec 650 packgram ();
8419d367 651
17ee7397 652 /* The grammar as a symbol_list is no longer needed. */
17bd8a73 653 symbol_list_free (grammar);
a70083a3 654}