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