]> git.saurik.com Git - bison.git/blame - src/reader.c
* src/reader.c (grammar_current_rule_prec_set).
[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 |
3a8b4109
AD
969| matching `}' into ACTION_OBSTACK. |
970| |
971| RULE_LENGTH is the number of values in the current rule so far, |
972| which says where to find `$0' with respect to the top of the |
973| stack. It is not the same as the rule->length in the case of mid |
974| rule actions. |
82b6cb3f 975`------------------------------------------------------------------*/
1ff442ca 976
4a120d45 977static void
3a8b4109 978parse_action (symbol_list *rule, int rule_length)
1ff442ca 979{
3a8b4109
AD
980 int count = 1;
981 rule->action_line = lineno;
1ff442ca
NF
982 while (count > 0)
983 {
3a8b4109 984 int c;
14d293ac
AD
985 while ((c = getc (finput)) != '}')
986 switch (c)
987 {
988 case '\n':
6390a83f 989 copy_character (&action_obstack, c);
f3849179 990 ++lineno;
14d293ac 991 break;
1ff442ca 992
14d293ac 993 case '{':
6390a83f 994 copy_character (&action_obstack, c);
f3849179 995 ++count;
14d293ac 996 break;
1ff442ca 997
14d293ac
AD
998 case '\'':
999 case '"':
1000 copy_string (finput, &action_obstack, c);
1001 break;
1ff442ca 1002
14d293ac
AD
1003 case '/':
1004 copy_comment (finput, &action_obstack);
1005 break;
1ff442ca 1006
14d293ac 1007 case '$':
82b6cb3f 1008 copy_dollar (finput, &action_obstack, rule, rule_length);
14d293ac 1009 break;
1ff442ca 1010
14d293ac 1011 case '@':
82b6cb3f 1012 copy_at (finput, &action_obstack, rule_length);
14d293ac 1013 break;
a70083a3 1014
14d293ac
AD
1015 case EOF:
1016 fatal (_("unmatched %s"), "`{'");
a70083a3 1017
14d293ac 1018 default:
6390a83f 1019 copy_character (&action_obstack, c);
14d293ac 1020 }
a70083a3 1021
14d293ac 1022 /* Above loop exits when C is '}'. */
a70083a3 1023 if (--count)
6390a83f 1024 copy_character (&action_obstack, c);
a70083a3
AD
1025 }
1026
3f96f4dc 1027 obstack_1grow (&action_obstack, '\0');
14d293ac
AD
1028 rule->action = obstack_finish (&action_obstack);
1029}
a70083a3 1030
a70083a3
AD
1031\f
1032
a70083a3
AD
1033/*-------------------------------------------------------------------.
1034| Generate a dummy symbol, a nonterminal, whose name cannot conflict |
1035| with the user's names. |
1036`-------------------------------------------------------------------*/
1ff442ca 1037
db8837cb 1038static symbol_t *
118fb205 1039gensym (void)
1ff442ca 1040{
274d42ce
AD
1041 /* Incremented for each generated symbol */
1042 static int gensym_count = 0;
1043 static char buf[256];
1044
db8837cb 1045 symbol_t *sym;
1ff442ca 1046
274d42ce
AD
1047 sprintf (buf, "@%d", ++gensym_count);
1048 token_buffer = buf;
a70083a3 1049 sym = getsym (token_buffer);
d7020c20 1050 sym->class = nterm_sym;
d9b739c3 1051 sym->number = nvars++;
36281465 1052 return sym;
1ff442ca 1053}
a70083a3 1054\f
107f7dfb
AD
1055/*-------------------------------------------------------------------.
1056| Parse the input grammar into a one symbol_list structure. Each |
1057| rule is represented by a sequence of symbols: the left hand side |
1058| followed by the contents of the right hand side, followed by a |
1059| null pointer instead of a symbol to terminate the rule. The next |
1060| symbol is the lhs of the following rule. |
1061| |
fdbcd8e2
AD
1062| All actions are copied out, labelled by the rule number they apply |
1063| to. |
107f7dfb
AD
1064| |
1065| Bison used to allow some %directives in the rules sections, but |
1066| this is no longer consider appropriate: (i) the documented grammar |
1067| doesn't claim it, (ii), it would promote bad style, (iii), error |
1068| recovery for %directives consists in skipping the junk until a `%' |
1069| is seen and helrp synchronizing. This scheme is definitely wrong |
1070| in the rules section. |
1071`-------------------------------------------------------------------*/
1ff442ca 1072
f6d0f937
AD
1073/* The (currently) last symbol of GRAMMAR. */
1074symbol_list *grammar_end = NULL;
1075
1076/* Append S to the GRAMMAR. */
1077static void
1078grammar_symbol_append (symbol_t *s)
1079{
1080 symbol_list *p = symbol_list_new (s);
1081
1082 if (grammar_end)
1083 grammar_end->next = p;
1084 else
1085 grammar = p;
1086
1087 grammar_end = p;
1088}
1089
da4160c3
AD
1090/* The rule currently being defined, and the previous rule. Point to
1091 the first symbol of each list: their lhs. */
1092symbol_list *current_rule = NULL;
1093symbol_list *previous_rule = NULL;
1094
1095
1096/* Create a new rule for LHS in to the GRAMMAR. */
1097
1098static void
1099grammar_rule_begin (symbol_t *lhs)
1100{
1101 if (!start_flag)
1102 {
1103 startsymbol = lhs;
1104 start_flag = 1;
1105 }
1106
1107 /* Start a new rule and record its lhs. */
1108 ++nrules;
1109 ++nritems;
1110
1111 previous_rule = grammar_end;
1112 grammar_symbol_append (lhs);
1113 current_rule = grammar_end;
1114
1115 /* Mark the rule's lhs as a nonterminal if not already so. */
1116
1117 if (lhs->class == unknown_sym)
1118 {
1119 lhs->class = nterm_sym;
1120 lhs->number = nvars;
1121 ++nvars;
1122 }
1123 else if (lhs->class == token_sym)
1124 complain (_("rule given for %s, which is a token"), lhs->tag);
1125}
1126
1485e106
AD
1127/* The previous action turns out the be a mid-rule action. Attach it
1128 to the current rule, i.e., create a dummy symbol, attach it this
1129 mid-rule action, and append this dummy nonterminal to the current
1130 rule. */
1131
1132static void
1133grammar_midrule_action (void)
1134{
1135 /* Since the action was written out with this rule's number, we must
1136 give the new rule this number by inserting the new rule before
1137 it. */
1138
1139 /* Make a dummy nonterminal, a gensym. */
1140 symbol_t *sdummy = gensym ();
1141 symbol_list *midrule_action = symbol_list_new (sdummy);
1142
1143 /* Make a new rule, whose body is empty, before the current one, so
1144 that the action just read can belong to it. */
1145 ++nrules;
1146 ++nritems;
1147 /* Attach its lineno to that of the host rule. */
1148 midrule_action->line = current_rule->line;
1149 /* Move the action from the host rule to this one. */
1150 midrule_action->action = current_rule->action;
1151 midrule_action->action_line = current_rule->action_line;
1152 current_rule->action = NULL;
1153
1154 if (previous_rule)
1155 previous_rule->next = midrule_action;
1156 else
1157 grammar = midrule_action;
1158
1159 /* End of the rule. */
1160 previous_rule = symbol_list_new (NULL);
1161 previous_rule->next = current_rule;
1162
1163 midrule_action->next = previous_rule;
1164
1165 /* Insert the dummy generated by that rule into this rule. */
1166 ++nritems;
1167 grammar_symbol_append (sdummy);
1168}
1169
9af3fbce
AD
1170/* Set the precedence symbol of the current rule to PRECSYM. */
1171
1172static void
1173grammar_current_rule_prec_set (symbol_t *precsym)
1174{
1175 if (current_rule->ruleprec)
1176 complain (_("two @prec's in a row"));
1177 current_rule->ruleprec = precsym;
1178}
1179
1180/* Check that the last rule (CURRENT_RULE) is properly defined. For
1181 instance, there should be no type clash on the default action. */
1182
1183static void
1184grammar_current_rule_check (void)
1185{
1186 symbol_t *lhs = current_rule->sym;
1187 symbol_t *first_rhs = current_rule->next->sym;
1188
1189 /* If there is an action, then there is nothing we can do: the user
1190 is allowed to shoot in her foot. */
1191 if (current_rule->action)
1192 return;
1193
1194 /* If $$ is being set in default way, report if any type mismatch.
1195 */
1196 if (first_rhs)
1197 {
1198 const char *lhs_type = lhs->type_name ? lhs->type_name : "";
1199 const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : "";
1200 if (strcmp (lhs_type, rhs_type))
1201 complain (_("type clash (`%s' `%s') on default action"),
1202 lhs_type, rhs_type);
1203 }
1204 /* Warn if there is no default for $$ but we need one. */
1205 else
1206 {
1207 if (lhs->type_name)
1208 complain (_("empty rule for typed nonterminal, and no action"));
1209 }
1210}
1211
1485e106 1212
4a120d45 1213static void
118fb205 1214readgram (void)
1ff442ca 1215{
f17bcd1f 1216 token_t t;
db8837cb 1217 symbol_t *lhs = NULL;
1ff442ca 1218
a70083a3 1219 t = lex ();
1ff442ca 1220
511e79b3 1221 while (t != tok_two_percents && t != tok_eof)
107f7dfb
AD
1222 if (t == tok_identifier || t == tok_bar)
1223 {
1224 int action_flag = 0;
1225 /* Number of symbols in rhs of this rule so far */
1226 int rulelength = 0;
107f7dfb
AD
1227
1228 if (t == tok_identifier)
1229 {
1230 lhs = symval;
1231
107f7dfb
AD
1232 t = lex ();
1233 if (t != tok_colon)
1234 {
1235 complain (_("ill-formed rule: initial symbol not followed by colon"));
1236 unlex (t);
1237 }
1238 }
107f7dfb
AD
1239 if (nrules == 0 && t == tok_bar)
1240 {
1241 complain (_("grammar starts with vertical bar"));
1242 lhs = symval; /* BOGUS: use a random symval */
1243 }
1ff442ca 1244
da4160c3 1245 grammar_rule_begin (lhs);
107f7dfb 1246 /* read the rhs of the rule. */
1ff442ca 1247
107f7dfb
AD
1248 for (;;)
1249 {
1250 t = lex ();
1251 if (t == tok_prec)
1252 {
1253 t = lex ();
9af3fbce 1254 grammar_current_rule_prec_set (symval);
107f7dfb
AD
1255 t = lex ();
1256 }
1257
1258 if (!(t == tok_identifier || t == tok_left_curly))
1259 break;
1ff442ca 1260
107f7dfb
AD
1261 /* If next token is an identifier, see if a colon follows it.
1262 If one does, exit this rule now. */
1263 if (t == tok_identifier)
1264 {
db8837cb 1265 symbol_t *ssave;
107f7dfb
AD
1266 token_t t1;
1267
1268 ssave = symval;
1269 t1 = lex ();
1270 unlex (t1);
1271 symval = ssave;
1272 if (t1 == tok_colon)
e5352bc7 1273 {
fff9bf0b 1274 warn (_("previous rule lacks an ending `;'"));
e5352bc7
AD
1275 break;
1276 }
9af3fbce
AD
1277 /* Not followed by colon => process as part of this
1278 rule's rhs. */
107f7dfb
AD
1279 }
1280
1281 /* If we just passed an action, that action was in the middle
1282 of a rule, so make a dummy rule to reduce it to a
1283 non-terminal. */
1284 if (action_flag)
1285 {
1485e106 1286 grammar_midrule_action ();
107f7dfb
AD
1287 action_flag = 0;
1288 }
1289
1290 if (t == tok_identifier)
1291 {
5123689b 1292 ++nritems;
f6d0f937 1293 grammar_symbol_append (symval);
107f7dfb
AD
1294 }
1295 else /* handle an action. */
1296 {
da4160c3 1297 parse_action (current_rule, rulelength);
107f7dfb 1298 action_flag = 1;
107f7dfb 1299 }
f3849179 1300 ++rulelength;
107f7dfb
AD
1301 } /* end of read rhs of rule */
1302
1303 /* Put an empty link in the list to mark the end of this rule */
f6d0f937 1304 grammar_symbol_append (NULL);
107f7dfb
AD
1305
1306 if (t == tok_prec)
1307 {
107f7dfb 1308 t = lex ();
9af3fbce 1309 grammar_current_rule_prec_set (symval);
107f7dfb
AD
1310 t = lex ();
1311 }
f499b062 1312
f499b062 1313 if (t == tok_left_curly)
107f7dfb 1314 {
da4160c3 1315 parse_action (current_rule, rulelength);
107f7dfb 1316 action_flag = 1;
107f7dfb
AD
1317 t = lex ();
1318 }
9af3fbce
AD
1319
1320 grammar_current_rule_check ();
1321
bfcf1f3a 1322 if (t == tok_two_percents || t == tok_eof)
fff9bf0b 1323 warn (_("previous rule lacks an ending `;'"));
107f7dfb 1324 if (t == tok_semicolon)
a70083a3 1325 t = lex ();
107f7dfb
AD
1326 }
1327 else
1328 {
1329 complain (_("invalid input: %s"), quote (token_buffer));
1330 t = lex ();
1331 }
943819bf 1332
b68e7744
AD
1333 /* grammar has been read. Do some checking */
1334
1335 if (nrules == 0)
1336 fatal (_("no rules in the input grammar"));
1337
1338 /* Report any undefined symbols and consider them nonterminals. */
2f1afb73 1339 symbols_check_defined ();
b68e7744 1340
ff442794
AD
1341 /* Insert the initial rule, which line is that of the first rule
1342 (not that of the start symbol):
30171f79
AD
1343
1344 axiom: %start EOF. */
f6d0f937
AD
1345 {
1346 symbol_list *p = symbol_list_new (axiom);
1347 p->line = grammar->line;
1348 p->next = symbol_list_new (startsymbol);
1349 p->next->next = symbol_list_new (eoftoken);
1350 p->next->next->next = symbol_list_new (NULL);
1351 p->next->next->next->next = grammar;
1352 nrules += 1;
1353 nritems += 3;
1354 grammar = p;
1355 }
1ff442ca 1356
62a3e4f0 1357 if (nsyms > SHRT_MAX)
a0f6b076 1358 fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
62a3e4f0 1359 SHRT_MAX);
1ff442ca 1360
72a23c97 1361 assert (nsyms == ntokens + nvars);
1ff442ca 1362}
ff48177d
MA
1363
1364/* At the end of the grammar file, some C source code must
63c2d5de 1365 be stored. It is going to be associated to the epilogue
ff48177d
MA
1366 directive. */
1367static void
1368read_additionnal_code (void)
1369{
9101a310 1370 int c;
63c2d5de 1371 struct obstack el_obstack;
342b8b6e 1372
63c2d5de 1373 obstack_init (&el_obstack);
ff48177d 1374
710ddc4f
MA
1375 if (!no_lines_flag)
1376 {
1377 obstack_fgrow2 (&el_obstack, muscle_find ("linef"),
1378 lineno, quotearg_style (c_quoting_style,
b7c49edf 1379 muscle_find ("filename")));
710ddc4f
MA
1380 }
1381
ff48177d 1382 while ((c = getc (finput)) != EOF)
2b7ed18a 1383 copy_character (&el_obstack, c);
342b8b6e 1384
63c2d5de 1385 obstack_1grow (&el_obstack, 0);
11d82f03 1386 muscle_insert ("epilogue", obstack_finish (&el_obstack));
ff48177d
MA
1387}
1388
a70083a3 1389\f
a70083a3
AD
1390/*---------------------------------------------------------------.
1391| Convert the rules into the representation using RRHS, RLHS and |
d9b739c3 1392| RITEM. |
a70083a3 1393`---------------------------------------------------------------*/
1ff442ca 1394
4a120d45 1395static void
118fb205 1396packgram (void)
1ff442ca 1397{
0c2d3f4c 1398 unsigned int itemno;
a70083a3
AD
1399 int ruleno;
1400 symbol_list *p;
1ff442ca 1401
a900a624 1402 ritem = XCALLOC (item_number_t, nritems);
1a2b5d37 1403 rules = XCALLOC (rule_t, nrules) - 1;
1ff442ca
NF
1404
1405 itemno = 0;
1406 ruleno = 1;
1407
1408 p = grammar;
1409 while (p)
1410 {
db8837cb 1411 symbol_t *ruleprec = p->ruleprec;
d7e1f00c 1412 rules[ruleno].user_number = ruleno;
c3b407f4 1413 rules[ruleno].number = ruleno;
bba97eb2 1414 rules[ruleno].lhs = p->sym;
99013900 1415 rules[ruleno].rhs = ritem + itemno;
1a2b5d37
AD
1416 rules[ruleno].line = p->line;
1417 rules[ruleno].useful = TRUE;
1418 rules[ruleno].action = p->action;
1419 rules[ruleno].action_line = p->action_line;
1ff442ca
NF
1420
1421 p = p->next;
1422 while (p && p->sym)
1423 {
a49aecd5 1424 /* item_number_t = symbol_number_t.
5fbb0954 1425 But the former needs to contain more: negative rule numbers. */
a49aecd5 1426 ritem[itemno++] = symbol_number_as_item_number (p->sym->number);
1ff442ca
NF
1427 /* A rule gets by default the precedence and associativity
1428 of the last token in it. */
d7020c20 1429 if (p->sym->class == token_sym)
03b31c0c 1430 rules[ruleno].prec = p->sym;
a70083a3
AD
1431 if (p)
1432 p = p->next;
1ff442ca
NF
1433 }
1434
1435 /* If this rule has a %prec,
a70083a3 1436 the specified symbol's precedence replaces the default. */
1ff442ca
NF
1437 if (ruleprec)
1438 {
03b31c0c
AD
1439 rules[ruleno].precsym = ruleprec;
1440 rules[ruleno].prec = ruleprec;
1ff442ca 1441 }
1ff442ca 1442 ritem[itemno++] = -ruleno;
f3849179 1443 ++ruleno;
1ff442ca 1444
a70083a3
AD
1445 if (p)
1446 p = p->next;
1ff442ca
NF
1447 }
1448
5123689b 1449 assert (itemno == nritems);
3067fbef
AD
1450
1451 if (trace_flag)
1452 ritem_print (stderr);
1ff442ca 1453}
a70083a3 1454\f
fdbcd8e2
AD
1455/*------------------------------------------------------------------.
1456| Read in the grammar specification and record it in the format |
1457| described in gram.h. All actions are copied into ACTION_OBSTACK, |
1458| in each case forming the body of a C function (YYACTION) which |
1459| contains a switch statement to decide which action to execute. |
1460`------------------------------------------------------------------*/
a70083a3
AD
1461
1462void
1463reader (void)
1464{
342b8b6e 1465 lex_init ();
a70083a3
AD
1466 lineno = 1;
1467
11d82f03
MA
1468 /* Initialize the muscle obstack. */
1469 obstack_init (&muscle_obstack);
82e236e2 1470
a70083a3 1471 /* Initialize the symbol table. */
db8837cb 1472 symbols_new ();
b6610515 1473
30171f79
AD
1474 /* Construct the axiom symbol. */
1475 axiom = getsym ("$axiom");
1476 axiom->class = nterm_sym;
d9b739c3 1477 axiom->number = nvars++;
30171f79 1478
a70083a3
AD
1479 /* Construct the error token */
1480 errtoken = getsym ("error");
d7020c20 1481 errtoken->class = token_sym;
72a23c97 1482 errtoken->number = ntokens++;
b6610515 1483
a70083a3
AD
1484 /* Construct a token that represents all undefined literal tokens.
1485 It is always token number 2. */
1486 undeftoken = getsym ("$undefined.");
d7020c20 1487 undeftoken->class = token_sym;
72a23c97 1488 undeftoken->number = ntokens++;
a70083a3 1489
331dbc1b
AD
1490 /* Initialize the obstacks. */
1491 obstack_init (&action_obstack);
331dbc1b 1492 obstack_init (&output_obstack);
0dd1580a
RA
1493 obstack_init (&pre_prologue_obstack);
1494 obstack_init (&post_prologue_obstack);
331dbc1b
AD
1495
1496 finput = xfopen (infile, "r");
1497
896fe5c1
AD
1498 /* Read the declaration section. Copy %{ ... %} groups to
1499 TABLE_OBSTACK and FDEFINES file. Also notice any %token, %left,
1500 etc. found there. */
a70083a3 1501 read_declarations ();
b7c49edf
AD
1502
1503 /* If the user did not define her EOFTOKEN, do it now. */
1504 if (!eoftoken)
1505 {
1506 eoftoken = getsym ("$");
1507 eoftoken->class = token_sym;
72a23c97 1508 eoftoken->number = 0;
b7c49edf
AD
1509 /* Value specified by POSIX. */
1510 eoftoken->user_token_number = 0;
1511 }
1512
a70083a3 1513 /* Read in the grammar, build grammar in list form. Write out
fdbcd8e2 1514 actions. */
a70083a3 1515 readgram ();
ff48177d
MA
1516 /* Some C code is given at the end of the grammar file. */
1517 read_additionnal_code ();
b0c4483e 1518
331dbc1b
AD
1519 lex_free ();
1520 xfclose (finput);
1521
a70083a3
AD
1522 /* Assign the symbols their symbol numbers. Write #defines for the
1523 token symbols into FDEFINES if requested. */
2f1afb73 1524 symbols_pack ();
93ede233 1525
a70083a3
AD
1526 /* Convert the grammar into the format described in gram.h. */
1527 packgram ();
8419d367
AD
1528
1529 /* The grammar as a symbol_list is no longer needed. */
1530 LIST_FREE (symbol_list, grammar);
a70083a3 1531}