]> git.saurik.com Git - bison.git/blame - src/reader.c
* src/bison.simple (union yyalloc): Change member names
[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/*---------------------------------.
969| Parse a double quoted parameter. |
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 }
997
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
1017void
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;
8c7ebe49 1136 char buf[4096];
1ff442ca
NF
1137
1138 /* offset is always 0 if parser has already popped the stack pointer */
41aca2e0
AD
1139 if (semantic_parser)
1140 stack_offset = 0;
1ff442ca 1141
25b222fa 1142 obstack_fgrow1 (&action_obstack, "\ncase %d:\n", nrules);
8c7ebe49 1143
89cab50d 1144 if (!no_lines_flag)
8c7ebe49 1145 {
25b222fa 1146 obstack_fgrow2 (&action_obstack, muscle_find ("linef"),
342b8b6e 1147 lineno, quotearg_style (c_quoting_style,
25b222fa 1148 muscle_find ("filename")));
8c7ebe49
AD
1149 }
1150 obstack_1grow (&action_obstack, '{');
1ff442ca
NF
1151
1152 count = 1;
a70083a3 1153 c = getc (finput);
1ff442ca
NF
1154
1155 while (count > 0)
1156 {
1157 while (c != '}')
a70083a3
AD
1158 {
1159 switch (c)
1ff442ca
NF
1160 {
1161 case '\n':
8c7ebe49 1162 obstack_1grow (&action_obstack, c);
1ff442ca
NF
1163 lineno++;
1164 break;
1165
1166 case '{':
8c7ebe49 1167 obstack_1grow (&action_obstack, c);
1ff442ca
NF
1168 count++;
1169 break;
1170
1171 case '\'':
1172 case '"':
337bab46 1173 copy_string (finput, &action_obstack, c);
1ff442ca
NF
1174 break;
1175
1176 case '/':
337bab46 1177 copy_comment (finput, &action_obstack);
1ff442ca
NF
1178 break;
1179
1180 case '$':
337bab46 1181 copy_dollar (finput, &action_obstack,
8c7ebe49 1182 rule, stack_offset);
1ff442ca
NF
1183 break;
1184
1185 case '@':
337bab46 1186 copy_at (finput, &action_obstack,
8c7ebe49 1187 stack_offset);
6666f98f 1188 break;
1ff442ca
NF
1189
1190 case EOF:
27821bff 1191 fatal (_("unmatched %s"), "`{'");
1ff442ca
NF
1192
1193 default:
8c7ebe49 1194 obstack_1grow (&action_obstack, c);
a70083a3
AD
1195 }
1196
1197 c = getc (finput);
1198 }
1199
1200 /* above loop exits when c is '}' */
1201
1202 if (--count)
1203 {
8c7ebe49 1204 obstack_1grow (&action_obstack, c);
a70083a3
AD
1205 c = getc (finput);
1206 }
1207 }
1208
ff4423cc 1209 obstack_sgrow (&action_obstack, ";\n break;}");
a70083a3
AD
1210}
1211\f
1212/*-------------------------------------------------------------------.
1213| After `%guard' is seen in the input file, copy the actual guard |
1214| into the guards file. If the guard is followed by an action, copy |
1215| that into the actions file. STACK_OFFSET is the number of values |
1216| in the current rule so far, which says where to find `$0' with |
1217| respect to the top of the stack, for the simple parser in which |
1218| the stack is not popped until after the guard is run. |
1219`-------------------------------------------------------------------*/
1220
1221static void
79282c5a 1222copy_guard (symbol_list *rule, int stack_offset)
a70083a3
AD
1223{
1224 int c;
a70083a3 1225 int count;
a70083a3
AD
1226 int brace_flag = 0;
1227
1228 /* offset is always 0 if parser has already popped the stack pointer */
1229 if (semantic_parser)
1230 stack_offset = 0;
1231
ea5607fd 1232 obstack_fgrow1 (&guard_obstack, "\ncase %d:\n", nrules);
89cab50d 1233 if (!no_lines_flag)
25b222fa 1234 obstack_fgrow2 (&guard_obstack, muscle_find ("linef"),
682d48cd 1235 lineno, quotearg_style (c_quoting_style,
11d82f03 1236 muscle_find ("filename")));
ea5607fd 1237 obstack_1grow (&guard_obstack, '{');
a70083a3
AD
1238
1239 count = 0;
1240 c = getc (finput);
1241
1242 while (brace_flag ? (count > 0) : (c != ';'))
1243 {
1244 switch (c)
1245 {
1246 case '\n':
ea5607fd 1247 obstack_1grow (&guard_obstack, c);
a70083a3
AD
1248 lineno++;
1249 break;
1250
1251 case '{':
ea5607fd 1252 obstack_1grow (&guard_obstack, c);
a70083a3
AD
1253 brace_flag = 1;
1254 count++;
1255 break;
1256
1257 case '}':
ea5607fd 1258 obstack_1grow (&guard_obstack, c);
a70083a3
AD
1259 if (count > 0)
1260 count--;
1261 else
1262 {
1263 complain (_("unmatched %s"), "`}'");
1264 c = getc (finput); /* skip it */
1265 }
1266 break;
1267
1268 case '\'':
1269 case '"':
337bab46 1270 copy_string (finput, &guard_obstack, c);
a70083a3
AD
1271 break;
1272
1273 case '/':
337bab46 1274 copy_comment (finput, &guard_obstack);
a70083a3
AD
1275 break;
1276
1277 case '$':
337bab46 1278 copy_dollar (finput, &guard_obstack, rule, stack_offset);
a70083a3 1279 break;
1ff442ca 1280
a70083a3 1281 case '@':
337bab46 1282 copy_at (finput, &guard_obstack, stack_offset);
a70083a3 1283 break;
1ff442ca 1284
a70083a3
AD
1285 case EOF:
1286 fatal ("%s", _("unterminated %guard clause"));
1ff442ca 1287
a70083a3 1288 default:
ea5607fd 1289 obstack_1grow (&guard_obstack, c);
1ff442ca 1290 }
a70083a3
AD
1291
1292 if (c != '}' || count != 0)
1293 c = getc (finput);
1ff442ca
NF
1294 }
1295
a70083a3
AD
1296 c = skip_white_space ();
1297
ff4423cc 1298 obstack_sgrow (&guard_obstack, ";\n break;}");
a70083a3
AD
1299 if (c == '{')
1300 copy_action (rule, stack_offset);
1301 else if (c == '=')
1302 {
1303 c = getc (finput); /* why not skip_white_space -wjh */
1304 if (c == '{')
1305 copy_action (rule, stack_offset);
1306 }
1307 else
1308 ungetc (c, finput);
1ff442ca 1309}
a70083a3
AD
1310\f
1311
a70083a3
AD
1312/*-------------------------------------------------------------------.
1313| Generate a dummy symbol, a nonterminal, whose name cannot conflict |
1314| with the user's names. |
1315`-------------------------------------------------------------------*/
1ff442ca 1316
4a120d45 1317static bucket *
118fb205 1318gensym (void)
1ff442ca 1319{
274d42ce
AD
1320 /* Incremented for each generated symbol */
1321 static int gensym_count = 0;
1322 static char buf[256];
1323
a70083a3 1324 bucket *sym;
1ff442ca 1325
274d42ce
AD
1326 sprintf (buf, "@%d", ++gensym_count);
1327 token_buffer = buf;
a70083a3 1328 sym = getsym (token_buffer);
d7020c20 1329 sym->class = nterm_sym;
1ff442ca 1330 sym->value = nvars++;
36281465 1331 return sym;
1ff442ca
NF
1332}
1333
a70083a3
AD
1334#if 0
1335/*------------------------------------------------------------------.
1336| read in a %type declaration and record its information for |
1337| get_type_name to access. This is unused. It is only called from |
1338| the #if 0 part of readgram |
1339`------------------------------------------------------------------*/
1340
1341static int
1342get_type (void)
1343{
1344 int k;
f17bcd1f 1345 token_t token;
a70083a3
AD
1346 char *name;
1347
f17bcd1f 1348 token = lex ();
a70083a3 1349
f17bcd1f 1350 if (token != tok_typename)
a70083a3
AD
1351 {
1352 complain (_("invalid %s declaration"), "%type");
1353 return t;
1354 }
1355
95e36146 1356 name = xstrdup (token_buffer);
a70083a3
AD
1357
1358 for (;;)
1359 {
f17bcd1f 1360 token = lex ();
a70083a3 1361
f17bcd1f 1362 switch (token)
a70083a3 1363 {
511e79b3 1364 case tok_semicolon:
a70083a3
AD
1365 return lex ();
1366
511e79b3 1367 case tok_comma:
a70083a3
AD
1368 break;
1369
511e79b3 1370 case tok_identifier:
a70083a3
AD
1371 if (symval->type_name == NULL)
1372 symval->type_name = name;
1373 else if (strcmp (name, symval->type_name) != 0)
1374 complain (_("type redeclaration for %s"), symval->tag);
1375
1376 break;
1377
1378 default:
f17bcd1f 1379 return token;
a70083a3
AD
1380 }
1381 }
1382}
1ff442ca 1383
a70083a3
AD
1384#endif
1385\f
1386/*------------------------------------------------------------------.
1387| Parse the input grammar into a one symbol_list structure. Each |
1388| rule is represented by a sequence of symbols: the left hand side |
1389| followed by the contents of the right hand side, followed by a |
1390| null pointer instead of a symbol to terminate the rule. The next |
1391| symbol is the lhs of the following rule. |
1392| |
1393| All guards and actions are copied out to the appropriate files, |
1394| labelled by the rule number they apply to. |
1395`------------------------------------------------------------------*/
1ff442ca 1396
4a120d45 1397static void
118fb205 1398readgram (void)
1ff442ca 1399{
f17bcd1f 1400 token_t t;
a70083a3
AD
1401 bucket *lhs = NULL;
1402 symbol_list *p;
1403 symbol_list *p1;
1404 bucket *bp;
1ff442ca 1405
ff4a34be
AD
1406 /* Points to first symbol_list of current rule. its symbol is the
1407 lhs of the rule. */
1408 symbol_list *crule;
1409 /* Points to the symbol_list preceding crule. */
1410 symbol_list *crule1;
1ff442ca
NF
1411
1412 p1 = NULL;
1413
a70083a3 1414 t = lex ();
1ff442ca 1415
511e79b3 1416 while (t != tok_two_percents && t != tok_eof)
1ff442ca 1417 {
511e79b3 1418 if (t == tok_identifier || t == tok_bar)
1ff442ca 1419 {
89cab50d 1420 int action_flag = 0;
ff4a34be
AD
1421 /* Number of symbols in rhs of this rule so far */
1422 int rulelength = 0;
1ff442ca
NF
1423 int xactions = 0; /* JF for error checking */
1424 bucket *first_rhs = 0;
1425
511e79b3 1426 if (t == tok_identifier)
1ff442ca
NF
1427 {
1428 lhs = symval;
943819bf
RS
1429
1430 if (!start_flag)
1431 {
1432 startval = lhs;
1433 start_flag = 1;
1434 }
a083fbbf 1435
a70083a3 1436 t = lex ();
511e79b3 1437 if (t != tok_colon)
943819bf 1438 {
a0f6b076 1439 complain (_("ill-formed rule: initial symbol not followed by colon"));
a70083a3 1440 unlex (t);
943819bf 1441 }
1ff442ca
NF
1442 }
1443
511e79b3 1444 if (nrules == 0 && t == tok_bar)
1ff442ca 1445 {
a0f6b076 1446 complain (_("grammar starts with vertical bar"));
943819bf 1447 lhs = symval; /* BOGUS: use a random symval */
1ff442ca 1448 }
1ff442ca
NF
1449 /* start a new rule and record its lhs. */
1450
1451 nrules++;
1452 nitems++;
1453
b29b2ed5 1454 p = symbol_list_new (lhs);
1ff442ca
NF
1455
1456 crule1 = p1;
1457 if (p1)
1458 p1->next = p;
1459 else
1460 grammar = p;
1461
1462 p1 = p;
1463 crule = p;
1464
1465 /* mark the rule's lhs as a nonterminal if not already so. */
1466
d7020c20 1467 if (lhs->class == unknown_sym)
1ff442ca 1468 {
d7020c20 1469 lhs->class = nterm_sym;
1ff442ca
NF
1470 lhs->value = nvars;
1471 nvars++;
1472 }
d7020c20 1473 else if (lhs->class == token_sym)
a0f6b076 1474 complain (_("rule given for %s, which is a token"), lhs->tag);
1ff442ca
NF
1475
1476 /* read the rhs of the rule. */
1477
1478 for (;;)
1479 {
a70083a3 1480 t = lex ();
511e79b3 1481 if (t == tok_prec)
943819bf 1482 {
a70083a3 1483 t = lex ();
943819bf 1484 crule->ruleprec = symval;
a70083a3 1485 t = lex ();
943819bf 1486 }
1ff442ca 1487
511e79b3 1488 if (!(t == tok_identifier || t == tok_left_curly))
a70083a3 1489 break;
1ff442ca
NF
1490
1491 /* If next token is an identifier, see if a colon follows it.
a70083a3 1492 If one does, exit this rule now. */
511e79b3 1493 if (t == tok_identifier)
1ff442ca 1494 {
a70083a3 1495 bucket *ssave;
f17bcd1f 1496 token_t t1;
1ff442ca
NF
1497
1498 ssave = symval;
a70083a3
AD
1499 t1 = lex ();
1500 unlex (t1);
1ff442ca 1501 symval = ssave;
511e79b3 1502 if (t1 == tok_colon)
a70083a3 1503 break;
1ff442ca 1504
a70083a3 1505 if (!first_rhs) /* JF */
1ff442ca
NF
1506 first_rhs = symval;
1507 /* Not followed by colon =>
1508 process as part of this rule's rhs. */
1509 }
1510
1511 /* If we just passed an action, that action was in the middle
a70083a3
AD
1512 of a rule, so make a dummy rule to reduce it to a
1513 non-terminal. */
89cab50d 1514 if (action_flag)
1ff442ca 1515 {
f282676b
AD
1516 /* Since the action was written out with this rule's
1517 number, we must give the new rule this number by
1518 inserting the new rule before it. */
1ff442ca
NF
1519
1520 /* Make a dummy nonterminal, a gensym. */
b29b2ed5 1521 bucket *sdummy = gensym ();
1ff442ca 1522
2ca209c1
AD
1523 /* Make a new rule, whose body is empty, before the
1524 current one, so that the action just read can
1525 belong to it. */
1ff442ca
NF
1526 nrules++;
1527 nitems++;
b29b2ed5 1528 p = symbol_list_new (sdummy);
2ca209c1
AD
1529 /* Attach its lineno to that of the host rule. */
1530 p->line = crule->line;
1ff442ca
NF
1531 if (crule1)
1532 crule1->next = p;
a70083a3
AD
1533 else
1534 grammar = p;
b29b2ed5
AD
1535 /* End of the rule. */
1536 crule1 = symbol_list_new (NULL);
1ff442ca
NF
1537 crule1->next = crule;
1538
e41dc700
AD
1539 p->next = crule1;
1540
f282676b
AD
1541 /* Insert the dummy generated by that rule into this
1542 rule. */
1ff442ca 1543 nitems++;
b29b2ed5 1544 p = symbol_list_new (sdummy);
1ff442ca
NF
1545 p1->next = p;
1546 p1 = p;
1547
89cab50d 1548 action_flag = 0;
1ff442ca
NF
1549 }
1550
511e79b3 1551 if (t == tok_identifier)
1ff442ca
NF
1552 {
1553 nitems++;
b29b2ed5 1554 p = symbol_list_new (symval);
1ff442ca
NF
1555 p1->next = p;
1556 p1 = p;
1557 }
a70083a3 1558 else /* handle an action. */
1ff442ca 1559 {
a70083a3 1560 copy_action (crule, rulelength);
89cab50d 1561 action_flag = 1;
1ff442ca
NF
1562 xactions++; /* JF */
1563 }
1564 rulelength++;
a70083a3 1565 } /* end of read rhs of rule */
1ff442ca
NF
1566
1567 /* Put an empty link in the list to mark the end of this rule */
b29b2ed5 1568 p = symbol_list_new (NULL);
1ff442ca
NF
1569 p1->next = p;
1570 p1 = p;
1571
511e79b3 1572 if (t == tok_prec)
1ff442ca 1573 {
a0f6b076 1574 complain (_("two @prec's in a row"));
a70083a3 1575 t = lex ();
1ff442ca 1576 crule->ruleprec = symval;
a70083a3 1577 t = lex ();
1ff442ca 1578 }
511e79b3 1579 if (t == tok_guard)
1ff442ca 1580 {
a70083a3 1581 if (!semantic_parser)
ff4a34be 1582 complain (_("%%guard present but %%semantic_parser not specified"));
1ff442ca 1583
a70083a3
AD
1584 copy_guard (crule, rulelength);
1585 t = lex ();
1ff442ca 1586 }
511e79b3 1587 else if (t == tok_left_curly)
1ff442ca 1588 {
a70083a3 1589 /* This case never occurs -wjh */
89cab50d 1590 if (action_flag)
a0f6b076 1591 complain (_("two actions at end of one rule"));
a70083a3 1592 copy_action (crule, rulelength);
89cab50d 1593 action_flag = 1;
943819bf 1594 xactions++; /* -wjh */
a70083a3 1595 t = lex ();
1ff442ca 1596 }
a0f6b076 1597 /* If $$ is being set in default way, report if any type
6666f98f
AD
1598 mismatch. */
1599 else if (!xactions
a70083a3 1600 && first_rhs && lhs->type_name != first_rhs->type_name)
1ff442ca 1601 {
6666f98f
AD
1602 if (lhs->type_name == 0
1603 || first_rhs->type_name == 0
a70083a3 1604 || strcmp (lhs->type_name, first_rhs->type_name))
a0f6b076
AD
1605 complain (_("type clash (`%s' `%s') on default action"),
1606 lhs->type_name ? lhs->type_name : "",
a70083a3 1607 first_rhs->type_name ? first_rhs->type_name : "");
1ff442ca
NF
1608 }
1609 /* Warn if there is no default for $$ but we need one. */
1610 else if (!xactions && !first_rhs && lhs->type_name != 0)
a0f6b076 1611 complain (_("empty rule for typed nonterminal, and no action"));
511e79b3 1612 if (t == tok_semicolon)
a70083a3 1613 t = lex ();
a083fbbf 1614 }
943819bf 1615#if 0
a70083a3 1616 /* these things can appear as alternatives to rules. */
943819bf
RS
1617/* NO, they cannot.
1618 a) none of the documentation allows them
1619 b) most of them scan forward until finding a next %
1620 thus they may swallow lots of intervening rules
1621*/
511e79b3 1622 else if (t == tok_token)
1ff442ca 1623 {
d7020c20 1624 parse_token_decl (token_sym, nterm_sym);
a70083a3 1625 t = lex ();
1ff442ca 1626 }
511e79b3 1627 else if (t == tok_nterm)
1ff442ca 1628 {
d7020c20 1629 parse_token_decl (nterm_sym, token_sym);
a70083a3 1630 t = lex ();
1ff442ca 1631 }
511e79b3 1632 else if (t == tok_type)
1ff442ca 1633 {
a70083a3 1634 t = get_type ();
1ff442ca 1635 }
511e79b3 1636 else if (t == tok_union)
1ff442ca 1637 {
a70083a3
AD
1638 parse_union_decl ();
1639 t = lex ();
1ff442ca 1640 }
511e79b3 1641 else if (t == tok_expect)
1ff442ca 1642 {
a70083a3
AD
1643 parse_expect_decl ();
1644 t = lex ();
1ff442ca 1645 }
511e79b3 1646 else if (t == tok_start)
1ff442ca 1647 {
a70083a3
AD
1648 parse_start_decl ();
1649 t = lex ();
1ff442ca 1650 }
943819bf
RS
1651#endif
1652
1ff442ca 1653 else
943819bf 1654 {
d01c415b 1655 complain (_("invalid input: %s"), quote (token_buffer));
a70083a3 1656 t = lex ();
943819bf 1657 }
1ff442ca
NF
1658 }
1659
943819bf
RS
1660 /* grammar has been read. Do some checking */
1661
1ff442ca 1662 if (nsyms > MAXSHORT)
a0f6b076
AD
1663 fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
1664 MAXSHORT);
1ff442ca 1665 if (nrules == 0)
a0f6b076 1666 fatal (_("no rules in the input grammar"));
1ff442ca 1667
1ff442ca
NF
1668 /* Report any undefined symbols and consider them nonterminals. */
1669
1670 for (bp = firstsymbol; bp; bp = bp->next)
d7020c20 1671 if (bp->class == unknown_sym)
1ff442ca 1672 {
a70083a3
AD
1673 complain (_
1674 ("symbol %s is used, but is not defined as a token and has no rules"),
ff4a34be 1675 bp->tag);
d7020c20 1676 bp->class = nterm_sym;
1ff442ca
NF
1677 bp->value = nvars++;
1678 }
1679
1680 ntokens = nsyms - nvars;
1681}
ff48177d
MA
1682
1683/* At the end of the grammar file, some C source code must
63c2d5de 1684 be stored. It is going to be associated to the epilogue
ff48177d
MA
1685 directive. */
1686static void
1687read_additionnal_code (void)
1688{
1689 char c;
63c2d5de 1690 struct obstack el_obstack;
342b8b6e 1691
63c2d5de 1692 obstack_init (&el_obstack);
ff48177d
MA
1693
1694 while ((c = getc (finput)) != EOF)
63c2d5de 1695 obstack_1grow (&el_obstack, c);
342b8b6e 1696
63c2d5de 1697 obstack_1grow (&el_obstack, 0);
11d82f03 1698 muscle_insert ("epilogue", obstack_finish (&el_obstack));
ff48177d
MA
1699}
1700
a70083a3
AD
1701\f
1702/*--------------------------------------------------------------.
1703| For named tokens, but not literal ones, define the name. The |
1704| value is the user token number. |
1705`--------------------------------------------------------------*/
1ff442ca 1706
4a120d45 1707static void
896fe5c1 1708output_token_defines (struct obstack *oout)
1ff442ca 1709{
a70083a3
AD
1710 bucket *bp;
1711 char *cp, *symbol;
1712 char c;
1ff442ca 1713
a70083a3 1714 for (bp = firstsymbol; bp; bp = bp->next)
1ff442ca 1715 {
a70083a3
AD
1716 symbol = bp->tag; /* get symbol */
1717
1718 if (bp->value >= ntokens)
1719 continue;
1720 if (bp->user_token_number == SALIAS)
1721 continue;
1722 if ('\'' == *symbol)
1723 continue; /* skip literal character */
1724 if (bp == errtoken)
1725 continue; /* skip error token */
1726 if ('\"' == *symbol)
1ff442ca 1727 {
a70083a3
AD
1728 /* use literal string only if given a symbol with an alias */
1729 if (bp->alias)
1730 symbol = bp->alias->tag;
1731 else
1732 continue;
1733 }
1ff442ca 1734
a70083a3
AD
1735 /* Don't #define nonliteral tokens whose names contain periods. */
1736 cp = symbol;
1737 while ((c = *cp++) && c != '.');
1738 if (c != '\0')
1739 continue;
1ff442ca 1740
0b8afb77 1741 obstack_fgrow2 (oout, "# define\t%s\t%d\n",
342b8b6e 1742 symbol, bp->user_token_number);
a70083a3 1743 if (semantic_parser)
342b8b6e
AD
1744 /* FIXME: This is certainly dead wrong, and should be just as
1745 above. --akim. */
0b8afb77 1746 obstack_fgrow2 (oout, "# define\tT%s\t%d\n", symbol, bp->value);
1ff442ca
NF
1747 }
1748}
1ff442ca
NF
1749
1750
037ca2f1
AD
1751/*------------------------------------------------------------------.
1752| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
1753| number. |
1754`------------------------------------------------------------------*/
1755
1756static void
1757token_translations_init (void)
1758{
1759 bucket *bp = NULL;
1760 int i;
1761
1762 token_translations = XCALLOC (short, max_user_token_number + 1);
1763
1764 /* Initialize all entries for literal tokens to 2, the internal
1765 token number for $undefined., which represents all invalid
1766 inputs. */
1767 for (i = 0; i <= max_user_token_number; i++)
1768 token_translations[i] = 2;
1769
1770 for (bp = firstsymbol; bp; bp = bp->next)
1771 {
1772 /* Non-terminal? */
1773 if (bp->value >= ntokens)
1774 continue;
1775 /* A token string alias? */
1776 if (bp->user_token_number == SALIAS)
1777 continue;
6b7e85b9
AD
1778
1779 assert (bp->user_token_number != SUNDEF);
1780
037ca2f1
AD
1781 /* A token which translation has already been set? */
1782 if (token_translations[bp->user_token_number] != 2)
1783 complain (_("tokens %s and %s both assigned number %d"),
1784 tags[token_translations[bp->user_token_number]],
1785 bp->tag, bp->user_token_number);
1786 token_translations[bp->user_token_number] = bp->value;
1787 }
1788}
1789
1790
a70083a3
AD
1791/*------------------------------------------------------------------.
1792| Assign symbol numbers, and write definition of token names into |
b2ca4022 1793| FDEFINES. Set up vectors TAGS and SPREC of names and precedences |
a70083a3
AD
1794| of symbols. |
1795`------------------------------------------------------------------*/
1ff442ca 1796
4a120d45 1797static void
118fb205 1798packsymbols (void)
1ff442ca 1799{
342b8b6e 1800 bucket *bp = NULL;
a70083a3 1801 int tokno = 1;
a70083a3 1802 int last_user_token_number;
4a120d45 1803 static char DOLLAR[] = "$";
1ff442ca 1804
d7913476 1805 tags = XCALLOC (char *, nsyms + 1);
d7913476 1806 user_toknums = XCALLOC (short, nsyms + 1);
1ff442ca 1807
d7913476
AD
1808 sprec = XCALLOC (short, nsyms);
1809 sassoc = XCALLOC (short, nsyms);
1ff442ca 1810
037ca2f1
AD
1811 /* The EOF token. */
1812 tags[0] = DOLLAR;
1813 user_toknums[0] = 0;
1814
1ff442ca
NF
1815 max_user_token_number = 256;
1816 last_user_token_number = 256;
1817
1818 for (bp = firstsymbol; bp; bp = bp->next)
1819 {
d7020c20 1820 if (bp->class == nterm_sym)
1ff442ca
NF
1821 {
1822 bp->value += ntokens;
1823 }
943819bf
RS
1824 else if (bp->alias)
1825 {
0a6384c4
AD
1826 /* this symbol and its alias are a single token defn.
1827 allocate a tokno, and assign to both check agreement of
1828 ->prec and ->assoc fields and make both the same */
1829 if (bp->value == 0)
1830 bp->value = bp->alias->value = tokno++;
943819bf 1831
0a6384c4
AD
1832 if (bp->prec != bp->alias->prec)
1833 {
1834 if (bp->prec != 0 && bp->alias->prec != 0
1835 && bp->user_token_number == SALIAS)
a0f6b076
AD
1836 complain (_("conflicting precedences for %s and %s"),
1837 bp->tag, bp->alias->tag);
0a6384c4
AD
1838 if (bp->prec != 0)
1839 bp->alias->prec = bp->prec;
1840 else
1841 bp->prec = bp->alias->prec;
1842 }
943819bf 1843
0a6384c4
AD
1844 if (bp->assoc != bp->alias->assoc)
1845 {
a0f6b076
AD
1846 if (bp->assoc != 0 && bp->alias->assoc != 0
1847 && bp->user_token_number == SALIAS)
1848 complain (_("conflicting assoc values for %s and %s"),
1849 bp->tag, bp->alias->tag);
1850 if (bp->assoc != 0)
1851 bp->alias->assoc = bp->assoc;
1852 else
1853 bp->assoc = bp->alias->assoc;
1854 }
0a6384c4
AD
1855
1856 if (bp->user_token_number == SALIAS)
a70083a3 1857 continue; /* do not do processing below for SALIASs */
943819bf 1858
a70083a3 1859 }
d7020c20 1860 else /* bp->class == token_sym */
943819bf
RS
1861 {
1862 bp->value = tokno++;
1863 }
1864
d7020c20 1865 if (bp->class == token_sym)
1ff442ca 1866 {
6b7e85b9 1867 if (bp->user_token_number == SUNDEF)
1ff442ca
NF
1868 bp->user_token_number = ++last_user_token_number;
1869 if (bp->user_token_number > max_user_token_number)
1870 max_user_token_number = bp->user_token_number;
1ff442ca
NF
1871 }
1872
1873 tags[bp->value] = bp->tag;
943819bf 1874 user_toknums[bp->value] = bp->user_token_number;
1ff442ca
NF
1875 sprec[bp->value] = bp->prec;
1876 sassoc[bp->value] = bp->assoc;
1ff442ca
NF
1877 }
1878
037ca2f1 1879 token_translations_init ();
1ff442ca
NF
1880
1881 error_token_number = errtoken->value;
1882
e3f1699f
AD
1883 if (startval->class == unknown_sym)
1884 fatal (_("the start symbol %s is undefined"), startval->tag);
1885 else if (startval->class == token_sym)
1886 fatal (_("the start symbol %s is a token"), startval->tag);
1887
1888 start_symbol = startval->value;
1889}
1890
1891
1892/*-----------------------------------.
1893| Output definition of token names. |
1894`-----------------------------------*/
1895
1896static void
1897symbols_output (void)
1898{
342b8b6e
AD
1899 {
1900 struct obstack tokendefs;
1901 obstack_init (&tokendefs);
1902 output_token_defines (&tokendefs);
1903 obstack_1grow (&tokendefs, 0);
1904 muscle_insert ("tokendef", xstrdup (obstack_finish (&tokendefs)));
1905 obstack_free (&tokendefs, NULL);
1906 }
b6610515 1907
d8cb5183
MA
1908#if 0
1909 if (!no_parser_flag)
1910 output_token_defines (&table_obstack);
1911#endif
1ff442ca 1912
89cab50d 1913 if (defines_flag)
1ff442ca 1914 {
896fe5c1 1915 output_token_defines (&defines_obstack);
1ff442ca
NF
1916
1917 if (!pure_parser)
1918 {
1919 if (spec_name_prefix)
896fe5c1
AD
1920 obstack_fgrow1 (&defines_obstack, "\nextern YYSTYPE %slval;\n",
1921 spec_name_prefix);
1ff442ca 1922 else
ff4423cc 1923 obstack_sgrow (&defines_obstack,
573c1d9f 1924 "\nextern YYSTYPE yylval;\n");
1ff442ca
NF
1925 }
1926
1927 if (semantic_parser)
037ca2f1
AD
1928 {
1929 int i;
1930
1931 for (i = ntokens; i < nsyms; i++)
1932 {
1933 /* don't make these for dummy nonterminals made by gensym. */
1934 if (*tags[i] != '@')
1935 obstack_fgrow2 (&defines_obstack,
1936 "# define\tNT%s\t%d\n", tags[i], i);
1937 }
1ff442ca 1938#if 0
037ca2f1
AD
1939 /* `fdefines' is now a temporary file, so we need to copy its
1940 contents in `done', so we can't close it here. */
1941 fclose (fdefines);
1942 fdefines = NULL;
1ff442ca 1943#endif
037ca2f1 1944 }
1ff442ca
NF
1945 }
1946}
a083fbbf 1947
1ff442ca 1948
a70083a3
AD
1949/*---------------------------------------------------------------.
1950| Convert the rules into the representation using RRHS, RLHS and |
1951| RITEMS. |
1952`---------------------------------------------------------------*/
1ff442ca 1953
4a120d45 1954static void
118fb205 1955packgram (void)
1ff442ca 1956{
a70083a3
AD
1957 int itemno;
1958 int ruleno;
1959 symbol_list *p;
1ff442ca 1960
d7913476 1961 ritem = XCALLOC (short, nitems + 1);
b2ed6e58 1962 rule_table = XCALLOC (rule_t, nrules) - 1;
1ff442ca
NF
1963
1964 itemno = 0;
1965 ruleno = 1;
1966
1967 p = grammar;
1968 while (p)
1969 {
b29b2ed5 1970 bucket *ruleprec = p->ruleprec;
b2ed6e58
AD
1971 rule_table[ruleno].lhs = p->sym->value;
1972 rule_table[ruleno].rhs = itemno;
b29b2ed5 1973 rule_table[ruleno].line = p->line;
68f1e3ed 1974 rule_table[ruleno].useful = TRUE;
1ff442ca
NF
1975
1976 p = p->next;
1977 while (p && p->sym)
1978 {
1979 ritem[itemno++] = p->sym->value;
1980 /* A rule gets by default the precedence and associativity
1981 of the last token in it. */
d7020c20 1982 if (p->sym->class == token_sym)
1ff442ca 1983 {
652a871c
AD
1984 rule_table[ruleno].prec = p->sym->prec;
1985 rule_table[ruleno].assoc = p->sym->assoc;
1ff442ca 1986 }
a70083a3
AD
1987 if (p)
1988 p = p->next;
1ff442ca
NF
1989 }
1990
1991 /* If this rule has a %prec,
a70083a3 1992 the specified symbol's precedence replaces the default. */
1ff442ca
NF
1993 if (ruleprec)
1994 {
652a871c
AD
1995 rule_table[ruleno].prec = ruleprec->prec;
1996 rule_table[ruleno].assoc = ruleprec->assoc;
1997 rule_table[ruleno].precsym = ruleprec->value;
1ff442ca
NF
1998 }
1999
2000 ritem[itemno++] = -ruleno;
2001 ruleno++;
2002
a70083a3
AD
2003 if (p)
2004 p = p->next;
1ff442ca
NF
2005 }
2006
2007 ritem[itemno] = 0;
2008}
a70083a3
AD
2009\f
2010/*-------------------------------------------------------------------.
2011| Read in the grammar specification and record it in the format |
ea5607fd 2012| described in gram.h. All guards are copied into the GUARD_OBSTACK |
8c7ebe49
AD
2013| and all actions into ACTION_OBSTACK, in each case forming the body |
2014| of a C function (YYGUARD or YYACTION) which contains a switch |
2015| statement to decide which guard or action to execute. |
a70083a3
AD
2016`-------------------------------------------------------------------*/
2017
2018void
2019reader (void)
2020{
2021 start_flag = 0;
2022 startval = NULL; /* start symbol not specified yet. */
2023
a70083a3
AD
2024 nsyms = 1;
2025 nvars = 0;
2026 nrules = 0;
2027 nitems = 0;
a70083a3
AD
2028
2029 typed = 0;
2030 lastprec = 0;
2031
a70083a3
AD
2032 semantic_parser = 0;
2033 pure_parser = 0;
a70083a3
AD
2034
2035 grammar = NULL;
2036
342b8b6e 2037 lex_init ();
a70083a3
AD
2038 lineno = 1;
2039
11d82f03
MA
2040 /* Initialize the muscle obstack. */
2041 obstack_init (&muscle_obstack);
82e236e2 2042
a70083a3
AD
2043 /* Initialize the symbol table. */
2044 tabinit ();
b6610515 2045
a70083a3
AD
2046 /* Construct the error token */
2047 errtoken = getsym ("error");
d7020c20 2048 errtoken->class = token_sym;
a70083a3 2049 errtoken->user_token_number = 256; /* Value specified by POSIX. */
b6610515 2050
a70083a3
AD
2051 /* Construct a token that represents all undefined literal tokens.
2052 It is always token number 2. */
2053 undeftoken = getsym ("$undefined.");
d7020c20 2054 undeftoken->class = token_sym;
a70083a3
AD
2055 undeftoken->user_token_number = 2;
2056
896fe5c1
AD
2057 /* Read the declaration section. Copy %{ ... %} groups to
2058 TABLE_OBSTACK and FDEFINES file. Also notice any %token, %left,
2059 etc. found there. */
a70083a3 2060 read_declarations ();
a70083a3
AD
2061 /* Read in the grammar, build grammar in list form. Write out
2062 guards and actions. */
2063 readgram ();
ff48177d
MA
2064 /* Some C code is given at the end of the grammar file. */
2065 read_additionnal_code ();
b0c4483e 2066
a70083a3 2067 /* Now we know whether we need the line-number stack. If we do,
b0c4483e
PB
2068 write its type into the .tab.h file.
2069 This is no longer need with header skeleton. */
2070
a70083a3
AD
2071 /* Assign the symbols their symbol numbers. Write #defines for the
2072 token symbols into FDEFINES if requested. */
2073 packsymbols ();
e3f1699f 2074 symbols_output ();
a70083a3
AD
2075 /* Convert the grammar into the format described in gram.h. */
2076 packgram ();
edad7067
AD
2077 /* Output the headers. */
2078 symbols_output ();
a70083a3 2079}