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