]> git.saurik.com Git - bison.git/blame - src/reader.c
Regen.
[bison.git] / src / reader.c
CommitLineData
1ff442ca 1/* Input parser for bison
76514394 2 Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000, 2001, 2002
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"
2a91a95e
AD
24#include "quotearg.h"
25#include "quote.h"
ceed8467 26#include "getargs.h"
1ff442ca 27#include "files.h"
1ff442ca 28#include "symtab.h"
82b6d266 29#include "options.h"
1ff442ca
NF
30#include "lex.h"
31#include "gram.h"
a0f6b076 32#include "complain.h"
6c89f1c1 33#include "output.h"
b2ca4022 34#include "reader.h"
340ef489 35#include "conflicts.h"
11d82f03 36#include "muscle_tab.h"
1ff442ca 37
a70083a3
AD
38typedef struct symbol_list
39{
40 struct symbol_list *next;
db8837cb 41 symbol_t *sym;
b29b2ed5 42 int line;
f499b062 43
3f96f4dc
AD
44 /* The action is attached to the LHS of a rule. */
45 const char *action;
46 int action_line;
f499b062 47
db8837cb 48 symbol_t *ruleprec;
d945f5cd 49} symbol_list;
118fb205 50
1ff442ca 51int lineno;
280a38c3
AD
52static symbol_list *grammar = NULL;
53static int start_flag = 0;
1ff442ca 54
d7020c20 55/* Nonzero if %union has been seen. */
280a38c3 56static int typed = 0;
1ff442ca 57
d7020c20 58/* Incremented for each %left, %right or %nonassoc seen */
280a38c3 59static int lastprec = 0;
1ff442ca 60
6255b435 61static symbol_list *
db8837cb 62symbol_list_new (symbol_t *sym)
b29b2ed5
AD
63{
64 symbol_list *res = XMALLOC (symbol_list, 1);
65 res->next = NULL;
66 res->sym = sym;
67 res->line = lineno;
d945f5cd
AD
68 res->action = NULL;
69 res->action_line = 0;
b29b2ed5
AD
70 res->ruleprec = NULL;
71 return res;
72}
73
0d533154
AD
74/*===================\
75| Low level lexing. |
76\===================*/
943819bf
RS
77
78static void
118fb205 79skip_to_char (int target)
943819bf
RS
80{
81 int c;
82 if (target == '\n')
a0f6b076 83 complain (_(" Skipping to next \\n"));
943819bf 84 else
a0f6b076 85 complain (_(" Skipping to next %c"), target);
943819bf
RS
86
87 do
0d533154 88 c = skip_white_space ();
943819bf 89 while (c != target && c != EOF);
a083fbbf 90 if (c != EOF)
0d533154 91 ungetc (c, finput);
943819bf
RS
92}
93
94
0d533154
AD
95/*---------------------------------------------------------.
96| Read a signed integer from STREAM and return its value. |
97`---------------------------------------------------------*/
98
99static inline int
100read_signed_integer (FILE *stream)
101{
a70083a3
AD
102 int c = getc (stream);
103 int sign = 1;
104 int n = 0;
0d533154
AD
105
106 if (c == '-')
107 {
108 c = getc (stream);
109 sign = -1;
110 }
111
112 while (isdigit (c))
113 {
114 n = 10 * n + (c - '0');
115 c = getc (stream);
116 }
117
118 ungetc (c, stream);
119
120 return sign * n;
121}
122\f
79282c5a
AD
123/*--------------------------------------------------------------.
124| Get the data type (alternative in the union) of the value for |
125| symbol N in rule RULE. |
126`--------------------------------------------------------------*/
127
128static char *
b29b2ed5 129get_type_name (int n, symbol_list *rule)
79282c5a
AD
130{
131 int i;
132 symbol_list *rp;
133
134 if (n < 0)
135 {
136 complain (_("invalid $ value"));
137 return NULL;
138 }
139
140 rp = rule;
141 i = 0;
142
143 while (i < n)
144 {
145 rp = rp->next;
146 if (rp == NULL || rp->sym == NULL)
147 {
148 complain (_("invalid $ value"));
149 return NULL;
150 }
f3849179 151 ++i;
79282c5a
AD
152 }
153
154 return rp->sym->type_name;
155}
156\f
2b7ed18a
RA
157/*------------------------------------------------------------------.
158| Copy the character C to OOUT, and insert quadigraphs when needed. |
159`------------------------------------------------------------------*/
160
161static inline void
162copy_character (struct obstack *oout, int c)
163{
164 switch (c)
165 {
166 case '[':
167 obstack_sgrow (oout, "@<:@");
168 break;
169
170 case ']':
171 obstack_sgrow (oout, "@:>@");
172 break;
173
174 default:
175 obstack_1grow (oout, c);
176 }
177}
178
337bab46
AD
179/*------------------------------------------------------------.
180| Dump the string from FIN to OOUT if non null. MATCH is the |
181| delimiter of the string (either ' or "). |
182`------------------------------------------------------------*/
ae3c3164
AD
183
184static inline void
b6610515 185copy_string2 (FILE *fin, struct obstack *oout, int match, int store)
ae3c3164
AD
186{
187 int c;
188
b6610515
RA
189 if (store)
190 obstack_1grow (oout, match);
8c7ebe49 191
4a120d45 192 c = getc (fin);
ae3c3164
AD
193
194 while (c != match)
195 {
196 if (c == EOF)
197 fatal (_("unterminated string at end of file"));
198 if (c == '\n')
199 {
a0f6b076 200 complain (_("unterminated string"));
4a120d45 201 ungetc (c, fin);
ae3c3164
AD
202 c = match; /* invent terminator */
203 continue;
204 }
205
2b7ed18a 206 copy_character (oout, c);
ae3c3164
AD
207
208 if (c == '\\')
209 {
4a120d45 210 c = getc (fin);
ae3c3164
AD
211 if (c == EOF)
212 fatal (_("unterminated string at end of file"));
2b7ed18a 213 copy_character (oout, c);
8c7ebe49 214
ae3c3164 215 if (c == '\n')
f3849179 216 ++lineno;
ae3c3164
AD
217 }
218
a70083a3 219 c = getc (fin);
ae3c3164
AD
220 }
221
b6610515
RA
222 if (store)
223 obstack_1grow (oout, c);
224}
225
226/* FIXME. */
227
228static inline void
229copy_string (FILE *fin, struct obstack *oout, int match)
230{
231 copy_string2 (fin, oout, match, 1);
ae3c3164
AD
232}
233
b6610515
RA
234/* FIXME. */
235
236static inline void
237copy_identifier (FILE *fin, struct obstack *oout)
238{
239 int c;
240
241 while (isalnum (c = getc (fin)) || c == '_')
242 obstack_1grow (oout, c);
243
244 ungetc (c, fin);
245}
ae3c3164 246
2666f928
AD
247
248/*------------------------------------------------------------------.
249| Dump the wannabee comment from IN to OOUT. In fact we just saw a |
250| `/', which might or might not be a comment. In any case, copy |
251| what we saw. |
252`------------------------------------------------------------------*/
ae3c3164
AD
253
254static inline void
2666f928 255copy_comment (FILE *fin, struct obstack *oout)
ae3c3164
AD
256{
257 int cplus_comment;
a70083a3 258 int ended;
550a72a3
AD
259 int c;
260
261 /* We read a `/', output it. */
2666f928 262 obstack_1grow (oout, '/');
550a72a3
AD
263
264 switch ((c = getc (fin)))
265 {
266 case '/':
267 cplus_comment = 1;
268 break;
269 case '*':
270 cplus_comment = 0;
271 break;
272 default:
273 ungetc (c, fin);
274 return;
275 }
ae3c3164 276
2666f928 277 obstack_1grow (oout, c);
550a72a3 278 c = getc (fin);
ae3c3164
AD
279
280 ended = 0;
281 while (!ended)
282 {
283 if (!cplus_comment && c == '*')
284 {
285 while (c == '*')
286 {
2666f928 287 obstack_1grow (oout, c);
550a72a3 288 c = getc (fin);
ae3c3164
AD
289 }
290
291 if (c == '/')
292 {
2666f928 293 obstack_1grow (oout, c);
ae3c3164
AD
294 ended = 1;
295 }
296 }
297 else if (c == '\n')
298 {
f3849179 299 ++lineno;
2666f928 300 obstack_1grow (oout, c);
ae3c3164
AD
301 if (cplus_comment)
302 ended = 1;
303 else
550a72a3 304 c = getc (fin);
ae3c3164
AD
305 }
306 else if (c == EOF)
307 fatal (_("unterminated comment"));
308 else
309 {
2b7ed18a 310 copy_character (oout, c);
550a72a3 311 c = getc (fin);
ae3c3164
AD
312 }
313 }
314}
315
316
82b6cb3f
AD
317/*-------------------------------------------------------------------.
318| FIN is pointing to a location (i.e., a `@'). Output to OOUT a |
319| reference to this location. RULE_LENGTH is the number of values in |
320| 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
82b6cb3f 325copy_at (FILE *fin, struct obstack *oout, int rule_length)
1ff442ca 326{
82b6cb3f
AD
327 int c = getc (fin);
328 locations_flag = 1;
1ff442ca 329
a70083a3 330 if (c == '$')
1ff442ca 331 {
82b6cb3f 332 obstack_sgrow (oout, "]b4_lhs_location[");
a70083a3
AD
333 }
334 else if (isdigit (c) || c == '-')
335 {
336 int n;
1ff442ca 337
a70083a3
AD
338 ungetc (c, fin);
339 n = read_signed_integer (fin);
82b6cb3f 340 if (n > rule_length)
11e2beca
AD
341 complain (_("invalid value: %s%d"), "@", n);
342 else
82b6cb3f
AD
343 obstack_fgrow2 (oout, "]b4_rhs_location([%d], [%d])[",
344 rule_length, n);
1ff442ca 345 }
a70083a3 346 else
ff4a34be
AD
347 {
348 char buf[] = "@c";
349 buf[1] = c;
350 complain (_("%s is invalid"), quote (buf));
351 }
1ff442ca 352}
79282c5a
AD
353
354
82b6cb3f
AD
355/*------------------------------------------------------------------.
356| FIN is pointing to a wannabee semantic value (i.e., a `$'). |
357| |
358| Possible inputs: $[<TYPENAME>]($|integer) |
359| |
360| Output to OOUT a reference to this semantic value. RULE_LENGTH is |
361| the number of values in the current rule so far, which says where |
362| to find `$0' with respect to the top of the stack. |
363`------------------------------------------------------------------*/
79282c5a
AD
364
365static inline void
337bab46 366copy_dollar (FILE *fin, struct obstack *oout,
82b6cb3f 367 symbol_list *rule, int rule_length)
79282c5a
AD
368{
369 int c = getc (fin);
b0ce6046 370 const char *type_name = NULL;
79282c5a 371
f282676b 372 /* Get the type name if explicit. */
79282c5a
AD
373 if (c == '<')
374 {
f282676b 375 read_type_name (fin);
79282c5a 376 type_name = token_buffer;
79282c5a
AD
377 c = getc (fin);
378 }
379
380 if (c == '$')
381 {
79282c5a
AD
382 if (!type_name)
383 type_name = get_type_name (0, rule);
79282c5a
AD
384 if (!type_name && typed)
385 complain (_("$$ of `%s' has no declared type"),
386 rule->sym->tag);
82b6cb3f
AD
387 if (!type_name)
388 type_name = "";
389 obstack_fgrow1 (oout,
390 "]b4_lhs_value([%s])[", type_name);
79282c5a
AD
391 }
392 else if (isdigit (c) || c == '-')
393 {
394 int n;
395 ungetc (c, fin);
396 n = read_signed_integer (fin);
397
82b6cb3f 398 if (n > rule_length)
11e2beca
AD
399 complain (_("invalid value: %s%d"), "$", n);
400 else
401 {
402 if (!type_name && n > 0)
403 type_name = get_type_name (n, rule);
11e2beca
AD
404 if (!type_name && typed)
405 complain (_("$%d of `%s' has no declared type"),
406 n, rule->sym->tag);
82b6cb3f
AD
407 if (!type_name)
408 type_name = "";
409 obstack_fgrow3 (oout, "]b4_rhs_value([%d], [%d], [%s])[",
410 rule_length, n, type_name);
11e2beca 411 }
79282c5a
AD
412 }
413 else
414 {
415 char buf[] = "$c";
416 buf[1] = c;
417 complain (_("%s is invalid"), quote (buf));
418 }
419}
a70083a3
AD
420\f
421/*-------------------------------------------------------------------.
422| Copy the contents of a `%{ ... %}' into the definitions file. The |
423| `%{' has already been read. Return after reading the `%}'. |
424`-------------------------------------------------------------------*/
1ff442ca 425
4a120d45 426static void
0dd1580a 427copy_definition (struct obstack *oout)
1ff442ca 428{
a70083a3 429 int c;
ae3c3164 430 /* -1 while reading a character if prev char was %. */
a70083a3 431 int after_percent;
1ff442ca 432
89cab50d 433 if (!no_lines_flag)
25b222fa 434 {
0dd1580a 435 obstack_fgrow2 (oout, muscle_find ("linef"),
342b8b6e 436 lineno, quotearg_style (c_quoting_style,
b7c49edf 437 muscle_find ("filename")));
25b222fa 438 }
1ff442ca
NF
439
440 after_percent = 0;
441
ae3c3164 442 c = getc (finput);
1ff442ca
NF
443
444 for (;;)
445 {
446 switch (c)
447 {
448 case '\n':
0dd1580a 449 obstack_1grow (oout, c);
f3849179 450 ++lineno;
1ff442ca
NF
451 break;
452
453 case '%':
a70083a3 454 after_percent = -1;
1ff442ca 455 break;
a083fbbf 456
1ff442ca
NF
457 case '\'':
458 case '"':
0dd1580a 459 copy_string (finput, oout, c);
1ff442ca
NF
460 break;
461
462 case '/':
0dd1580a 463 copy_comment (finput, oout);
1ff442ca
NF
464 break;
465
466 case EOF:
a70083a3 467 fatal ("%s", _("unterminated `%{' definition"));
1ff442ca
NF
468
469 default:
2b7ed18a 470 copy_character (oout, c);
1ff442ca
NF
471 }
472
a70083a3 473 c = getc (finput);
1ff442ca
NF
474
475 if (after_percent)
476 {
477 if (c == '}')
478 return;
0dd1580a 479 obstack_1grow (oout, '%');
1ff442ca
NF
480 }
481 after_percent = 0;
1ff442ca 482 }
1ff442ca
NF
483}
484
485
44536b35
AD
486/*------------------------------------------.
487| Parse what comes after %token or %nterm. |
488`------------------------------------------*/
1ff442ca 489
4a120d45 490static void
44536b35 491parse_token_decl (symbol_class class)
1ff442ca 492{
342b8b6e
AD
493 token_t token = tok_undef;
494 char *typename = NULL;
1ff442ca 495
1e9798d5 496 /* The symbol being defined. */
db8837cb 497 symbol_t *symbol = NULL;
1e9798d5
AD
498
499 /* After `%token' and `%nterm', any number of symbols maybe be
500 defined. */
1ff442ca
NF
501 for (;;)
502 {
e6011337
JT
503 int tmp_char = ungetc (skip_white_space (), finput);
504
1e9798d5
AD
505 /* `%' (for instance from `%token', or from `%%' etc.) is the
506 only valid means to end this declaration. */
e6011337 507 if (tmp_char == '%')
1ff442ca 508 return;
e6011337 509 if (tmp_char == EOF)
a0f6b076 510 fatal (_("Premature EOF after %s"), token_buffer);
e6011337 511
a70083a3 512 token = lex ();
44536b35 513 switch (token)
943819bf 514 {
44536b35 515 case tok_comma:
943819bf 516 symbol = NULL;
44536b35
AD
517 break;
518
519 case tok_typename:
95e36146 520 typename = xstrdup (token_buffer);
943819bf 521 symbol = NULL;
44536b35
AD
522 break;
523
524 case tok_identifier:
525 if (*symval->tag == '\"' && symbol)
1ff442ca 526 {
44536b35
AD
527 symbol_make_alias (symbol, symval, typename);
528 symbol = NULL;
1ff442ca 529 }
44536b35 530 else
72a23c97 531 {
44536b35
AD
532 symbol = symval;
533 symbol_class_set (symbol, class);
534 if (typename)
535 symbol_type_set (symbol, typename);
72a23c97 536 }
44536b35
AD
537 break;
538
539 case tok_number:
540 symbol_user_token_number_set (symbol, numval);
541 break;
542
543 default:
a0f6b076 544 complain (_("`%s' is invalid in %s"),
b29b2ed5 545 token_buffer,
44536b35 546 (class == token_sym) ? "%token" : "%nterm");
a70083a3 547 skip_to_char ('%');
943819bf 548 }
1ff442ca
NF
549 }
550
551}
552
1ff442ca 553
d7020c20
AD
554/*------------------------------.
555| Parse what comes after %start |
556`------------------------------*/
1ff442ca 557
4a120d45 558static void
118fb205 559parse_start_decl (void)
1ff442ca
NF
560{
561 if (start_flag)
27821bff 562 complain (_("multiple %s declarations"), "%start");
511e79b3 563 if (lex () != tok_identifier)
27821bff 564 complain (_("invalid %s declaration"), "%start");
943819bf
RS
565 else
566 {
567 start_flag = 1;
2f1afb73 568 startsymbol = symval;
943819bf 569 }
1ff442ca
NF
570}
571
a70083a3
AD
572/*-----------------------------------------------------------.
573| read in a %type declaration and record its information for |
574| get_type_name to access |
575`-----------------------------------------------------------*/
576
577static void
578parse_type_decl (void)
579{
a70083a3
AD
580 char *name;
581
511e79b3 582 if (lex () != tok_typename)
a70083a3
AD
583 {
584 complain ("%s", _("%type declaration has no <typename>"));
585 skip_to_char ('%');
586 return;
587 }
588
95e36146 589 name = xstrdup (token_buffer);
a70083a3
AD
590
591 for (;;)
592 {
f17bcd1f 593 token_t t;
a70083a3
AD
594 int tmp_char = ungetc (skip_white_space (), finput);
595
596 if (tmp_char == '%')
597 return;
598 if (tmp_char == EOF)
599 fatal (_("Premature EOF after %s"), token_buffer);
600
601 t = lex ();
602
603 switch (t)
1ff442ca 604 {
511e79b3
AD
605 case tok_comma:
606 case tok_semicolon:
1ff442ca
NF
607 break;
608
511e79b3 609 case tok_identifier:
3ae2b51f 610 symbol_type_set (symval, name);
1ff442ca
NF
611 break;
612
613 default:
a0f6b076
AD
614 complain (_("invalid %%type declaration due to item: %s"),
615 token_buffer);
a70083a3 616 skip_to_char ('%');
1ff442ca
NF
617 }
618 }
619}
620
621
622
d7020c20
AD
623/*----------------------------------------------------------------.
624| Read in a %left, %right or %nonassoc declaration and record its |
625| information. |
626`----------------------------------------------------------------*/
1ff442ca 627
4a120d45 628static void
d7020c20 629parse_assoc_decl (associativity assoc)
1ff442ca 630{
a70083a3
AD
631 char *name = NULL;
632 int prev = 0;
1ff442ca 633
f3849179
AD
634 /* Assign a new precedence level, never 0. */
635 ++lastprec;
1ff442ca 636
1ff442ca
NF
637 for (;;)
638 {
f17bcd1f 639 token_t t;
e6011337 640 int tmp_char = ungetc (skip_white_space (), finput);
1ff442ca 641
e6011337 642 if (tmp_char == '%')
1ff442ca 643 return;
e6011337 644 if (tmp_char == EOF)
a0f6b076 645 fatal (_("Premature EOF after %s"), token_buffer);
1ff442ca 646
a70083a3 647 t = lex ();
1ff442ca
NF
648
649 switch (t)
650 {
511e79b3 651 case tok_typename:
95e36146 652 name = xstrdup (token_buffer);
1ff442ca
NF
653 break;
654
511e79b3 655 case tok_comma:
1ff442ca
NF
656 break;
657
511e79b3 658 case tok_identifier:
5e424082 659 symbol_class_set (symval, token_sym);
3ae2b51f 660 symbol_precedence_set (symval, lastprec, assoc);
1ff442ca 661 if (name)
3ae2b51f 662 symbol_type_set (symval, name);
1ff442ca
NF
663 break;
664
511e79b3
AD
665 case tok_number:
666 if (prev == tok_identifier)
a70083a3 667 {
5e424082 668 symbol_user_token_number_set (symval, numval);
a70083a3
AD
669 }
670 else
671 {
72a23c97
AD
672 complain
673 (_("invalid text (%s) - number should be after identifier"),
674 token_buffer);
a70083a3
AD
675 skip_to_char ('%');
676 }
1ff442ca
NF
677 break;
678
511e79b3 679 case tok_semicolon:
1ff442ca
NF
680 return;
681
682 default:
a0f6b076 683 complain (_("unexpected item: %s"), token_buffer);
a70083a3 684 skip_to_char ('%');
1ff442ca
NF
685 }
686
687 prev = t;
1ff442ca
NF
688 }
689}
690
691
692
dd60faec 693/*--------------------------------------------------------------.
180d45ba
PB
694| Copy the union declaration into the stype muscle |
695| (and fdefines), where it is made into the definition of |
696| YYSTYPE, the type of elements of the parser value stack. |
dd60faec 697`--------------------------------------------------------------*/
1ff442ca 698
4a120d45 699static void
118fb205 700parse_union_decl (void)
1ff442ca 701{
a70083a3
AD
702 int c;
703 int count = 0;
428046f8 704 bool done = FALSE;
180d45ba 705 struct obstack union_obstack;
1ff442ca 706 if (typed)
27821bff 707 complain (_("multiple %s declarations"), "%union");
1ff442ca
NF
708
709 typed = 1;
710
642cb8f8 711 MUSCLE_INSERT_INT ("stype_line", lineno);
180d45ba
PB
712 obstack_init (&union_obstack);
713 obstack_sgrow (&union_obstack, "union");
1ff442ca 714
428046f8 715 while (!done)
1ff442ca 716 {
428046f8
AD
717 c = xgetc (finput);
718
342b8b6e
AD
719 /* If C contains '/', it is output by copy_comment (). */
720 if (c != '/')
2666f928 721 obstack_1grow (&union_obstack, c);
1ff442ca
NF
722
723 switch (c)
724 {
725 case '\n':
f3849179 726 ++lineno;
1ff442ca
NF
727 break;
728
729 case '/':
2666f928 730 copy_comment (finput, &union_obstack);
1ff442ca
NF
731 break;
732
1ff442ca 733 case '{':
f3849179 734 ++count;
1ff442ca
NF
735 break;
736
737 case '}':
428046f8 738 /* FIXME: Errr. How could this happen???. --akim */
1ff442ca 739 if (count == 0)
27821bff 740 complain (_("unmatched %s"), "`}'");
1ff442ca 741 count--;
428046f8
AD
742 if (!count)
743 done = TRUE;
744 break;
1ff442ca 745 }
1ff442ca 746 }
180d45ba 747
428046f8
AD
748 /* JF don't choke on trailing semi */
749 c = skip_white_space ();
750 if (c != ';')
751 ungetc (c, finput);
752 obstack_1grow (&union_obstack, 0);
753 muscle_insert ("stype", obstack_finish (&union_obstack));
1ff442ca
NF
754}
755
d7020c20
AD
756
757/*-------------------------------------------------------.
758| Parse the declaration %expect N which says to expect N |
759| shift-reduce conflicts. |
760`-------------------------------------------------------*/
1ff442ca 761
4a120d45 762static void
118fb205 763parse_expect_decl (void)
1ff442ca 764{
131e2fef 765 int c = skip_white_space ();
1ff442ca
NF
766 ungetc (c, finput);
767
131e2fef 768 if (!isdigit (c))
79282c5a 769 complain (_("argument of %%expect is not an integer"));
131e2fef
AD
770 else
771 expected_conflicts = read_signed_integer (finput);
1ff442ca
NF
772}
773
a70083a3 774
b6610515 775static void
11d82f03 776parse_muscle_decl (void)
b6610515
RA
777{
778 int ch = ungetc (skip_white_space (), finput);
b7c49edf
AD
779 char *muscle_key;
780 char *muscle_value;
b6610515
RA
781
782 /* Read key. */
783 if (!isalpha (ch) && ch != '_')
784 {
785 complain (_("invalid %s declaration"), "%define");
786 skip_to_char ('%');
787 return;
788 }
11d82f03
MA
789 copy_identifier (finput, &muscle_obstack);
790 obstack_1grow (&muscle_obstack, 0);
791 muscle_key = obstack_finish (&muscle_obstack);
342b8b6e 792
b6610515
RA
793 /* Read value. */
794 ch = skip_white_space ();
795 if (ch != '"')
796 {
797 ungetc (ch, finput);
798 if (ch != EOF)
799 {
800 complain (_("invalid %s declaration"), "%define");
801 skip_to_char ('%');
802 return;
803 }
804 else
805 fatal (_("Premature EOF after %s"), "\"");
806 }
11d82f03
MA
807 copy_string2 (finput, &muscle_obstack, '"', 0);
808 obstack_1grow (&muscle_obstack, 0);
809 muscle_value = obstack_finish (&muscle_obstack);
b6610515 810
b6610515 811 /* Store the (key, value) pair in the environment. */
11d82f03 812 muscle_insert (muscle_key, muscle_value);
b6610515
RA
813}
814
2ba3b73c 815
426cf563
MA
816
817/*---------------------------------.
a870c567 818| Parse a double quoted parameter. |
426cf563
MA
819`---------------------------------*/
820
821static const char *
822parse_dquoted_param (const char *from)
823{
824 struct obstack param_obstack;
825 const char *param = NULL;
826 int c;
827
828 obstack_init (&param_obstack);
829 c = skip_white_space ();
830
831 if (c != '"')
832 {
833 complain (_("invalid %s declaration"), from);
834 ungetc (c, finput);
835 skip_to_char ('%');
836 return NULL;
837 }
838
2648a72d
AD
839 while ((c = literalchar ()) != '"')
840 obstack_1grow (&param_obstack, c);
a870c567 841
426cf563
MA
842 obstack_1grow (&param_obstack, '\0');
843 param = obstack_finish (&param_obstack);
844
845 if (c != '"' || strlen (param) == 0)
846 {
847 complain (_("invalid %s declaration"), from);
848 if (c != '"')
849 ungetc (c, finput);
850 skip_to_char ('%');
851 return NULL;
852 }
853
854 return param;
855}
856
2ba3b73c
MA
857/*----------------------------------.
858| Parse what comes after %skeleton. |
859`----------------------------------*/
860
a870c567 861static void
2ba3b73c
MA
862parse_skel_decl (void)
863{
426cf563 864 skeleton = parse_dquoted_param ("%skeleton");
2ba3b73c
MA
865}
866
a70083a3
AD
867/*----------------------------------------------------------------.
868| Read from finput until `%%' is seen. Discard the `%%'. Handle |
869| any `%' declarations, and copy the contents of any `%{ ... %}' |
0dd1580a 870| groups to PRE_PROLOGUE_OBSTACK or POST_PROLOGUE_OBSTACK. |
a70083a3 871`----------------------------------------------------------------*/
1ff442ca 872
4a120d45 873static void
a70083a3 874read_declarations (void)
1ff442ca 875{
a70083a3 876 for (;;)
1ff442ca 877 {
951366c1 878 int c = skip_white_space ();
1ff442ca 879
a70083a3
AD
880 if (c == '%')
881 {
951366c1 882 token_t tok = parse_percent_token ();
1ff442ca 883
a70083a3 884 switch (tok)
943819bf 885 {
511e79b3 886 case tok_two_percents:
a70083a3 887 return;
1ff442ca 888
511e79b3 889 case tok_percent_left_curly:
0dd1580a
RA
890 if (!typed)
891 copy_definition (&pre_prologue_obstack);
892 else
893 copy_definition (&post_prologue_obstack);
a70083a3 894 break;
1ff442ca 895
511e79b3 896 case tok_token:
44536b35 897 parse_token_decl (token_sym);
a70083a3 898 break;
1ff442ca 899
511e79b3 900 case tok_nterm:
44536b35 901 parse_token_decl (nterm_sym);
a70083a3 902 break;
1ff442ca 903
511e79b3 904 case tok_type:
a70083a3
AD
905 parse_type_decl ();
906 break;
1ff442ca 907
511e79b3 908 case tok_start:
a70083a3
AD
909 parse_start_decl ();
910 break;
118fb205 911
511e79b3 912 case tok_union:
a70083a3
AD
913 parse_union_decl ();
914 break;
1ff442ca 915
511e79b3 916 case tok_expect:
a70083a3
AD
917 parse_expect_decl ();
918 break;
6deb4447 919
511e79b3 920 case tok_left:
d7020c20 921 parse_assoc_decl (left_assoc);
a70083a3 922 break;
1ff442ca 923
511e79b3 924 case tok_right:
d7020c20 925 parse_assoc_decl (right_assoc);
a70083a3 926 break;
1ff442ca 927
511e79b3 928 case tok_nonassoc:
d7020c20 929 parse_assoc_decl (non_assoc);
a70083a3 930 break;
1ff442ca 931
b6610515 932 case tok_define:
11d82f03 933 parse_muscle_decl ();
b6610515 934 break;
342b8b6e 935
2ba3b73c
MA
936 case tok_skel:
937 parse_skel_decl ();
938 break;
b6610515 939
511e79b3 940 case tok_noop:
a70083a3 941 break;
1ff442ca 942
951366c1
AD
943 case tok_stropt:
944 case tok_intopt:
945 case tok_obsolete:
72a23c97 946 assert (0);
951366c1
AD
947 break;
948
e0c40012 949 case tok_illegal:
a70083a3
AD
950 default:
951 complain (_("unrecognized: %s"), token_buffer);
952 skip_to_char ('%');
953 }
954 }
955 else if (c == EOF)
956 fatal (_("no input grammar"));
957 else
958 {
ff4a34be
AD
959 char buf[] = "c";
960 buf[0] = c;
961 complain (_("unknown character: %s"), quote (buf));
a70083a3 962 skip_to_char ('%');
1ff442ca 963 }
1ff442ca 964 }
1ff442ca 965}
a70083a3 966\f
82b6cb3f
AD
967/*------------------------------------------------------------------.
968| Assuming that a `{' has just been seen, copy everything up to the |
2e047461
AD
969| matching `}' into ACTION_OBSTACK, and return a pointer to this |
970| action. |
82b6cb3f 971`------------------------------------------------------------------*/
1ff442ca 972
2e047461
AD
973static char *
974parse_action (symbol_list *rule)
1ff442ca 975{
3a8b4109 976 int count = 1;
2e047461
AD
977
978 /* RULE_LENGTH is the number of values in the current rule so far,
979 which says where to find `$0' with respect to the top of the
980 stack. It is not the same as the rule->length in the case of mid
981 rule actions. */
982 int rule_length = 0;
983 symbol_list *rhs;
984 for (rhs = rule->next; rhs; rhs = rhs->next)
985 ++rule_length;
986
1ff442ca
NF
987 while (count > 0)
988 {
3a8b4109 989 int c;
14d293ac
AD
990 while ((c = getc (finput)) != '}')
991 switch (c)
992 {
993 case '\n':
6390a83f 994 copy_character (&action_obstack, c);
f3849179 995 ++lineno;
14d293ac 996 break;
1ff442ca 997
14d293ac 998 case '{':
6390a83f 999 copy_character (&action_obstack, c);
f3849179 1000 ++count;
14d293ac 1001 break;
1ff442ca 1002
14d293ac
AD
1003 case '\'':
1004 case '"':
1005 copy_string (finput, &action_obstack, c);
1006 break;
1ff442ca 1007
14d293ac
AD
1008 case '/':
1009 copy_comment (finput, &action_obstack);
1010 break;
1ff442ca 1011
14d293ac 1012 case '$':
82b6cb3f 1013 copy_dollar (finput, &action_obstack, rule, rule_length);
14d293ac 1014 break;
1ff442ca 1015
14d293ac 1016 case '@':
82b6cb3f 1017 copy_at (finput, &action_obstack, rule_length);
14d293ac 1018 break;
a70083a3 1019
14d293ac
AD
1020 case EOF:
1021 fatal (_("unmatched %s"), "`{'");
a70083a3 1022
14d293ac 1023 default:
6390a83f 1024 copy_character (&action_obstack, c);
14d293ac 1025 }
a70083a3 1026
14d293ac 1027 /* Above loop exits when C is '}'. */
a70083a3 1028 if (--count)
6390a83f 1029 copy_character (&action_obstack, c);
a70083a3
AD
1030 }
1031
3f96f4dc 1032 obstack_1grow (&action_obstack, '\0');
2e047461 1033 return obstack_finish (&action_obstack);
14d293ac 1034}
a70083a3 1035
a70083a3
AD
1036\f
1037
a70083a3
AD
1038/*-------------------------------------------------------------------.
1039| Generate a dummy symbol, a nonterminal, whose name cannot conflict |
1040| with the user's names. |
1041`-------------------------------------------------------------------*/
1ff442ca 1042
db8837cb 1043static symbol_t *
118fb205 1044gensym (void)
1ff442ca 1045{
274d42ce
AD
1046 /* Incremented for each generated symbol */
1047 static int gensym_count = 0;
1048 static char buf[256];
1049
db8837cb 1050 symbol_t *sym;
1ff442ca 1051
274d42ce
AD
1052 sprintf (buf, "@%d", ++gensym_count);
1053 token_buffer = buf;
a70083a3 1054 sym = getsym (token_buffer);
d7020c20 1055 sym->class = nterm_sym;
d9b739c3 1056 sym->number = nvars++;
36281465 1057 return sym;
1ff442ca 1058}
a70083a3 1059\f
107f7dfb
AD
1060/*-------------------------------------------------------------------.
1061| Parse the input grammar into a one symbol_list structure. Each |
1062| rule is represented by a sequence of symbols: the left hand side |
1063| followed by the contents of the right hand side, followed by a |
1064| null pointer instead of a symbol to terminate the rule. The next |
1065| symbol is the lhs of the following rule. |
1066| |
fdbcd8e2
AD
1067| All actions are copied out, labelled by the rule number they apply |
1068| to. |
107f7dfb
AD
1069| |
1070| Bison used to allow some %directives in the rules sections, but |
1071| this is no longer consider appropriate: (i) the documented grammar |
1072| doesn't claim it, (ii), it would promote bad style, (iii), error |
1073| recovery for %directives consists in skipping the junk until a `%' |
1074| is seen and helrp synchronizing. This scheme is definitely wrong |
1075| in the rules section. |
1076`-------------------------------------------------------------------*/
1ff442ca 1077
f6d0f937
AD
1078/* The (currently) last symbol of GRAMMAR. */
1079symbol_list *grammar_end = NULL;
1080
1081/* Append S to the GRAMMAR. */
1082static void
1083grammar_symbol_append (symbol_t *s)
1084{
1085 symbol_list *p = symbol_list_new (s);
1086
1087 if (grammar_end)
1088 grammar_end->next = p;
1089 else
1090 grammar = p;
1091
1092 grammar_end = p;
1093}
1094
da4160c3
AD
1095/* The rule currently being defined, and the previous rule. Point to
1096 the first symbol of each list: their lhs. */
1097symbol_list *current_rule = NULL;
1098symbol_list *previous_rule = NULL;
1099
1100
1101/* Create a new rule for LHS in to the GRAMMAR. */
1102
1103static void
1104grammar_rule_begin (symbol_t *lhs)
1105{
1106 if (!start_flag)
1107 {
1108 startsymbol = lhs;
1109 start_flag = 1;
1110 }
1111
1112 /* Start a new rule and record its lhs. */
1113 ++nrules;
1114 ++nritems;
1115
1116 previous_rule = grammar_end;
1117 grammar_symbol_append (lhs);
1118 current_rule = grammar_end;
1119
1120 /* Mark the rule's lhs as a nonterminal if not already so. */
1121
1122 if (lhs->class == unknown_sym)
1123 {
1124 lhs->class = nterm_sym;
1125 lhs->number = nvars;
1126 ++nvars;
1127 }
1128 else if (lhs->class == token_sym)
1129 complain (_("rule given for %s, which is a token"), lhs->tag);
1130}
1131
1485e106
AD
1132/* The previous action turns out the be a mid-rule action. Attach it
1133 to the current rule, i.e., create a dummy symbol, attach it this
1134 mid-rule action, and append this dummy nonterminal to the current
1135 rule. */
1136
1137static void
1138grammar_midrule_action (void)
1139{
1140 /* Since the action was written out with this rule's number, we must
1141 give the new rule this number by inserting the new rule before
1142 it. */
1143
1144 /* Make a dummy nonterminal, a gensym. */
1145 symbol_t *sdummy = gensym ();
1146 symbol_list *midrule_action = symbol_list_new (sdummy);
1147
1148 /* Make a new rule, whose body is empty, before the current one, so
1149 that the action just read can belong to it. */
1150 ++nrules;
1151 ++nritems;
1152 /* Attach its lineno to that of the host rule. */
1153 midrule_action->line = current_rule->line;
1154 /* Move the action from the host rule to this one. */
1155 midrule_action->action = current_rule->action;
1156 midrule_action->action_line = current_rule->action_line;
1157 current_rule->action = NULL;
1158
1159 if (previous_rule)
1160 previous_rule->next = midrule_action;
1161 else
1162 grammar = midrule_action;
1163
1164 /* End of the rule. */
1165 previous_rule = symbol_list_new (NULL);
1166 previous_rule->next = current_rule;
1167
1168 midrule_action->next = previous_rule;
1169
1170 /* Insert the dummy generated by that rule into this rule. */
1171 ++nritems;
1172 grammar_symbol_append (sdummy);
1173}
1174
9af3fbce
AD
1175/* Set the precedence symbol of the current rule to PRECSYM. */
1176
1177static void
1178grammar_current_rule_prec_set (symbol_t *precsym)
1179{
1180 if (current_rule->ruleprec)
1181 complain (_("two @prec's in a row"));
1182 current_rule->ruleprec = precsym;
1183}
1184
1185/* Check that the last rule (CURRENT_RULE) is properly defined. For
1186 instance, there should be no type clash on the default action. */
1187
1188static void
1189grammar_current_rule_check (void)
1190{
1191 symbol_t *lhs = current_rule->sym;
1192 symbol_t *first_rhs = current_rule->next->sym;
1193
1194 /* If there is an action, then there is nothing we can do: the user
1195 is allowed to shoot in her foot. */
1196 if (current_rule->action)
1197 return;
1198
1199 /* If $$ is being set in default way, report if any type mismatch.
1200 */
1201 if (first_rhs)
1202 {
1203 const char *lhs_type = lhs->type_name ? lhs->type_name : "";
1204 const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : "";
1205 if (strcmp (lhs_type, rhs_type))
1206 complain (_("type clash (`%s' `%s') on default action"),
1207 lhs_type, rhs_type);
1208 }
1209 /* Warn if there is no default for $$ but we need one. */
1210 else
1211 {
1212 if (lhs->type_name)
1213 complain (_("empty rule for typed nonterminal, and no action"));
1214 }
1215}
1216
1485e106 1217
2e047461
AD
1218/* Attach a SYMBOL to the current rule. If needed, move the previous
1219 action as a mid-rule action. */
1220
1221static void
1222grammar_current_rule_symbol_append (symbol_t *symbol)
1223{
1224 if (current_rule->action)
1225 grammar_midrule_action ();
1226 ++nritems;
1227 grammar_symbol_append (symbol);
1228}
1229
1230
1231/* Attach an ACTION to the current rule. If needed, move the previous
1232 action as a mid-rule action. */
1233
1234static void
1235grammar_current_rule_action_append (char *action, int action_line)
1236{
1237 if (current_rule->action)
1238 grammar_midrule_action ();
1239 current_rule->action = action;
1240 current_rule->action_line = action_line;
1241}
1242
1243
1244
4a120d45 1245static void
118fb205 1246readgram (void)
1ff442ca 1247{
f17bcd1f 1248 token_t t;
db8837cb 1249 symbol_t *lhs = NULL;
1ff442ca 1250
a70083a3 1251 t = lex ();
1ff442ca 1252
511e79b3 1253 while (t != tok_two_percents && t != tok_eof)
107f7dfb
AD
1254 if (t == tok_identifier || t == tok_bar)
1255 {
107f7dfb
AD
1256 if (t == tok_identifier)
1257 {
1258 lhs = symval;
1259
107f7dfb
AD
1260 t = lex ();
1261 if (t != tok_colon)
1262 {
1263 complain (_("ill-formed rule: initial symbol not followed by colon"));
1264 unlex (t);
1265 }
1266 }
107f7dfb
AD
1267 if (nrules == 0 && t == tok_bar)
1268 {
1269 complain (_("grammar starts with vertical bar"));
1270 lhs = symval; /* BOGUS: use a random symval */
1271 }
1ff442ca 1272
da4160c3 1273 grammar_rule_begin (lhs);
107f7dfb 1274 /* read the rhs of the rule. */
1ff442ca 1275
107f7dfb
AD
1276 for (;;)
1277 {
1278 t = lex ();
1279 if (t == tok_prec)
1280 {
1281 t = lex ();
9af3fbce 1282 grammar_current_rule_prec_set (symval);
107f7dfb
AD
1283 t = lex ();
1284 }
1285
1286 if (!(t == tok_identifier || t == tok_left_curly))
1287 break;
1ff442ca 1288
107f7dfb
AD
1289 /* If next token is an identifier, see if a colon follows it.
1290 If one does, exit this rule now. */
1291 if (t == tok_identifier)
1292 {
db8837cb 1293 symbol_t *ssave;
107f7dfb
AD
1294 token_t t1;
1295
1296 ssave = symval;
1297 t1 = lex ();
1298 unlex (t1);
1299 symval = ssave;
1300 if (t1 == tok_colon)
e5352bc7 1301 {
fff9bf0b 1302 warn (_("previous rule lacks an ending `;'"));
e5352bc7
AD
1303 break;
1304 }
9af3fbce
AD
1305 /* Not followed by colon => process as part of this
1306 rule's rhs. */
107f7dfb
AD
1307 }
1308
107f7dfb
AD
1309 if (t == tok_identifier)
1310 {
2e047461 1311 grammar_current_rule_symbol_append (symval);
107f7dfb
AD
1312 }
1313 else /* handle an action. */
1314 {
2e047461
AD
1315 int action_line = lineno;
1316 char *action = parse_action (current_rule);
1317 grammar_current_rule_action_append (action, action_line);
107f7dfb 1318 }
107f7dfb
AD
1319 } /* end of read rhs of rule */
1320
1321 /* Put an empty link in the list to mark the end of this rule */
f6d0f937 1322 grammar_symbol_append (NULL);
107f7dfb
AD
1323
1324 if (t == tok_prec)
1325 {
107f7dfb 1326 t = lex ();
9af3fbce 1327 grammar_current_rule_prec_set (symval);
107f7dfb
AD
1328 t = lex ();
1329 }
f499b062 1330
f499b062 1331 if (t == tok_left_curly)
107f7dfb 1332 {
2e047461
AD
1333 int action_line = lineno;
1334 char *action = parse_action (current_rule);
1335 grammar_current_rule_action_append (action, action_line);
107f7dfb
AD
1336 t = lex ();
1337 }
9af3fbce
AD
1338
1339 grammar_current_rule_check ();
1340
bfcf1f3a 1341 if (t == tok_two_percents || t == tok_eof)
fff9bf0b 1342 warn (_("previous rule lacks an ending `;'"));
107f7dfb 1343 if (t == tok_semicolon)
a70083a3 1344 t = lex ();
107f7dfb
AD
1345 }
1346 else
1347 {
1348 complain (_("invalid input: %s"), quote (token_buffer));
1349 t = lex ();
1350 }
943819bf 1351
b68e7744
AD
1352 /* grammar has been read. Do some checking */
1353
1354 if (nrules == 0)
1355 fatal (_("no rules in the input grammar"));
1356
1357 /* Report any undefined symbols and consider them nonterminals. */
2f1afb73 1358 symbols_check_defined ();
b68e7744 1359
ff442794
AD
1360 /* Insert the initial rule, which line is that of the first rule
1361 (not that of the start symbol):
30171f79
AD
1362
1363 axiom: %start EOF. */
f6d0f937
AD
1364 {
1365 symbol_list *p = symbol_list_new (axiom);
1366 p->line = grammar->line;
1367 p->next = symbol_list_new (startsymbol);
1368 p->next->next = symbol_list_new (eoftoken);
1369 p->next->next->next = symbol_list_new (NULL);
1370 p->next->next->next->next = grammar;
1371 nrules += 1;
1372 nritems += 3;
1373 grammar = p;
1374 }
1ff442ca 1375
62a3e4f0 1376 if (nsyms > SHRT_MAX)
a0f6b076 1377 fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
62a3e4f0 1378 SHRT_MAX);
1ff442ca 1379
72a23c97 1380 assert (nsyms == ntokens + nvars);
1ff442ca 1381}
ff48177d
MA
1382
1383/* At the end of the grammar file, some C source code must
63c2d5de 1384 be stored. It is going to be associated to the epilogue
ff48177d
MA
1385 directive. */
1386static void
1387read_additionnal_code (void)
1388{
9101a310 1389 int c;
63c2d5de 1390 struct obstack el_obstack;
342b8b6e 1391
63c2d5de 1392 obstack_init (&el_obstack);
ff48177d 1393
710ddc4f
MA
1394 if (!no_lines_flag)
1395 {
1396 obstack_fgrow2 (&el_obstack, muscle_find ("linef"),
1397 lineno, quotearg_style (c_quoting_style,
b7c49edf 1398 muscle_find ("filename")));
710ddc4f
MA
1399 }
1400
ff48177d 1401 while ((c = getc (finput)) != EOF)
2b7ed18a 1402 copy_character (&el_obstack, c);
342b8b6e 1403
63c2d5de 1404 obstack_1grow (&el_obstack, 0);
11d82f03 1405 muscle_insert ("epilogue", obstack_finish (&el_obstack));
ff48177d
MA
1406}
1407
a70083a3 1408\f
a70083a3
AD
1409/*---------------------------------------------------------------.
1410| Convert the rules into the representation using RRHS, RLHS and |
d9b739c3 1411| RITEM. |
a70083a3 1412`---------------------------------------------------------------*/
1ff442ca 1413
4a120d45 1414static void
118fb205 1415packgram (void)
1ff442ca 1416{
0c2d3f4c 1417 unsigned int itemno;
a70083a3
AD
1418 int ruleno;
1419 symbol_list *p;
1ff442ca 1420
a900a624 1421 ritem = XCALLOC (item_number_t, nritems);
1a2b5d37 1422 rules = XCALLOC (rule_t, nrules) - 1;
1ff442ca
NF
1423
1424 itemno = 0;
1425 ruleno = 1;
1426
1427 p = grammar;
1428 while (p)
1429 {
db8837cb 1430 symbol_t *ruleprec = p->ruleprec;
d7e1f00c 1431 rules[ruleno].user_number = ruleno;
c3b407f4 1432 rules[ruleno].number = ruleno;
bba97eb2 1433 rules[ruleno].lhs = p->sym;
99013900 1434 rules[ruleno].rhs = ritem + itemno;
1a2b5d37
AD
1435 rules[ruleno].line = p->line;
1436 rules[ruleno].useful = TRUE;
1437 rules[ruleno].action = p->action;
1438 rules[ruleno].action_line = p->action_line;
1ff442ca
NF
1439
1440 p = p->next;
1441 while (p && p->sym)
1442 {
a49aecd5 1443 /* item_number_t = symbol_number_t.
5fbb0954 1444 But the former needs to contain more: negative rule numbers. */
a49aecd5 1445 ritem[itemno++] = symbol_number_as_item_number (p->sym->number);
1ff442ca
NF
1446 /* A rule gets by default the precedence and associativity
1447 of the last token in it. */
d7020c20 1448 if (p->sym->class == token_sym)
03b31c0c 1449 rules[ruleno].prec = p->sym;
a70083a3
AD
1450 if (p)
1451 p = p->next;
1ff442ca
NF
1452 }
1453
1454 /* If this rule has a %prec,
a70083a3 1455 the specified symbol's precedence replaces the default. */
1ff442ca
NF
1456 if (ruleprec)
1457 {
03b31c0c
AD
1458 rules[ruleno].precsym = ruleprec;
1459 rules[ruleno].prec = ruleprec;
1ff442ca 1460 }
1ff442ca 1461 ritem[itemno++] = -ruleno;
f3849179 1462 ++ruleno;
1ff442ca 1463
a70083a3
AD
1464 if (p)
1465 p = p->next;
1ff442ca
NF
1466 }
1467
5123689b 1468 assert (itemno == nritems);
3067fbef
AD
1469
1470 if (trace_flag)
1471 ritem_print (stderr);
1ff442ca 1472}
a70083a3 1473\f
fdbcd8e2
AD
1474/*------------------------------------------------------------------.
1475| Read in the grammar specification and record it in the format |
1476| described in gram.h. All actions are copied into ACTION_OBSTACK, |
1477| in each case forming the body of a C function (YYACTION) which |
1478| contains a switch statement to decide which action to execute. |
1479`------------------------------------------------------------------*/
a70083a3
AD
1480
1481void
1482reader (void)
1483{
342b8b6e 1484 lex_init ();
a70083a3
AD
1485 lineno = 1;
1486
11d82f03
MA
1487 /* Initialize the muscle obstack. */
1488 obstack_init (&muscle_obstack);
82e236e2 1489
a70083a3 1490 /* Initialize the symbol table. */
db8837cb 1491 symbols_new ();
b6610515 1492
30171f79
AD
1493 /* Construct the axiom symbol. */
1494 axiom = getsym ("$axiom");
1495 axiom->class = nterm_sym;
d9b739c3 1496 axiom->number = nvars++;
30171f79 1497
a70083a3
AD
1498 /* Construct the error token */
1499 errtoken = getsym ("error");
d7020c20 1500 errtoken->class = token_sym;
72a23c97 1501 errtoken->number = ntokens++;
b6610515 1502
a70083a3
AD
1503 /* Construct a token that represents all undefined literal tokens.
1504 It is always token number 2. */
1505 undeftoken = getsym ("$undefined.");
d7020c20 1506 undeftoken->class = token_sym;
72a23c97 1507 undeftoken->number = ntokens++;
a70083a3 1508
331dbc1b
AD
1509 /* Initialize the obstacks. */
1510 obstack_init (&action_obstack);
331dbc1b 1511 obstack_init (&output_obstack);
0dd1580a
RA
1512 obstack_init (&pre_prologue_obstack);
1513 obstack_init (&post_prologue_obstack);
331dbc1b
AD
1514
1515 finput = xfopen (infile, "r");
1516
896fe5c1
AD
1517 /* Read the declaration section. Copy %{ ... %} groups to
1518 TABLE_OBSTACK and FDEFINES file. Also notice any %token, %left,
1519 etc. found there. */
a70083a3 1520 read_declarations ();
b7c49edf
AD
1521
1522 /* If the user did not define her EOFTOKEN, do it now. */
1523 if (!eoftoken)
1524 {
1525 eoftoken = getsym ("$");
1526 eoftoken->class = token_sym;
72a23c97 1527 eoftoken->number = 0;
b7c49edf
AD
1528 /* Value specified by POSIX. */
1529 eoftoken->user_token_number = 0;
1530 }
1531
a70083a3 1532 /* Read in the grammar, build grammar in list form. Write out
fdbcd8e2 1533 actions. */
a70083a3 1534 readgram ();
ff48177d
MA
1535 /* Some C code is given at the end of the grammar file. */
1536 read_additionnal_code ();
b0c4483e 1537
331dbc1b
AD
1538 lex_free ();
1539 xfclose (finput);
1540
a70083a3
AD
1541 /* Assign the symbols their symbol numbers. Write #defines for the
1542 token symbols into FDEFINES if requested. */
2f1afb73 1543 symbols_pack ();
93ede233 1544
a70083a3
AD
1545 /* Convert the grammar into the format described in gram.h. */
1546 packgram ();
8419d367
AD
1547
1548 /* The grammar as a symbol_list is no longer needed. */
1549 LIST_FREE (symbol_list, grammar);
a70083a3 1550}