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