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