]> git.saurik.com Git - bison.git/blame - src/reader.c
* src/reader.c (reader): Calling symbols_output once is enough.
[bison.git] / src / reader.c
CommitLineData
1ff442ca 1/* Input parser for bison
037ca2f1 2 Copyright 1984, 1986, 1989, 1992, 1998, 2000, 2001
a70083a3 3 Free Software Foundation, Inc.
1ff442ca 4
41aca2e0 5 This file is part of Bison, the GNU Compiler Compiler.
1ff442ca 6
41aca2e0
AD
7 Bison is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
1ff442ca 11
41aca2e0
AD
12 Bison is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
1ff442ca 16
41aca2e0
AD
17 You should have received a copy of the GNU General Public License
18 along with Bison; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
1ff442ca
NF
21
22
1ff442ca 23#include "system.h"
8c7ebe49 24#include "obstack.h"
2a91a95e
AD
25#include "quotearg.h"
26#include "quote.h"
ceed8467 27#include "getargs.h"
1ff442ca 28#include "files.h"
1ff442ca 29#include "symtab.h"
82b6d266 30#include "options.h"
1ff442ca
NF
31#include "lex.h"
32#include "gram.h"
a0f6b076 33#include "complain.h"
6c89f1c1 34#include "output.h"
b2ca4022 35#include "reader.h"
340ef489 36#include "conflicts.h"
11d82f03 37#include "muscle_tab.h"
1ff442ca 38
a70083a3
AD
39typedef struct symbol_list
40{
41 struct symbol_list *next;
42 bucket *sym;
b29b2ed5 43 int line;
a70083a3
AD
44 bucket *ruleprec;
45}
46symbol_list;
118fb205 47
1ff442ca 48int lineno;
1ff442ca 49char **tags;
d019d655 50short *user_toknums;
4a120d45
JT
51static symbol_list *grammar;
52static int start_flag;
53static bucket *startval;
1ff442ca
NF
54
55/* Nonzero if components of semantic values are used, implying
56 they must be unions. */
57static int value_components_used;
58
d7020c20
AD
59/* Nonzero if %union has been seen. */
60static int typed;
1ff442ca 61
d7020c20
AD
62/* Incremented for each %left, %right or %nonassoc seen */
63static int lastprec;
1ff442ca 64
1ff442ca 65static bucket *errtoken;
5b2e3c89 66static bucket *undeftoken;
b29b2ed5
AD
67
68
6255b435 69static symbol_list *
b29b2ed5
AD
70symbol_list_new (bucket *sym)
71{
72 symbol_list *res = XMALLOC (symbol_list, 1);
73 res->next = NULL;
74 res->sym = sym;
75 res->line = lineno;
76 res->ruleprec = NULL;
77 return res;
78}
79
0d533154 80\f
a70083a3 81
0d533154
AD
82/*===================\
83| Low level lexing. |
84\===================*/
943819bf
RS
85
86static void
118fb205 87skip_to_char (int target)
943819bf
RS
88{
89 int c;
90 if (target == '\n')
a0f6b076 91 complain (_(" Skipping to next \\n"));
943819bf 92 else
a0f6b076 93 complain (_(" Skipping to next %c"), target);
943819bf
RS
94
95 do
0d533154 96 c = skip_white_space ();
943819bf 97 while (c != target && c != EOF);
a083fbbf 98 if (c != EOF)
0d533154 99 ungetc (c, finput);
943819bf
RS
100}
101
102
0d533154
AD
103/*---------------------------------------------------------.
104| Read a signed integer from STREAM and return its value. |
105`---------------------------------------------------------*/
106
107static inline int
108read_signed_integer (FILE *stream)
109{
a70083a3
AD
110 int c = getc (stream);
111 int sign = 1;
112 int n = 0;
0d533154
AD
113
114 if (c == '-')
115 {
116 c = getc (stream);
117 sign = -1;
118 }
119
120 while (isdigit (c))
121 {
122 n = 10 * n + (c - '0');
123 c = getc (stream);
124 }
125
126 ungetc (c, stream);
127
128 return sign * n;
129}
130\f
79282c5a
AD
131/*--------------------------------------------------------------.
132| Get the data type (alternative in the union) of the value for |
133| symbol N in rule RULE. |
134`--------------------------------------------------------------*/
135
136static char *
b29b2ed5 137get_type_name (int n, symbol_list *rule)
79282c5a
AD
138{
139 int i;
140 symbol_list *rp;
141
142 if (n < 0)
143 {
144 complain (_("invalid $ value"));
145 return NULL;
146 }
147
148 rp = rule;
149 i = 0;
150
151 while (i < n)
152 {
153 rp = rp->next;
154 if (rp == NULL || rp->sym == NULL)
155 {
156 complain (_("invalid $ value"));
157 return NULL;
158 }
159 i++;
160 }
161
162 return rp->sym->type_name;
163}
164\f
337bab46
AD
165/*------------------------------------------------------------.
166| Dump the string from FIN to OOUT if non null. MATCH is the |
167| delimiter of the string (either ' or "). |
168`------------------------------------------------------------*/
ae3c3164
AD
169
170static inline void
b6610515 171copy_string2 (FILE *fin, struct obstack *oout, int match, int store)
ae3c3164
AD
172{
173 int c;
174
b6610515
RA
175 if (store)
176 obstack_1grow (oout, match);
8c7ebe49 177
4a120d45 178 c = getc (fin);
ae3c3164
AD
179
180 while (c != match)
181 {
182 if (c == EOF)
183 fatal (_("unterminated string at end of file"));
184 if (c == '\n')
185 {
a0f6b076 186 complain (_("unterminated string"));
4a120d45 187 ungetc (c, fin);
ae3c3164
AD
188 c = match; /* invent terminator */
189 continue;
190 }
191
337bab46 192 obstack_1grow (oout, c);
ae3c3164
AD
193
194 if (c == '\\')
195 {
4a120d45 196 c = getc (fin);
ae3c3164
AD
197 if (c == EOF)
198 fatal (_("unterminated string at end of file"));
337bab46 199 obstack_1grow (oout, c);
8c7ebe49 200
ae3c3164
AD
201 if (c == '\n')
202 lineno++;
203 }
204
a70083a3 205 c = getc (fin);
ae3c3164
AD
206 }
207
b6610515
RA
208 if (store)
209 obstack_1grow (oout, c);
210}
211
212/* FIXME. */
213
214static inline void
215copy_string (FILE *fin, struct obstack *oout, int match)
216{
217 copy_string2 (fin, oout, match, 1);
ae3c3164
AD
218}
219
b6610515
RA
220/* FIXME. */
221
222static inline void
223copy_identifier (FILE *fin, struct obstack *oout)
224{
225 int c;
226
227 while (isalnum (c = getc (fin)) || c == '_')
228 obstack_1grow (oout, c);
229
230 ungetc (c, fin);
231}
ae3c3164 232
337bab46
AD
233/*-----------------------------------------------------------------.
234| Dump the wannabee comment from IN to OUT1 and OUT2 (which can be |
235| NULL). In fact we just saw a `/', which might or might not be a |
236| comment. In any case, copy what we saw. |
237| |
238| OUT2 might be NULL. |
239`-----------------------------------------------------------------*/
ae3c3164
AD
240
241static inline void
337bab46 242copy_comment2 (FILE *fin, struct obstack *oout1, struct obstack *oout2)
ae3c3164
AD
243{
244 int cplus_comment;
a70083a3 245 int ended;
550a72a3
AD
246 int c;
247
248 /* We read a `/', output it. */
337bab46 249 obstack_1grow (oout1, '/');
896fe5c1
AD
250 if (oout2)
251 obstack_1grow (oout2, '/');
550a72a3
AD
252
253 switch ((c = getc (fin)))
254 {
255 case '/':
256 cplus_comment = 1;
257 break;
258 case '*':
259 cplus_comment = 0;
260 break;
261 default:
262 ungetc (c, fin);
263 return;
264 }
ae3c3164 265
337bab46 266 obstack_1grow (oout1, c);
896fe5c1
AD
267 if (oout2)
268 obstack_1grow (oout2, c);
550a72a3 269 c = getc (fin);
ae3c3164
AD
270
271 ended = 0;
272 while (!ended)
273 {
274 if (!cplus_comment && c == '*')
275 {
276 while (c == '*')
277 {
337bab46 278 obstack_1grow (oout1, c);
896fe5c1
AD
279 if (oout2)
280 obstack_1grow (oout2, c);
550a72a3 281 c = getc (fin);
ae3c3164
AD
282 }
283
284 if (c == '/')
285 {
337bab46 286 obstack_1grow (oout1, c);
896fe5c1
AD
287 if (oout2)
288 obstack_1grow (oout2, c);
ae3c3164
AD
289 ended = 1;
290 }
291 }
292 else if (c == '\n')
293 {
294 lineno++;
337bab46 295 obstack_1grow (oout1, c);
896fe5c1
AD
296 if (oout2)
297 obstack_1grow (oout2, c);
ae3c3164
AD
298 if (cplus_comment)
299 ended = 1;
300 else
550a72a3 301 c = getc (fin);
ae3c3164
AD
302 }
303 else if (c == EOF)
304 fatal (_("unterminated comment"));
305 else
306 {
337bab46 307 obstack_1grow (oout1, c);
896fe5c1
AD
308 if (oout2)
309 obstack_1grow (oout2, c);
550a72a3 310 c = getc (fin);
ae3c3164
AD
311 }
312 }
313}
314
315
550a72a3
AD
316/*-------------------------------------------------------------------.
317| Dump the comment (actually the current string starting with a `/') |
337bab46 318| from FIN to OOUT. |
550a72a3 319`-------------------------------------------------------------------*/
27821bff
AD
320
321static inline void
337bab46 322copy_comment (FILE *fin, struct obstack *oout)
27821bff 323{
337bab46 324 copy_comment2 (fin, oout, NULL);
27821bff
AD
325}
326
327
a70083a3 328/*-----------------------------------------------------------------.
337bab46 329| FIN is pointing to a location (i.e., a `@'). Output to OOUT a |
a70083a3
AD
330| reference to this location. STACK_OFFSET is the number of values |
331| in the current rule so far, which says where to find `$0' with |
332| respect to the top of the stack. |
333`-----------------------------------------------------------------*/
1ff442ca 334
a70083a3 335static inline void
337bab46 336copy_at (FILE *fin, struct obstack *oout, int stack_offset)
1ff442ca 337{
a70083a3 338 int c;
1ff442ca 339
a70083a3
AD
340 c = getc (fin);
341 if (c == '$')
1ff442ca 342 {
ff4423cc 343 obstack_sgrow (oout, "yyloc");
89cab50d 344 locations_flag = 1;
a70083a3
AD
345 }
346 else if (isdigit (c) || c == '-')
347 {
348 int n;
1ff442ca 349
a70083a3
AD
350 ungetc (c, fin);
351 n = read_signed_integer (fin);
943819bf 352
337bab46 353 obstack_fgrow1 (oout, "yylsp[%d]", n - stack_offset);
89cab50d 354 locations_flag = 1;
1ff442ca 355 }
a70083a3 356 else
ff4a34be
AD
357 {
358 char buf[] = "@c";
359 buf[1] = c;
360 complain (_("%s is invalid"), quote (buf));
361 }
1ff442ca 362}
79282c5a
AD
363
364
365/*-------------------------------------------------------------------.
366| FIN is pointing to a wannabee semantic value (i.e., a `$'). |
367| |
368| Possible inputs: $[<TYPENAME>]($|integer) |
369| |
337bab46 370| Output to OOUT a reference to this semantic value. STACK_OFFSET is |
79282c5a
AD
371| the number of values in the current rule so far, which says where |
372| to find `$0' with respect to the top of the stack. |
373`-------------------------------------------------------------------*/
374
375static inline void
337bab46 376copy_dollar (FILE *fin, struct obstack *oout,
79282c5a
AD
377 symbol_list *rule, int stack_offset)
378{
379 int c = getc (fin);
b0ce6046 380 const char *type_name = NULL;
79282c5a 381
f282676b 382 /* Get the type name if explicit. */
79282c5a
AD
383 if (c == '<')
384 {
f282676b 385 read_type_name (fin);
79282c5a
AD
386 type_name = token_buffer;
387 value_components_used = 1;
79282c5a
AD
388 c = getc (fin);
389 }
390
391 if (c == '$')
392 {
ff4423cc 393 obstack_sgrow (oout, "yyval");
8c7ebe49 394
79282c5a
AD
395 if (!type_name)
396 type_name = get_type_name (0, rule);
397 if (type_name)
337bab46 398 obstack_fgrow1 (oout, ".%s", type_name);
79282c5a
AD
399 if (!type_name && typed)
400 complain (_("$$ of `%s' has no declared type"),
401 rule->sym->tag);
402 }
403 else if (isdigit (c) || c == '-')
404 {
405 int n;
406 ungetc (c, fin);
407 n = read_signed_integer (fin);
408
409 if (!type_name && n > 0)
410 type_name = get_type_name (n, rule);
411
337bab46 412 obstack_fgrow1 (oout, "yyvsp[%d]", n - stack_offset);
8c7ebe49 413
79282c5a 414 if (type_name)
337bab46 415 obstack_fgrow1 (oout, ".%s", type_name);
79282c5a
AD
416 if (!type_name && typed)
417 complain (_("$%d of `%s' has no declared type"),
418 n, rule->sym->tag);
419 }
420 else
421 {
422 char buf[] = "$c";
423 buf[1] = c;
424 complain (_("%s is invalid"), quote (buf));
425 }
426}
a70083a3
AD
427\f
428/*-------------------------------------------------------------------.
429| Copy the contents of a `%{ ... %}' into the definitions file. The |
430| `%{' has already been read. Return after reading the `%}'. |
431`-------------------------------------------------------------------*/
1ff442ca 432
4a120d45 433static void
118fb205 434copy_definition (void)
1ff442ca 435{
a70083a3 436 int c;
ae3c3164 437 /* -1 while reading a character if prev char was %. */
a70083a3 438 int after_percent;
1ff442ca 439
b6610515 440#if 0
89cab50d 441 if (!no_lines_flag)
25b222fa
MA
442 {
443 obstack_fgrow2 (&attrs_obstack, muscle_find ("linef"),
342b8b6e 444 lineno, quotearg_style (c_quoting_style,
25b222fa
MA
445 muscle_find("filename")));
446 }
b6610515 447#endif
1ff442ca
NF
448
449 after_percent = 0;
450
ae3c3164 451 c = getc (finput);
1ff442ca
NF
452
453 for (;;)
454 {
455 switch (c)
456 {
457 case '\n':
dd60faec 458 obstack_1grow (&attrs_obstack, c);
1ff442ca
NF
459 lineno++;
460 break;
461
462 case '%':
a70083a3 463 after_percent = -1;
1ff442ca 464 break;
a083fbbf 465
1ff442ca
NF
466 case '\'':
467 case '"':
337bab46 468 copy_string (finput, &attrs_obstack, c);
1ff442ca
NF
469 break;
470
471 case '/':
337bab46 472 copy_comment (finput, &attrs_obstack);
1ff442ca
NF
473 break;
474
475 case EOF:
a70083a3 476 fatal ("%s", _("unterminated `%{' definition"));
1ff442ca
NF
477
478 default:
dd60faec 479 obstack_1grow (&attrs_obstack, c);
1ff442ca
NF
480 }
481
a70083a3 482 c = getc (finput);
1ff442ca
NF
483
484 if (after_percent)
485 {
486 if (c == '}')
487 return;
dd60faec 488 obstack_1grow (&attrs_obstack, '%');
1ff442ca
NF
489 }
490 after_percent = 0;
1ff442ca 491 }
1ff442ca
NF
492}
493
494
d7020c20
AD
495/*-------------------------------------------------------------------.
496| Parse what comes after %token or %nterm. For %token, WHAT_IS is |
497| token_sym and WHAT_IS_NOT is nterm_sym. For %nterm, the arguments |
498| are reversed. |
499`-------------------------------------------------------------------*/
1ff442ca 500
4a120d45 501static void
d7020c20 502parse_token_decl (symbol_class what_is, symbol_class what_is_not)
1ff442ca 503{
342b8b6e
AD
504 token_t token = tok_undef;
505 char *typename = NULL;
1ff442ca 506
1e9798d5
AD
507 /* The symbol being defined. */
508 struct bucket *symbol = NULL;
509
510 /* After `%token' and `%nterm', any number of symbols maybe be
511 defined. */
1ff442ca
NF
512 for (;;)
513 {
e6011337
JT
514 int tmp_char = ungetc (skip_white_space (), finput);
515
1e9798d5
AD
516 /* `%' (for instance from `%token', or from `%%' etc.) is the
517 only valid means to end this declaration. */
e6011337 518 if (tmp_char == '%')
1ff442ca 519 return;
e6011337 520 if (tmp_char == EOF)
a0f6b076 521 fatal (_("Premature EOF after %s"), token_buffer);
e6011337 522
a70083a3 523 token = lex ();
511e79b3 524 if (token == tok_comma)
943819bf
RS
525 {
526 symbol = NULL;
527 continue;
528 }
511e79b3 529 if (token == tok_typename)
1ff442ca 530 {
95e36146 531 typename = xstrdup (token_buffer);
1ff442ca 532 value_components_used = 1;
943819bf
RS
533 symbol = NULL;
534 }
511e79b3 535 else if (token == tok_identifier && *symval->tag == '\"' && symbol)
943819bf 536 {
8e03724b
AD
537 if (symval->alias)
538 warn (_("symbol `%s' used more than once as a literal string"),
539 symval->tag);
540 else if (symbol->alias)
541 warn (_("symbol `%s' given more than one literal string"),
542 symbol->tag);
543 else
544 {
545 symval->class = token_sym;
546 symval->type_name = typename;
547 symval->user_token_number = symbol->user_token_number;
548 symbol->user_token_number = SALIAS;
549 symval->alias = symbol;
550 symbol->alias = symval;
551 /* symbol and symval combined are only one symbol */
552 nsyms--;
553 }
8e03724b 554 symbol = NULL;
1ff442ca 555 }
511e79b3 556 else if (token == tok_identifier)
1ff442ca
NF
557 {
558 int oldclass = symval->class;
943819bf 559 symbol = symval;
1ff442ca 560
943819bf 561 if (symbol->class == what_is_not)
a0f6b076 562 complain (_("symbol %s redefined"), symbol->tag);
943819bf 563 symbol->class = what_is;
d7020c20 564 if (what_is == nterm_sym && oldclass != nterm_sym)
943819bf 565 symbol->value = nvars++;
1ff442ca
NF
566
567 if (typename)
568 {
943819bf
RS
569 if (symbol->type_name == NULL)
570 symbol->type_name = typename;
a70083a3 571 else if (strcmp (typename, symbol->type_name) != 0)
a0f6b076 572 complain (_("type redeclaration for %s"), symbol->tag);
1ff442ca
NF
573 }
574 }
511e79b3 575 else if (symbol && token == tok_number)
a70083a3 576 {
943819bf 577 symbol->user_token_number = numval;
a70083a3 578 }
1ff442ca 579 else
943819bf 580 {
a0f6b076 581 complain (_("`%s' is invalid in %s"),
b29b2ed5
AD
582 token_buffer,
583 (what_is == token_sym) ? "%token" : "%nterm");
a70083a3 584 skip_to_char ('%');
943819bf 585 }
1ff442ca
NF
586 }
587
588}
589
1ff442ca 590
d7020c20
AD
591/*------------------------------.
592| Parse what comes after %start |
593`------------------------------*/
1ff442ca 594
4a120d45 595static void
118fb205 596parse_start_decl (void)
1ff442ca
NF
597{
598 if (start_flag)
27821bff 599 complain (_("multiple %s declarations"), "%start");
511e79b3 600 if (lex () != tok_identifier)
27821bff 601 complain (_("invalid %s declaration"), "%start");
943819bf
RS
602 else
603 {
604 start_flag = 1;
605 startval = symval;
606 }
1ff442ca
NF
607}
608
a70083a3
AD
609/*-----------------------------------------------------------.
610| read in a %type declaration and record its information for |
611| get_type_name to access |
612`-----------------------------------------------------------*/
613
614static void
615parse_type_decl (void)
616{
a70083a3
AD
617 char *name;
618
511e79b3 619 if (lex () != tok_typename)
a70083a3
AD
620 {
621 complain ("%s", _("%type declaration has no <typename>"));
622 skip_to_char ('%');
623 return;
624 }
625
95e36146 626 name = xstrdup (token_buffer);
a70083a3
AD
627
628 for (;;)
629 {
f17bcd1f 630 token_t t;
a70083a3
AD
631 int tmp_char = ungetc (skip_white_space (), finput);
632
633 if (tmp_char == '%')
634 return;
635 if (tmp_char == EOF)
636 fatal (_("Premature EOF after %s"), token_buffer);
637
638 t = lex ();
639
640 switch (t)
1ff442ca
NF
641 {
642
511e79b3
AD
643 case tok_comma:
644 case tok_semicolon:
1ff442ca
NF
645 break;
646
511e79b3 647 case tok_identifier:
1ff442ca
NF
648 if (symval->type_name == NULL)
649 symval->type_name = name;
a70083a3 650 else if (strcmp (name, symval->type_name) != 0)
a0f6b076 651 complain (_("type redeclaration for %s"), symval->tag);
1ff442ca
NF
652
653 break;
654
655 default:
a0f6b076
AD
656 complain (_("invalid %%type declaration due to item: %s"),
657 token_buffer);
a70083a3 658 skip_to_char ('%');
1ff442ca
NF
659 }
660 }
661}
662
663
664
d7020c20
AD
665/*----------------------------------------------------------------.
666| Read in a %left, %right or %nonassoc declaration and record its |
667| information. |
668`----------------------------------------------------------------*/
1ff442ca 669
4a120d45 670static void
d7020c20 671parse_assoc_decl (associativity assoc)
1ff442ca 672{
a70083a3
AD
673 char *name = NULL;
674 int prev = 0;
1ff442ca 675
a70083a3 676 lastprec++; /* Assign a new precedence level, never 0. */
1ff442ca 677
1ff442ca
NF
678 for (;;)
679 {
f17bcd1f 680 token_t t;
e6011337 681 int tmp_char = ungetc (skip_white_space (), finput);
1ff442ca 682
e6011337 683 if (tmp_char == '%')
1ff442ca 684 return;
e6011337 685 if (tmp_char == EOF)
a0f6b076 686 fatal (_("Premature EOF after %s"), token_buffer);
1ff442ca 687
a70083a3 688 t = lex ();
1ff442ca
NF
689
690 switch (t)
691 {
511e79b3 692 case tok_typename:
95e36146 693 name = xstrdup (token_buffer);
1ff442ca
NF
694 break;
695
511e79b3 696 case tok_comma:
1ff442ca
NF
697 break;
698
511e79b3 699 case tok_identifier:
1ff442ca 700 if (symval->prec != 0)
a0f6b076 701 complain (_("redefining precedence of %s"), symval->tag);
1ff442ca
NF
702 symval->prec = lastprec;
703 symval->assoc = assoc;
d7020c20 704 if (symval->class == nterm_sym)
a0f6b076 705 complain (_("symbol %s redefined"), symval->tag);
d7020c20 706 symval->class = token_sym;
1ff442ca 707 if (name)
a70083a3 708 { /* record the type, if one is specified */
1ff442ca
NF
709 if (symval->type_name == NULL)
710 symval->type_name = name;
a70083a3 711 else if (strcmp (name, symval->type_name) != 0)
a0f6b076 712 complain (_("type redeclaration for %s"), symval->tag);
1ff442ca
NF
713 }
714 break;
715
511e79b3
AD
716 case tok_number:
717 if (prev == tok_identifier)
a70083a3 718 {
1ff442ca 719 symval->user_token_number = numval;
a70083a3
AD
720 }
721 else
722 {
723 complain (_
724 ("invalid text (%s) - number should be after identifier"),
725token_buffer);
726 skip_to_char ('%');
727 }
1ff442ca
NF
728 break;
729
511e79b3 730 case tok_semicolon:
1ff442ca
NF
731 return;
732
733 default:
a0f6b076 734 complain (_("unexpected item: %s"), token_buffer);
a70083a3 735 skip_to_char ('%');
1ff442ca
NF
736 }
737
738 prev = t;
1ff442ca
NF
739 }
740}
741
742
743
dd60faec 744/*--------------------------------------------------------------.
180d45ba
PB
745| Copy the union declaration into the stype muscle |
746| (and fdefines), where it is made into the definition of |
747| YYSTYPE, the type of elements of the parser value stack. |
dd60faec 748`--------------------------------------------------------------*/
1ff442ca 749
4a120d45 750static void
118fb205 751parse_union_decl (void)
1ff442ca 752{
a70083a3
AD
753 int c;
754 int count = 0;
180d45ba 755 struct obstack union_obstack;
5f7e0832
AD
756 const char *prologue = "\
757#ifndef YYSTYPE\n\
758typedef union";
759 const char *epilogue = "\
760 yystype;\n\
761# define YYSTYPE yystype\n\
762#endif\n";
1ff442ca
NF
763
764 if (typed)
27821bff 765 complain (_("multiple %s declarations"), "%union");
1ff442ca
NF
766
767 typed = 1;
768
f6ec6d13
AD
769 /* FIXME: I'm worried: are you sure attrs_obstack is properly
770 filled? */
5f7e0832
AD
771 /* I don't see any reasons to keep this line, because we should
772 create a special skeleton for this option. */
180d45ba 773 if (no_lines_flag)
dd60faec 774 obstack_1grow (&attrs_obstack, '\n');
342b8b6e 775
180d45ba
PB
776 obstack_init (&union_obstack);
777 obstack_sgrow (&union_obstack, "union");
896fe5c1 778 if (defines_flag)
5f7e0832 779 obstack_sgrow (&defines_obstack, prologue);
1ff442ca 780
27821bff 781 c = getc (finput);
1ff442ca
NF
782
783 while (c != EOF)
784 {
342b8b6e
AD
785 /* If C contains '/', it is output by copy_comment (). */
786 if (c != '/')
787 {
f6ec6d13 788 obstack_1grow (&union_obstack, c);
342b8b6e
AD
789 if (defines_flag)
790 obstack_1grow (&defines_obstack, c);
791 }
1ff442ca
NF
792
793 switch (c)
794 {
795 case '\n':
796 lineno++;
797 break;
798
799 case '/':
180d45ba 800 copy_comment2 (finput, &defines_obstack, &union_obstack);
1ff442ca
NF
801 break;
802
1ff442ca
NF
803 case '{':
804 count++;
805 break;
806
807 case '}':
808 if (count == 0)
27821bff 809 complain (_("unmatched %s"), "`}'");
1ff442ca 810 count--;
943819bf 811 if (count <= 0)
1ff442ca 812 {
896fe5c1 813 if (defines_flag)
5f7e0832 814 obstack_sgrow (&defines_obstack, epilogue);
1ff442ca 815 /* JF don't choke on trailing semi */
27821bff
AD
816 c = skip_white_space ();
817 if (c != ';')
a70083a3 818 ungetc (c, finput);
180d45ba
PB
819 obstack_1grow (&union_obstack, 0);
820 muscle_insert ("stype", obstack_finish (&union_obstack));
1ff442ca
NF
821 return;
822 }
823 }
824
27821bff 825 c = getc (finput);
1ff442ca 826 }
180d45ba 827
1ff442ca
NF
828}
829
d7020c20
AD
830
831/*-------------------------------------------------------.
832| Parse the declaration %expect N which says to expect N |
833| shift-reduce conflicts. |
834`-------------------------------------------------------*/
1ff442ca 835
4a120d45 836static void
118fb205 837parse_expect_decl (void)
1ff442ca 838{
131e2fef 839 int c = skip_white_space ();
1ff442ca
NF
840 ungetc (c, finput);
841
131e2fef 842 if (!isdigit (c))
79282c5a 843 complain (_("argument of %%expect is not an integer"));
131e2fef
AD
844 else
845 expected_conflicts = read_signed_integer (finput);
1ff442ca
NF
846}
847
a70083a3
AD
848
849/*-------------------------------------------------------------------.
850| Parse what comes after %thong. the full syntax is |
851| |
852| %thong <type> token number literal |
853| |
854| the <type> or number may be omitted. The number specifies the |
855| user_token_number. |
856| |
857| Two symbols are entered in the table, one for the token symbol and |
858| one for the literal. Both are given the <type>, if any, from the |
859| declaration. The ->user_token_number of the first is SALIAS and |
860| the ->user_token_number of the second is set to the number, if |
861| any, from the declaration. The two symbols are linked via |
862| pointers in their ->alias fields. |
863| |
864| During OUTPUT_DEFINES_TABLE, the symbol is reported thereafter, |
865| only the literal string is retained it is the literal string that |
866| is output to yytname |
867`-------------------------------------------------------------------*/
868
869static void
870parse_thong_decl (void)
7b306f52 871{
f17bcd1f 872 token_t token;
a70083a3
AD
873 struct bucket *symbol;
874 char *typename = 0;
6b7e85b9 875 int usrtoknum = SUNDEF;
7b306f52 876
a70083a3 877 token = lex (); /* fetch typename or first token */
511e79b3 878 if (token == tok_typename)
7b306f52 879 {
95e36146 880 typename = xstrdup (token_buffer);
a70083a3
AD
881 value_components_used = 1;
882 token = lex (); /* fetch first token */
7b306f52 883 }
7b306f52 884
a70083a3 885 /* process first token */
7b306f52 886
511e79b3 887 if (token != tok_identifier)
a70083a3
AD
888 {
889 complain (_("unrecognized item %s, expected an identifier"),
890 token_buffer);
891 skip_to_char ('%');
892 return;
7b306f52 893 }
d7020c20 894 symval->class = token_sym;
a70083a3
AD
895 symval->type_name = typename;
896 symval->user_token_number = SALIAS;
897 symbol = symval;
7b306f52 898
a70083a3 899 token = lex (); /* get number or literal string */
1ff442ca 900
511e79b3 901 if (token == tok_number)
943819bf 902 {
a70083a3
AD
903 usrtoknum = numval;
904 token = lex (); /* okay, did number, now get literal */
943819bf 905 }
1ff442ca 906
a70083a3 907 /* process literal string token */
1ff442ca 908
511e79b3 909 if (token != tok_identifier || *symval->tag != '\"')
1ff442ca 910 {
a70083a3
AD
911 complain (_("expected string constant instead of %s"), token_buffer);
912 skip_to_char ('%');
913 return;
1ff442ca 914 }
d7020c20 915 symval->class = token_sym;
a70083a3
AD
916 symval->type_name = typename;
917 symval->user_token_number = usrtoknum;
1ff442ca 918
a70083a3
AD
919 symval->alias = symbol;
920 symbol->alias = symval;
1ff442ca 921
79282c5a
AD
922 /* symbol and symval combined are only one symbol. */
923 nsyms--;
a70083a3 924}
3cef001a 925
b6610515 926static void
11d82f03 927parse_muscle_decl (void)
b6610515
RA
928{
929 int ch = ungetc (skip_white_space (), finput);
11d82f03
MA
930 char* muscle_key;
931 char* muscle_value;
b6610515
RA
932
933 /* Read key. */
934 if (!isalpha (ch) && ch != '_')
935 {
936 complain (_("invalid %s declaration"), "%define");
937 skip_to_char ('%');
938 return;
939 }
11d82f03
MA
940 copy_identifier (finput, &muscle_obstack);
941 obstack_1grow (&muscle_obstack, 0);
942 muscle_key = obstack_finish (&muscle_obstack);
342b8b6e 943
b6610515
RA
944 /* Read value. */
945 ch = skip_white_space ();
946 if (ch != '"')
947 {
948 ungetc (ch, finput);
949 if (ch != EOF)
950 {
951 complain (_("invalid %s declaration"), "%define");
952 skip_to_char ('%');
953 return;
954 }
955 else
956 fatal (_("Premature EOF after %s"), "\"");
957 }
11d82f03
MA
958 copy_string2 (finput, &muscle_obstack, '"', 0);
959 obstack_1grow (&muscle_obstack, 0);
960 muscle_value = obstack_finish (&muscle_obstack);
b6610515 961
b6610515 962 /* Store the (key, value) pair in the environment. */
11d82f03 963 muscle_insert (muscle_key, muscle_value);
b6610515
RA
964}
965
2ba3b73c 966
426cf563
MA
967
968/*---------------------------------.
a870c567 969| Parse a double quoted parameter. |
426cf563
MA
970`---------------------------------*/
971
972static const char *
973parse_dquoted_param (const char *from)
974{
975 struct obstack param_obstack;
976 const char *param = NULL;
977 int c;
978
979 obstack_init (&param_obstack);
980 c = skip_white_space ();
981
982 if (c != '"')
983 {
984 complain (_("invalid %s declaration"), from);
985 ungetc (c, finput);
986 skip_to_char ('%');
987 return NULL;
988 }
989
990 for (;;)
991 {
992 if (literalchar (NULL, &c, '\"'))
993 obstack_1grow (&param_obstack, c);
994 else
995 break;
996 }
a870c567 997
426cf563
MA
998 obstack_1grow (&param_obstack, '\0');
999 param = obstack_finish (&param_obstack);
1000
1001 if (c != '"' || strlen (param) == 0)
1002 {
1003 complain (_("invalid %s declaration"), from);
1004 if (c != '"')
1005 ungetc (c, finput);
1006 skip_to_char ('%');
1007 return NULL;
1008 }
1009
1010 return param;
1011}
1012
2ba3b73c
MA
1013/*----------------------------------.
1014| Parse what comes after %skeleton. |
1015`----------------------------------*/
1016
a870c567 1017static void
2ba3b73c
MA
1018parse_skel_decl (void)
1019{
426cf563 1020 skeleton = parse_dquoted_param ("%skeleton");
2ba3b73c
MA
1021}
1022
a70083a3
AD
1023/*----------------------------------------------------------------.
1024| Read from finput until `%%' is seen. Discard the `%%'. Handle |
1025| any `%' declarations, and copy the contents of any `%{ ... %}' |
dd60faec 1026| groups to ATTRS_OBSTACK. |
a70083a3 1027`----------------------------------------------------------------*/
1ff442ca 1028
4a120d45 1029static void
a70083a3 1030read_declarations (void)
1ff442ca 1031{
a70083a3 1032 for (;;)
1ff442ca 1033 {
951366c1 1034 int c = skip_white_space ();
1ff442ca 1035
a70083a3
AD
1036 if (c == '%')
1037 {
951366c1 1038 token_t tok = parse_percent_token ();
1ff442ca 1039
a70083a3 1040 switch (tok)
943819bf 1041 {
511e79b3 1042 case tok_two_percents:
a70083a3 1043 return;
1ff442ca 1044
511e79b3 1045 case tok_percent_left_curly:
a70083a3
AD
1046 copy_definition ();
1047 break;
1ff442ca 1048
511e79b3 1049 case tok_token:
d7020c20 1050 parse_token_decl (token_sym, nterm_sym);
a70083a3 1051 break;
1ff442ca 1052
511e79b3 1053 case tok_nterm:
d7020c20 1054 parse_token_decl (nterm_sym, token_sym);
a70083a3 1055 break;
1ff442ca 1056
511e79b3 1057 case tok_type:
a70083a3
AD
1058 parse_type_decl ();
1059 break;
1ff442ca 1060
511e79b3 1061 case tok_start:
a70083a3
AD
1062 parse_start_decl ();
1063 break;
118fb205 1064
511e79b3 1065 case tok_union:
a70083a3
AD
1066 parse_union_decl ();
1067 break;
1ff442ca 1068
511e79b3 1069 case tok_expect:
a70083a3
AD
1070 parse_expect_decl ();
1071 break;
6deb4447 1072
511e79b3 1073 case tok_thong:
a70083a3
AD
1074 parse_thong_decl ();
1075 break;
d7020c20 1076
511e79b3 1077 case tok_left:
d7020c20 1078 parse_assoc_decl (left_assoc);
a70083a3 1079 break;
1ff442ca 1080
511e79b3 1081 case tok_right:
d7020c20 1082 parse_assoc_decl (right_assoc);
a70083a3 1083 break;
1ff442ca 1084
511e79b3 1085 case tok_nonassoc:
d7020c20 1086 parse_assoc_decl (non_assoc);
a70083a3 1087 break;
1ff442ca 1088
b6610515 1089 case tok_define:
11d82f03 1090 parse_muscle_decl ();
b6610515 1091 break;
342b8b6e 1092
2ba3b73c
MA
1093 case tok_skel:
1094 parse_skel_decl ();
1095 break;
b6610515 1096
511e79b3 1097 case tok_noop:
a70083a3 1098 break;
1ff442ca 1099
951366c1
AD
1100 case tok_stropt:
1101 case tok_intopt:
1102 case tok_obsolete:
951366c1
AD
1103 abort ();
1104 break;
1105
e0c40012 1106 case tok_illegal:
a70083a3
AD
1107 default:
1108 complain (_("unrecognized: %s"), token_buffer);
1109 skip_to_char ('%');
1110 }
1111 }
1112 else if (c == EOF)
1113 fatal (_("no input grammar"));
1114 else
1115 {
ff4a34be
AD
1116 char buf[] = "c";
1117 buf[0] = c;
1118 complain (_("unknown character: %s"), quote (buf));
a70083a3 1119 skip_to_char ('%');
1ff442ca 1120 }
1ff442ca 1121 }
1ff442ca 1122}
a70083a3
AD
1123\f
1124/*-------------------------------------------------------------------.
1125| Assuming that a `{' has just been seen, copy everything up to the |
1126| matching `}' into the actions file. STACK_OFFSET is the number of |
1127| values in the current rule so far, which says where to find `$0' |
1128| with respect to the top of the stack. |
1129`-------------------------------------------------------------------*/
1ff442ca 1130
4a120d45 1131static void
79282c5a 1132copy_action (symbol_list *rule, int stack_offset)
1ff442ca 1133{
a70083a3 1134 int c;
a70083a3 1135 int count;
1ff442ca
NF
1136
1137 /* offset is always 0 if parser has already popped the stack pointer */
41aca2e0
AD
1138 if (semantic_parser)
1139 stack_offset = 0;
1ff442ca 1140
25b222fa 1141 obstack_fgrow1 (&action_obstack, "\ncase %d:\n", nrules);
8c7ebe49 1142
89cab50d 1143 if (!no_lines_flag)
8c7ebe49 1144 {
25b222fa 1145 obstack_fgrow2 (&action_obstack, muscle_find ("linef"),
342b8b6e 1146 lineno, quotearg_style (c_quoting_style,
25b222fa 1147 muscle_find ("filename")));
8c7ebe49
AD
1148 }
1149 obstack_1grow (&action_obstack, '{');
1ff442ca
NF
1150
1151 count = 1;
a70083a3 1152 c = getc (finput);
1ff442ca
NF
1153
1154 while (count > 0)
1155 {
1156 while (c != '}')
a70083a3
AD
1157 {
1158 switch (c)
1ff442ca
NF
1159 {
1160 case '\n':
8c7ebe49 1161 obstack_1grow (&action_obstack, c);
1ff442ca
NF
1162 lineno++;
1163 break;
1164
1165 case '{':
8c7ebe49 1166 obstack_1grow (&action_obstack, c);
1ff442ca
NF
1167 count++;
1168 break;
1169
1170 case '\'':
1171 case '"':
337bab46 1172 copy_string (finput, &action_obstack, c);
1ff442ca
NF
1173 break;
1174
1175 case '/':
337bab46 1176 copy_comment (finput, &action_obstack);
1ff442ca
NF
1177 break;
1178
1179 case '$':
337bab46 1180 copy_dollar (finput, &action_obstack,
8c7ebe49 1181 rule, stack_offset);
1ff442ca
NF
1182 break;
1183
1184 case '@':
337bab46 1185 copy_at (finput, &action_obstack,
8c7ebe49 1186 stack_offset);
6666f98f 1187 break;
1ff442ca
NF
1188
1189 case EOF:
27821bff 1190 fatal (_("unmatched %s"), "`{'");
1ff442ca
NF
1191
1192 default:
8c7ebe49 1193 obstack_1grow (&action_obstack, c);
a70083a3
AD
1194 }
1195
1196 c = getc (finput);
1197 }
1198
1199 /* above loop exits when c is '}' */
1200
1201 if (--count)
1202 {
8c7ebe49 1203 obstack_1grow (&action_obstack, c);
a70083a3
AD
1204 c = getc (finput);
1205 }
1206 }
1207
ff4423cc 1208 obstack_sgrow (&action_obstack, ";\n break;}");
a70083a3
AD
1209}
1210\f
1211/*-------------------------------------------------------------------.
1212| After `%guard' is seen in the input file, copy the actual guard |
1213| into the guards file. If the guard is followed by an action, copy |
1214| that into the actions file. STACK_OFFSET is the number of values |
1215| in the current rule so far, which says where to find `$0' with |
1216| respect to the top of the stack, for the simple parser in which |
1217| the stack is not popped until after the guard is run. |
1218`-------------------------------------------------------------------*/
1219
1220static void
79282c5a 1221copy_guard (symbol_list *rule, int stack_offset)
a70083a3
AD
1222{
1223 int c;
a70083a3 1224 int count;
a70083a3
AD
1225 int brace_flag = 0;
1226
1227 /* offset is always 0 if parser has already popped the stack pointer */
1228 if (semantic_parser)
1229 stack_offset = 0;
1230
ea5607fd 1231 obstack_fgrow1 (&guard_obstack, "\ncase %d:\n", nrules);
89cab50d 1232 if (!no_lines_flag)
25b222fa 1233 obstack_fgrow2 (&guard_obstack, muscle_find ("linef"),
682d48cd 1234 lineno, quotearg_style (c_quoting_style,
11d82f03 1235 muscle_find ("filename")));
ea5607fd 1236 obstack_1grow (&guard_obstack, '{');
a70083a3
AD
1237
1238 count = 0;
1239 c = getc (finput);
1240
1241 while (brace_flag ? (count > 0) : (c != ';'))
1242 {
1243 switch (c)
1244 {
1245 case '\n':
ea5607fd 1246 obstack_1grow (&guard_obstack, c);
a70083a3
AD
1247 lineno++;
1248 break;
1249
1250 case '{':
ea5607fd 1251 obstack_1grow (&guard_obstack, c);
a70083a3
AD
1252 brace_flag = 1;
1253 count++;
1254 break;
1255
1256 case '}':
ea5607fd 1257 obstack_1grow (&guard_obstack, c);
a70083a3
AD
1258 if (count > 0)
1259 count--;
1260 else
1261 {
1262 complain (_("unmatched %s"), "`}'");
1263 c = getc (finput); /* skip it */
1264 }
1265 break;
1266
1267 case '\'':
1268 case '"':
337bab46 1269 copy_string (finput, &guard_obstack, c);
a70083a3
AD
1270 break;
1271
1272 case '/':
337bab46 1273 copy_comment (finput, &guard_obstack);
a70083a3
AD
1274 break;
1275
1276 case '$':
337bab46 1277 copy_dollar (finput, &guard_obstack, rule, stack_offset);
a70083a3 1278 break;
1ff442ca 1279
a70083a3 1280 case '@':
337bab46 1281 copy_at (finput, &guard_obstack, stack_offset);
a70083a3 1282 break;
1ff442ca 1283
a70083a3
AD
1284 case EOF:
1285 fatal ("%s", _("unterminated %guard clause"));
1ff442ca 1286
a70083a3 1287 default:
ea5607fd 1288 obstack_1grow (&guard_obstack, c);
1ff442ca 1289 }
a70083a3
AD
1290
1291 if (c != '}' || count != 0)
1292 c = getc (finput);
1ff442ca
NF
1293 }
1294
a70083a3
AD
1295 c = skip_white_space ();
1296
ff4423cc 1297 obstack_sgrow (&guard_obstack, ";\n break;}");
a70083a3
AD
1298 if (c == '{')
1299 copy_action (rule, stack_offset);
1300 else if (c == '=')
1301 {
1302 c = getc (finput); /* why not skip_white_space -wjh */
1303 if (c == '{')
1304 copy_action (rule, stack_offset);
1305 }
1306 else
1307 ungetc (c, finput);
1ff442ca 1308}
a70083a3
AD
1309\f
1310
a70083a3
AD
1311/*-------------------------------------------------------------------.
1312| Generate a dummy symbol, a nonterminal, whose name cannot conflict |
1313| with the user's names. |
1314`-------------------------------------------------------------------*/
1ff442ca 1315
4a120d45 1316static bucket *
118fb205 1317gensym (void)
1ff442ca 1318{
274d42ce
AD
1319 /* Incremented for each generated symbol */
1320 static int gensym_count = 0;
1321 static char buf[256];
1322
a70083a3 1323 bucket *sym;
1ff442ca 1324
274d42ce
AD
1325 sprintf (buf, "@%d", ++gensym_count);
1326 token_buffer = buf;
a70083a3 1327 sym = getsym (token_buffer);
d7020c20 1328 sym->class = nterm_sym;
1ff442ca 1329 sym->value = nvars++;
36281465 1330 return sym;
1ff442ca
NF
1331}
1332
a70083a3
AD
1333#if 0
1334/*------------------------------------------------------------------.
1335| read in a %type declaration and record its information for |
1336| get_type_name to access. This is unused. It is only called from |
1337| the #if 0 part of readgram |
1338`------------------------------------------------------------------*/
1339
1340static int
1341get_type (void)
1342{
1343 int k;
f17bcd1f 1344 token_t token;
a70083a3
AD
1345 char *name;
1346
f17bcd1f 1347 token = lex ();
a70083a3 1348
f17bcd1f 1349 if (token != tok_typename)
a70083a3
AD
1350 {
1351 complain (_("invalid %s declaration"), "%type");
1352 return t;
1353 }
1354
95e36146 1355 name = xstrdup (token_buffer);
a70083a3
AD
1356
1357 for (;;)
1358 {
f17bcd1f 1359 token = lex ();
a70083a3 1360
f17bcd1f 1361 switch (token)
a70083a3 1362 {
511e79b3 1363 case tok_semicolon:
a70083a3
AD
1364 return lex ();
1365
511e79b3 1366 case tok_comma:
a70083a3
AD
1367 break;
1368
511e79b3 1369 case tok_identifier:
a70083a3
AD
1370 if (symval->type_name == NULL)
1371 symval->type_name = name;
1372 else if (strcmp (name, symval->type_name) != 0)
1373 complain (_("type redeclaration for %s"), symval->tag);
1374
1375 break;
1376
1377 default:
f17bcd1f 1378 return token;
a70083a3
AD
1379 }
1380 }
1381}
1ff442ca 1382
a70083a3
AD
1383#endif
1384\f
1385/*------------------------------------------------------------------.
1386| Parse the input grammar into a one symbol_list structure. Each |
1387| rule is represented by a sequence of symbols: the left hand side |
1388| followed by the contents of the right hand side, followed by a |
1389| null pointer instead of a symbol to terminate the rule. The next |
1390| symbol is the lhs of the following rule. |
1391| |
1392| All guards and actions are copied out to the appropriate files, |
1393| labelled by the rule number they apply to. |
1394`------------------------------------------------------------------*/
1ff442ca 1395
4a120d45 1396static void
118fb205 1397readgram (void)
1ff442ca 1398{
f17bcd1f 1399 token_t t;
a70083a3
AD
1400 bucket *lhs = NULL;
1401 symbol_list *p;
1402 symbol_list *p1;
1403 bucket *bp;
1ff442ca 1404
ff4a34be
AD
1405 /* Points to first symbol_list of current rule. its symbol is the
1406 lhs of the rule. */
1407 symbol_list *crule;
1408 /* Points to the symbol_list preceding crule. */
1409 symbol_list *crule1;
1ff442ca
NF
1410
1411 p1 = NULL;
1412
a70083a3 1413 t = lex ();
1ff442ca 1414
511e79b3 1415 while (t != tok_two_percents && t != tok_eof)
1ff442ca 1416 {
511e79b3 1417 if (t == tok_identifier || t == tok_bar)
1ff442ca 1418 {
89cab50d 1419 int action_flag = 0;
ff4a34be
AD
1420 /* Number of symbols in rhs of this rule so far */
1421 int rulelength = 0;
1ff442ca
NF
1422 int xactions = 0; /* JF for error checking */
1423 bucket *first_rhs = 0;
1424
511e79b3 1425 if (t == tok_identifier)
1ff442ca
NF
1426 {
1427 lhs = symval;
943819bf
RS
1428
1429 if (!start_flag)
1430 {
1431 startval = lhs;
1432 start_flag = 1;
1433 }
a083fbbf 1434
a70083a3 1435 t = lex ();
511e79b3 1436 if (t != tok_colon)
943819bf 1437 {
a0f6b076 1438 complain (_("ill-formed rule: initial symbol not followed by colon"));
a70083a3 1439 unlex (t);
943819bf 1440 }
1ff442ca
NF
1441 }
1442
511e79b3 1443 if (nrules == 0 && t == tok_bar)
1ff442ca 1444 {
a0f6b076 1445 complain (_("grammar starts with vertical bar"));
943819bf 1446 lhs = symval; /* BOGUS: use a random symval */
1ff442ca 1447 }
1ff442ca
NF
1448 /* start a new rule and record its lhs. */
1449
1450 nrules++;
1451 nitems++;
1452
b29b2ed5 1453 p = symbol_list_new (lhs);
1ff442ca
NF
1454
1455 crule1 = p1;
1456 if (p1)
1457 p1->next = p;
1458 else
1459 grammar = p;
1460
1461 p1 = p;
1462 crule = p;
1463
1464 /* mark the rule's lhs as a nonterminal if not already so. */
1465
d7020c20 1466 if (lhs->class == unknown_sym)
1ff442ca 1467 {
d7020c20 1468 lhs->class = nterm_sym;
1ff442ca
NF
1469 lhs->value = nvars;
1470 nvars++;
1471 }
d7020c20 1472 else if (lhs->class == token_sym)
a0f6b076 1473 complain (_("rule given for %s, which is a token"), lhs->tag);
1ff442ca
NF
1474
1475 /* read the rhs of the rule. */
1476
1477 for (;;)
1478 {
a70083a3 1479 t = lex ();
511e79b3 1480 if (t == tok_prec)
943819bf 1481 {
a70083a3 1482 t = lex ();
943819bf 1483 crule->ruleprec = symval;
a70083a3 1484 t = lex ();
943819bf 1485 }
1ff442ca 1486
511e79b3 1487 if (!(t == tok_identifier || t == tok_left_curly))
a70083a3 1488 break;
1ff442ca
NF
1489
1490 /* If next token is an identifier, see if a colon follows it.
a70083a3 1491 If one does, exit this rule now. */
511e79b3 1492 if (t == tok_identifier)
1ff442ca 1493 {
a70083a3 1494 bucket *ssave;
f17bcd1f 1495 token_t t1;
1ff442ca
NF
1496
1497 ssave = symval;
a70083a3
AD
1498 t1 = lex ();
1499 unlex (t1);
1ff442ca 1500 symval = ssave;
511e79b3 1501 if (t1 == tok_colon)
a70083a3 1502 break;
1ff442ca 1503
a70083a3 1504 if (!first_rhs) /* JF */
1ff442ca
NF
1505 first_rhs = symval;
1506 /* Not followed by colon =>
1507 process as part of this rule's rhs. */
1508 }
1509
1510 /* If we just passed an action, that action was in the middle
a70083a3
AD
1511 of a rule, so make a dummy rule to reduce it to a
1512 non-terminal. */
89cab50d 1513 if (action_flag)
1ff442ca 1514 {
f282676b
AD
1515 /* Since the action was written out with this rule's
1516 number, we must give the new rule this number by
1517 inserting the new rule before it. */
1ff442ca
NF
1518
1519 /* Make a dummy nonterminal, a gensym. */
b29b2ed5 1520 bucket *sdummy = gensym ();
1ff442ca 1521
2ca209c1
AD
1522 /* Make a new rule, whose body is empty, before the
1523 current one, so that the action just read can
1524 belong to it. */
1ff442ca
NF
1525 nrules++;
1526 nitems++;
b29b2ed5 1527 p = symbol_list_new (sdummy);
2ca209c1
AD
1528 /* Attach its lineno to that of the host rule. */
1529 p->line = crule->line;
1ff442ca
NF
1530 if (crule1)
1531 crule1->next = p;
a70083a3
AD
1532 else
1533 grammar = p;
b29b2ed5
AD
1534 /* End of the rule. */
1535 crule1 = symbol_list_new (NULL);
1ff442ca
NF
1536 crule1->next = crule;
1537
e41dc700
AD
1538 p->next = crule1;
1539
f282676b
AD
1540 /* Insert the dummy generated by that rule into this
1541 rule. */
1ff442ca 1542 nitems++;
b29b2ed5 1543 p = symbol_list_new (sdummy);
1ff442ca
NF
1544 p1->next = p;
1545 p1 = p;
1546
89cab50d 1547 action_flag = 0;
1ff442ca
NF
1548 }
1549
511e79b3 1550 if (t == tok_identifier)
1ff442ca
NF
1551 {
1552 nitems++;
b29b2ed5 1553 p = symbol_list_new (symval);
1ff442ca
NF
1554 p1->next = p;
1555 p1 = p;
1556 }
a70083a3 1557 else /* handle an action. */
1ff442ca 1558 {
a70083a3 1559 copy_action (crule, rulelength);
89cab50d 1560 action_flag = 1;
1ff442ca
NF
1561 xactions++; /* JF */
1562 }
1563 rulelength++;
a70083a3 1564 } /* end of read rhs of rule */
1ff442ca
NF
1565
1566 /* Put an empty link in the list to mark the end of this rule */
b29b2ed5 1567 p = symbol_list_new (NULL);
1ff442ca
NF
1568 p1->next = p;
1569 p1 = p;
1570
511e79b3 1571 if (t == tok_prec)
1ff442ca 1572 {
a0f6b076 1573 complain (_("two @prec's in a row"));
a70083a3 1574 t = lex ();
1ff442ca 1575 crule->ruleprec = symval;
a70083a3 1576 t = lex ();
1ff442ca 1577 }
511e79b3 1578 if (t == tok_guard)
1ff442ca 1579 {
a70083a3 1580 if (!semantic_parser)
ff4a34be 1581 complain (_("%%guard present but %%semantic_parser not specified"));
1ff442ca 1582
a70083a3
AD
1583 copy_guard (crule, rulelength);
1584 t = lex ();
1ff442ca 1585 }
511e79b3 1586 else if (t == tok_left_curly)
1ff442ca 1587 {
a70083a3 1588 /* This case never occurs -wjh */
89cab50d 1589 if (action_flag)
a0f6b076 1590 complain (_("two actions at end of one rule"));
a70083a3 1591 copy_action (crule, rulelength);
89cab50d 1592 action_flag = 1;
943819bf 1593 xactions++; /* -wjh */
a70083a3 1594 t = lex ();
1ff442ca 1595 }
a0f6b076 1596 /* If $$ is being set in default way, report if any type
6666f98f
AD
1597 mismatch. */
1598 else if (!xactions
a70083a3 1599 && first_rhs && lhs->type_name != first_rhs->type_name)
1ff442ca 1600 {
6666f98f
AD
1601 if (lhs->type_name == 0
1602 || first_rhs->type_name == 0
a70083a3 1603 || strcmp (lhs->type_name, first_rhs->type_name))
a0f6b076
AD
1604 complain (_("type clash (`%s' `%s') on default action"),
1605 lhs->type_name ? lhs->type_name : "",
a70083a3 1606 first_rhs->type_name ? first_rhs->type_name : "");
1ff442ca
NF
1607 }
1608 /* Warn if there is no default for $$ but we need one. */
1609 else if (!xactions && !first_rhs && lhs->type_name != 0)
a0f6b076 1610 complain (_("empty rule for typed nonterminal, and no action"));
511e79b3 1611 if (t == tok_semicolon)
a70083a3 1612 t = lex ();
a083fbbf 1613 }
943819bf 1614#if 0
a70083a3 1615 /* these things can appear as alternatives to rules. */
943819bf
RS
1616/* NO, they cannot.
1617 a) none of the documentation allows them
1618 b) most of them scan forward until finding a next %
1619 thus they may swallow lots of intervening rules
1620*/
511e79b3 1621 else if (t == tok_token)
1ff442ca 1622 {
d7020c20 1623 parse_token_decl (token_sym, nterm_sym);
a70083a3 1624 t = lex ();
1ff442ca 1625 }
511e79b3 1626 else if (t == tok_nterm)
1ff442ca 1627 {
d7020c20 1628 parse_token_decl (nterm_sym, token_sym);
a70083a3 1629 t = lex ();
1ff442ca 1630 }
511e79b3 1631 else if (t == tok_type)
1ff442ca 1632 {
a70083a3 1633 t = get_type ();
1ff442ca 1634 }
511e79b3 1635 else if (t == tok_union)
1ff442ca 1636 {
a70083a3
AD
1637 parse_union_decl ();
1638 t = lex ();
1ff442ca 1639 }
511e79b3 1640 else if (t == tok_expect)
1ff442ca 1641 {
a70083a3
AD
1642 parse_expect_decl ();
1643 t = lex ();
1ff442ca 1644 }
511e79b3 1645 else if (t == tok_start)
1ff442ca 1646 {
a70083a3
AD
1647 parse_start_decl ();
1648 t = lex ();
1ff442ca 1649 }
943819bf
RS
1650#endif
1651
1ff442ca 1652 else
943819bf 1653 {
d01c415b 1654 complain (_("invalid input: %s"), quote (token_buffer));
a70083a3 1655 t = lex ();
943819bf 1656 }
1ff442ca
NF
1657 }
1658
943819bf
RS
1659 /* grammar has been read. Do some checking */
1660
1ff442ca 1661 if (nsyms > MAXSHORT)
a0f6b076
AD
1662 fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
1663 MAXSHORT);
1ff442ca 1664 if (nrules == 0)
a0f6b076 1665 fatal (_("no rules in the input grammar"));
1ff442ca 1666
1ff442ca
NF
1667 /* Report any undefined symbols and consider them nonterminals. */
1668
1669 for (bp = firstsymbol; bp; bp = bp->next)
d7020c20 1670 if (bp->class == unknown_sym)
1ff442ca 1671 {
a70083a3
AD
1672 complain (_
1673 ("symbol %s is used, but is not defined as a token and has no rules"),
ff4a34be 1674 bp->tag);
d7020c20 1675 bp->class = nterm_sym;
1ff442ca
NF
1676 bp->value = nvars++;
1677 }
1678
1679 ntokens = nsyms - nvars;
1680}
ff48177d
MA
1681
1682/* At the end of the grammar file, some C source code must
63c2d5de 1683 be stored. It is going to be associated to the epilogue
ff48177d
MA
1684 directive. */
1685static void
1686read_additionnal_code (void)
1687{
1688 char c;
63c2d5de 1689 struct obstack el_obstack;
342b8b6e 1690
63c2d5de 1691 obstack_init (&el_obstack);
ff48177d
MA
1692
1693 while ((c = getc (finput)) != EOF)
63c2d5de 1694 obstack_1grow (&el_obstack, c);
342b8b6e 1695
63c2d5de 1696 obstack_1grow (&el_obstack, 0);
11d82f03 1697 muscle_insert ("epilogue", obstack_finish (&el_obstack));
ff48177d
MA
1698}
1699
a70083a3
AD
1700\f
1701/*--------------------------------------------------------------.
1702| For named tokens, but not literal ones, define the name. The |
1703| value is the user token number. |
1704`--------------------------------------------------------------*/
1ff442ca 1705
4a120d45 1706static void
896fe5c1 1707output_token_defines (struct obstack *oout)
1ff442ca 1708{
a70083a3
AD
1709 bucket *bp;
1710 char *cp, *symbol;
1711 char c;
1ff442ca 1712
a70083a3 1713 for (bp = firstsymbol; bp; bp = bp->next)
1ff442ca 1714 {
a70083a3
AD
1715 symbol = bp->tag; /* get symbol */
1716
1717 if (bp->value >= ntokens)
1718 continue;
1719 if (bp->user_token_number == SALIAS)
1720 continue;
1721 if ('\'' == *symbol)
1722 continue; /* skip literal character */
1723 if (bp == errtoken)
1724 continue; /* skip error token */
1725 if ('\"' == *symbol)
1ff442ca 1726 {
a70083a3
AD
1727 /* use literal string only if given a symbol with an alias */
1728 if (bp->alias)
1729 symbol = bp->alias->tag;
1730 else
1731 continue;
1732 }
1ff442ca 1733
a70083a3
AD
1734 /* Don't #define nonliteral tokens whose names contain periods. */
1735 cp = symbol;
1736 while ((c = *cp++) && c != '.');
1737 if (c != '\0')
1738 continue;
1ff442ca 1739
0b8afb77 1740 obstack_fgrow2 (oout, "# define\t%s\t%d\n",
342b8b6e 1741 symbol, bp->user_token_number);
a70083a3 1742 if (semantic_parser)
342b8b6e
AD
1743 /* FIXME: This is certainly dead wrong, and should be just as
1744 above. --akim. */
0b8afb77 1745 obstack_fgrow2 (oout, "# define\tT%s\t%d\n", symbol, bp->value);
1ff442ca
NF
1746 }
1747}
1ff442ca
NF
1748
1749
037ca2f1
AD
1750/*------------------------------------------------------------------.
1751| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
1752| number. |
1753`------------------------------------------------------------------*/
1754
1755static void
1756token_translations_init (void)
1757{
1758 bucket *bp = NULL;
1759 int i;
1760
1761 token_translations = XCALLOC (short, max_user_token_number + 1);
1762
1763 /* Initialize all entries for literal tokens to 2, the internal
1764 token number for $undefined., which represents all invalid
1765 inputs. */
1766 for (i = 0; i <= max_user_token_number; i++)
1767 token_translations[i] = 2;
1768
1769 for (bp = firstsymbol; bp; bp = bp->next)
1770 {
1771 /* Non-terminal? */
1772 if (bp->value >= ntokens)
1773 continue;
1774 /* A token string alias? */
1775 if (bp->user_token_number == SALIAS)
1776 continue;
6b7e85b9
AD
1777
1778 assert (bp->user_token_number != SUNDEF);
1779
037ca2f1
AD
1780 /* A token which translation has already been set? */
1781 if (token_translations[bp->user_token_number] != 2)
1782 complain (_("tokens %s and %s both assigned number %d"),
1783 tags[token_translations[bp->user_token_number]],
1784 bp->tag, bp->user_token_number);
1785 token_translations[bp->user_token_number] = bp->value;
1786 }
1787}
1788
1789
a70083a3
AD
1790/*------------------------------------------------------------------.
1791| Assign symbol numbers, and write definition of token names into |
b2ca4022 1792| FDEFINES. Set up vectors TAGS and SPREC of names and precedences |
a70083a3
AD
1793| of symbols. |
1794`------------------------------------------------------------------*/
1ff442ca 1795
4a120d45 1796static void
118fb205 1797packsymbols (void)
1ff442ca 1798{
342b8b6e 1799 bucket *bp = NULL;
a70083a3 1800 int tokno = 1;
a70083a3 1801 int last_user_token_number;
4a120d45 1802 static char DOLLAR[] = "$";
1ff442ca 1803
d7913476 1804 tags = XCALLOC (char *, nsyms + 1);
d7913476 1805 user_toknums = XCALLOC (short, nsyms + 1);
1ff442ca 1806
d7913476
AD
1807 sprec = XCALLOC (short, nsyms);
1808 sassoc = XCALLOC (short, nsyms);
1ff442ca 1809
037ca2f1
AD
1810 /* The EOF token. */
1811 tags[0] = DOLLAR;
1812 user_toknums[0] = 0;
1813
1ff442ca
NF
1814 max_user_token_number = 256;
1815 last_user_token_number = 256;
1816
1817 for (bp = firstsymbol; bp; bp = bp->next)
1818 {
d7020c20 1819 if (bp->class == nterm_sym)
1ff442ca
NF
1820 {
1821 bp->value += ntokens;
1822 }
943819bf
RS
1823 else if (bp->alias)
1824 {
0a6384c4
AD
1825 /* this symbol and its alias are a single token defn.
1826 allocate a tokno, and assign to both check agreement of
1827 ->prec and ->assoc fields and make both the same */
1828 if (bp->value == 0)
1829 bp->value = bp->alias->value = tokno++;
943819bf 1830
0a6384c4
AD
1831 if (bp->prec != bp->alias->prec)
1832 {
1833 if (bp->prec != 0 && bp->alias->prec != 0
1834 && bp->user_token_number == SALIAS)
a0f6b076
AD
1835 complain (_("conflicting precedences for %s and %s"),
1836 bp->tag, bp->alias->tag);
0a6384c4
AD
1837 if (bp->prec != 0)
1838 bp->alias->prec = bp->prec;
1839 else
1840 bp->prec = bp->alias->prec;
1841 }
943819bf 1842
0a6384c4
AD
1843 if (bp->assoc != bp->alias->assoc)
1844 {
a0f6b076
AD
1845 if (bp->assoc != 0 && bp->alias->assoc != 0
1846 && bp->user_token_number == SALIAS)
1847 complain (_("conflicting assoc values for %s and %s"),
1848 bp->tag, bp->alias->tag);
1849 if (bp->assoc != 0)
1850 bp->alias->assoc = bp->assoc;
1851 else
1852 bp->assoc = bp->alias->assoc;
1853 }
0a6384c4
AD
1854
1855 if (bp->user_token_number == SALIAS)
a70083a3 1856 continue; /* do not do processing below for SALIASs */
943819bf 1857
a70083a3 1858 }
d7020c20 1859 else /* bp->class == token_sym */
943819bf
RS
1860 {
1861 bp->value = tokno++;
1862 }
1863
d7020c20 1864 if (bp->class == token_sym)
1ff442ca 1865 {
6b7e85b9 1866 if (bp->user_token_number == SUNDEF)
1ff442ca
NF
1867 bp->user_token_number = ++last_user_token_number;
1868 if (bp->user_token_number > max_user_token_number)
1869 max_user_token_number = bp->user_token_number;
1ff442ca
NF
1870 }
1871
1872 tags[bp->value] = bp->tag;
943819bf 1873 user_toknums[bp->value] = bp->user_token_number;
1ff442ca
NF
1874 sprec[bp->value] = bp->prec;
1875 sassoc[bp->value] = bp->assoc;
1ff442ca
NF
1876 }
1877
037ca2f1 1878 token_translations_init ();
1ff442ca
NF
1879
1880 error_token_number = errtoken->value;
1881
e3f1699f
AD
1882 if (startval->class == unknown_sym)
1883 fatal (_("the start symbol %s is undefined"), startval->tag);
1884 else if (startval->class == token_sym)
1885 fatal (_("the start symbol %s is a token"), startval->tag);
1886
1887 start_symbol = startval->value;
1888}
1889
1890
1891/*-----------------------------------.
1892| Output definition of token names. |
1893`-----------------------------------*/
1894
1895static void
1896symbols_output (void)
1897{
342b8b6e
AD
1898 {
1899 struct obstack tokendefs;
1900 obstack_init (&tokendefs);
1901 output_token_defines (&tokendefs);
1902 obstack_1grow (&tokendefs, 0);
1903 muscle_insert ("tokendef", xstrdup (obstack_finish (&tokendefs)));
1904 obstack_free (&tokendefs, NULL);
1905 }
b6610515 1906
d8cb5183
MA
1907#if 0
1908 if (!no_parser_flag)
1909 output_token_defines (&table_obstack);
1910#endif
1ff442ca 1911
89cab50d 1912 if (defines_flag)
1ff442ca 1913 {
896fe5c1 1914 output_token_defines (&defines_obstack);
1ff442ca
NF
1915
1916 if (!pure_parser)
1917 {
1918 if (spec_name_prefix)
896fe5c1
AD
1919 obstack_fgrow1 (&defines_obstack, "\nextern YYSTYPE %slval;\n",
1920 spec_name_prefix);
1ff442ca 1921 else
ff4423cc 1922 obstack_sgrow (&defines_obstack,
573c1d9f 1923 "\nextern YYSTYPE yylval;\n");
1ff442ca
NF
1924 }
1925
1926 if (semantic_parser)
037ca2f1
AD
1927 {
1928 int i;
1929
1930 for (i = ntokens; i < nsyms; i++)
1931 {
1932 /* don't make these for dummy nonterminals made by gensym. */
1933 if (*tags[i] != '@')
1934 obstack_fgrow2 (&defines_obstack,
1935 "# define\tNT%s\t%d\n", tags[i], i);
1936 }
1ff442ca 1937#if 0
037ca2f1
AD
1938 /* `fdefines' is now a temporary file, so we need to copy its
1939 contents in `done', so we can't close it here. */
1940 fclose (fdefines);
1941 fdefines = NULL;
1ff442ca 1942#endif
037ca2f1 1943 }
1ff442ca
NF
1944 }
1945}
a083fbbf 1946
1ff442ca 1947
a70083a3
AD
1948/*---------------------------------------------------------------.
1949| Convert the rules into the representation using RRHS, RLHS and |
1950| RITEMS. |
1951`---------------------------------------------------------------*/
1ff442ca 1952
4a120d45 1953static void
118fb205 1954packgram (void)
1ff442ca 1955{
a70083a3
AD
1956 int itemno;
1957 int ruleno;
1958 symbol_list *p;
1ff442ca 1959
d7913476 1960 ritem = XCALLOC (short, nitems + 1);
b2ed6e58 1961 rule_table = XCALLOC (rule_t, nrules) - 1;
1ff442ca
NF
1962
1963 itemno = 0;
1964 ruleno = 1;
1965
1966 p = grammar;
1967 while (p)
1968 {
b29b2ed5 1969 bucket *ruleprec = p->ruleprec;
b2ed6e58
AD
1970 rule_table[ruleno].lhs = p->sym->value;
1971 rule_table[ruleno].rhs = itemno;
b29b2ed5 1972 rule_table[ruleno].line = p->line;
68f1e3ed 1973 rule_table[ruleno].useful = TRUE;
1ff442ca
NF
1974
1975 p = p->next;
1976 while (p && p->sym)
1977 {
1978 ritem[itemno++] = p->sym->value;
1979 /* A rule gets by default the precedence and associativity
1980 of the last token in it. */
d7020c20 1981 if (p->sym->class == token_sym)
1ff442ca 1982 {
652a871c
AD
1983 rule_table[ruleno].prec = p->sym->prec;
1984 rule_table[ruleno].assoc = p->sym->assoc;
1ff442ca 1985 }
a70083a3
AD
1986 if (p)
1987 p = p->next;
1ff442ca
NF
1988 }
1989
1990 /* If this rule has a %prec,
a70083a3 1991 the specified symbol's precedence replaces the default. */
1ff442ca
NF
1992 if (ruleprec)
1993 {
652a871c
AD
1994 rule_table[ruleno].prec = ruleprec->prec;
1995 rule_table[ruleno].assoc = ruleprec->assoc;
1996 rule_table[ruleno].precsym = ruleprec->value;
1ff442ca
NF
1997 }
1998
1999 ritem[itemno++] = -ruleno;
2000 ruleno++;
2001
a70083a3
AD
2002 if (p)
2003 p = p->next;
1ff442ca
NF
2004 }
2005
2006 ritem[itemno] = 0;
3067fbef
AD
2007
2008 if (trace_flag)
2009 ritem_print (stderr);
1ff442ca 2010}
a70083a3
AD
2011\f
2012/*-------------------------------------------------------------------.
2013| Read in the grammar specification and record it in the format |
ea5607fd 2014| described in gram.h. All guards are copied into the GUARD_OBSTACK |
8c7ebe49
AD
2015| and all actions into ACTION_OBSTACK, in each case forming the body |
2016| of a C function (YYGUARD or YYACTION) which contains a switch |
2017| statement to decide which guard or action to execute. |
a70083a3
AD
2018`-------------------------------------------------------------------*/
2019
2020void
2021reader (void)
2022{
2023 start_flag = 0;
2024 startval = NULL; /* start symbol not specified yet. */
2025
a70083a3
AD
2026 nsyms = 1;
2027 nvars = 0;
2028 nrules = 0;
2029 nitems = 0;
a70083a3
AD
2030
2031 typed = 0;
2032 lastprec = 0;
2033
a70083a3
AD
2034 semantic_parser = 0;
2035 pure_parser = 0;
a70083a3
AD
2036
2037 grammar = NULL;
2038
342b8b6e 2039 lex_init ();
a70083a3
AD
2040 lineno = 1;
2041
11d82f03
MA
2042 /* Initialize the muscle obstack. */
2043 obstack_init (&muscle_obstack);
82e236e2 2044
a70083a3
AD
2045 /* Initialize the symbol table. */
2046 tabinit ();
b6610515 2047
a70083a3
AD
2048 /* Construct the error token */
2049 errtoken = getsym ("error");
d7020c20 2050 errtoken->class = token_sym;
a70083a3 2051 errtoken->user_token_number = 256; /* Value specified by POSIX. */
b6610515 2052
a70083a3
AD
2053 /* Construct a token that represents all undefined literal tokens.
2054 It is always token number 2. */
2055 undeftoken = getsym ("$undefined.");
d7020c20 2056 undeftoken->class = token_sym;
a70083a3
AD
2057 undeftoken->user_token_number = 2;
2058
896fe5c1
AD
2059 /* Read the declaration section. Copy %{ ... %} groups to
2060 TABLE_OBSTACK and FDEFINES file. Also notice any %token, %left,
2061 etc. found there. */
a70083a3 2062 read_declarations ();
a70083a3
AD
2063 /* Read in the grammar, build grammar in list form. Write out
2064 guards and actions. */
2065 readgram ();
ff48177d
MA
2066 /* Some C code is given at the end of the grammar file. */
2067 read_additionnal_code ();
b0c4483e 2068
a70083a3 2069 /* Now we know whether we need the line-number stack. If we do,
b0c4483e
PB
2070 write its type into the .tab.h file.
2071 This is no longer need with header skeleton. */
2072
a70083a3
AD
2073 /* Assign the symbols their symbol numbers. Write #defines for the
2074 token symbols into FDEFINES if requested. */
2075 packsymbols ();
2076 /* Convert the grammar into the format described in gram.h. */
2077 packgram ();
edad7067
AD
2078 /* Output the headers. */
2079 symbols_output ();
a70083a3 2080}