]> git.saurik.com Git - bison.git/blame - src/reader.c
* src/reader.c (grammar_midrule_action): New, Eved out from
[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
f6d0f937
AD
1075/* The (currently) last symbol of GRAMMAR. */
1076symbol_list *grammar_end = NULL;
1077
1078/* Append S to the GRAMMAR. */
1079static void
1080grammar_symbol_append (symbol_t *s)
1081{
1082 symbol_list *p = symbol_list_new (s);
1083
1084 if (grammar_end)
1085 grammar_end->next = p;
1086 else
1087 grammar = p;
1088
1089 grammar_end = p;
1090}
1091
da4160c3
AD
1092/* The rule currently being defined, and the previous rule. Point to
1093 the first symbol of each list: their lhs. */
1094symbol_list *current_rule = NULL;
1095symbol_list *previous_rule = NULL;
1096
1097
1098/* Create a new rule for LHS in to the GRAMMAR. */
1099
1100static void
1101grammar_rule_begin (symbol_t *lhs)
1102{
1103 if (!start_flag)
1104 {
1105 startsymbol = lhs;
1106 start_flag = 1;
1107 }
1108
1109 /* Start a new rule and record its lhs. */
1110 ++nrules;
1111 ++nritems;
1112
1113 previous_rule = grammar_end;
1114 grammar_symbol_append (lhs);
1115 current_rule = grammar_end;
1116
1117 /* Mark the rule's lhs as a nonterminal if not already so. */
1118
1119 if (lhs->class == unknown_sym)
1120 {
1121 lhs->class = nterm_sym;
1122 lhs->number = nvars;
1123 ++nvars;
1124 }
1125 else if (lhs->class == token_sym)
1126 complain (_("rule given for %s, which is a token"), lhs->tag);
1127}
1128
1485e106
AD
1129/* The previous action turns out the be a mid-rule action. Attach it
1130 to the current rule, i.e., create a dummy symbol, attach it this
1131 mid-rule action, and append this dummy nonterminal to the current
1132 rule. */
1133
1134static void
1135grammar_midrule_action (void)
1136{
1137 /* Since the action was written out with this rule's number, we must
1138 give the new rule this number by inserting the new rule before
1139 it. */
1140
1141 /* Make a dummy nonterminal, a gensym. */
1142 symbol_t *sdummy = gensym ();
1143 symbol_list *midrule_action = symbol_list_new (sdummy);
1144
1145 /* Make a new rule, whose body is empty, before the current one, so
1146 that the action just read can belong to it. */
1147 ++nrules;
1148 ++nritems;
1149 /* Attach its lineno to that of the host rule. */
1150 midrule_action->line = current_rule->line;
1151 /* Move the action from the host rule to this one. */
1152 midrule_action->action = current_rule->action;
1153 midrule_action->action_line = current_rule->action_line;
1154 current_rule->action = NULL;
1155
1156 if (previous_rule)
1157 previous_rule->next = midrule_action;
1158 else
1159 grammar = midrule_action;
1160
1161 /* End of the rule. */
1162 previous_rule = symbol_list_new (NULL);
1163 previous_rule->next = current_rule;
1164
1165 midrule_action->next = previous_rule;
1166
1167 /* Insert the dummy generated by that rule into this rule. */
1168 ++nritems;
1169 grammar_symbol_append (sdummy);
1170}
1171
1172
4a120d45 1173static void
118fb205 1174readgram (void)
1ff442ca 1175{
f17bcd1f 1176 token_t t;
db8837cb 1177 symbol_t *lhs = NULL;
1ff442ca 1178
a70083a3 1179 t = lex ();
1ff442ca 1180
511e79b3 1181 while (t != tok_two_percents && t != tok_eof)
107f7dfb
AD
1182 if (t == tok_identifier || t == tok_bar)
1183 {
1184 int action_flag = 0;
1185 /* Number of symbols in rhs of this rule so far */
1186 int rulelength = 0;
1187 int xactions = 0; /* JF for error checking */
db8837cb 1188 symbol_t *first_rhs = 0;
107f7dfb
AD
1189
1190 if (t == tok_identifier)
1191 {
1192 lhs = symval;
1193
107f7dfb
AD
1194 t = lex ();
1195 if (t != tok_colon)
1196 {
1197 complain (_("ill-formed rule: initial symbol not followed by colon"));
1198 unlex (t);
1199 }
1200 }
107f7dfb
AD
1201 if (nrules == 0 && t == tok_bar)
1202 {
1203 complain (_("grammar starts with vertical bar"));
1204 lhs = symval; /* BOGUS: use a random symval */
1205 }
1ff442ca 1206
da4160c3 1207 grammar_rule_begin (lhs);
107f7dfb 1208 /* read the rhs of the rule. */
1ff442ca 1209
107f7dfb
AD
1210 for (;;)
1211 {
1212 t = lex ();
1213 if (t == tok_prec)
1214 {
1215 t = lex ();
da4160c3 1216 current_rule->ruleprec = symval;
107f7dfb
AD
1217 t = lex ();
1218 }
1219
1220 if (!(t == tok_identifier || t == tok_left_curly))
1221 break;
1ff442ca 1222
107f7dfb
AD
1223 /* If next token is an identifier, see if a colon follows it.
1224 If one does, exit this rule now. */
1225 if (t == tok_identifier)
1226 {
db8837cb 1227 symbol_t *ssave;
107f7dfb
AD
1228 token_t t1;
1229
1230 ssave = symval;
1231 t1 = lex ();
1232 unlex (t1);
1233 symval = ssave;
1234 if (t1 == tok_colon)
e5352bc7 1235 {
fff9bf0b 1236 warn (_("previous rule lacks an ending `;'"));
e5352bc7
AD
1237 break;
1238 }
107f7dfb
AD
1239
1240 if (!first_rhs) /* JF */
1241 first_rhs = symval;
1242 /* Not followed by colon =>
1243 process as part of this rule's rhs. */
1244 }
1245
1246 /* If we just passed an action, that action was in the middle
1247 of a rule, so make a dummy rule to reduce it to a
1248 non-terminal. */
1249 if (action_flag)
1250 {
1485e106 1251 grammar_midrule_action ();
107f7dfb
AD
1252 action_flag = 0;
1253 }
1254
1255 if (t == tok_identifier)
1256 {
5123689b 1257 ++nritems;
f6d0f937 1258 grammar_symbol_append (symval);
107f7dfb
AD
1259 }
1260 else /* handle an action. */
1261 {
da4160c3 1262 parse_action (current_rule, rulelength);
107f7dfb 1263 action_flag = 1;
f3849179 1264 ++xactions; /* JF */
107f7dfb 1265 }
f3849179 1266 ++rulelength;
107f7dfb
AD
1267 } /* end of read rhs of rule */
1268
1269 /* Put an empty link in the list to mark the end of this rule */
f6d0f937 1270 grammar_symbol_append (NULL);
107f7dfb
AD
1271
1272 if (t == tok_prec)
1273 {
1274 complain (_("two @prec's in a row"));
1275 t = lex ();
da4160c3 1276 current_rule->ruleprec = symval;
107f7dfb
AD
1277 t = lex ();
1278 }
f499b062 1279
f499b062 1280 if (t == tok_left_curly)
107f7dfb
AD
1281 {
1282 /* This case never occurs -wjh */
1283 if (action_flag)
1284 complain (_("two actions at end of one rule"));
da4160c3 1285 parse_action (current_rule, rulelength);
107f7dfb 1286 action_flag = 1;
f3849179 1287 ++xactions; /* -wjh */
107f7dfb
AD
1288 t = lex ();
1289 }
1290 /* If $$ is being set in default way, report if any type
1291 mismatch. */
1292 else if (!xactions
1293 && first_rhs && lhs->type_name != first_rhs->type_name)
1294 {
1295 if (lhs->type_name == 0
1296 || first_rhs->type_name == 0
1297 || strcmp (lhs->type_name, first_rhs->type_name))
1298 complain (_("type clash (`%s' `%s') on default action"),
1299 lhs->type_name ? lhs->type_name : "",
1300 first_rhs->type_name ? first_rhs->type_name : "");
1301 }
1302 /* Warn if there is no default for $$ but we need one. */
1303 else if (!xactions && !first_rhs && lhs->type_name != 0)
1304 complain (_("empty rule for typed nonterminal, and no action"));
bfcf1f3a 1305 if (t == tok_two_percents || t == tok_eof)
fff9bf0b 1306 warn (_("previous rule lacks an ending `;'"));
107f7dfb 1307 if (t == tok_semicolon)
a70083a3 1308 t = lex ();
107f7dfb
AD
1309 }
1310 else
1311 {
1312 complain (_("invalid input: %s"), quote (token_buffer));
1313 t = lex ();
1314 }
943819bf 1315
b68e7744
AD
1316 /* grammar has been read. Do some checking */
1317
1318 if (nrules == 0)
1319 fatal (_("no rules in the input grammar"));
1320
1321 /* Report any undefined symbols and consider them nonterminals. */
2f1afb73 1322 symbols_check_defined ();
b68e7744 1323
ff442794
AD
1324 /* Insert the initial rule, which line is that of the first rule
1325 (not that of the start symbol):
30171f79
AD
1326
1327 axiom: %start EOF. */
f6d0f937
AD
1328 {
1329 symbol_list *p = symbol_list_new (axiom);
1330 p->line = grammar->line;
1331 p->next = symbol_list_new (startsymbol);
1332 p->next->next = symbol_list_new (eoftoken);
1333 p->next->next->next = symbol_list_new (NULL);
1334 p->next->next->next->next = grammar;
1335 nrules += 1;
1336 nritems += 3;
1337 grammar = p;
1338 }
1ff442ca 1339
62a3e4f0 1340 if (nsyms > SHRT_MAX)
a0f6b076 1341 fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
62a3e4f0 1342 SHRT_MAX);
1ff442ca 1343
72a23c97 1344 assert (nsyms == ntokens + nvars);
1ff442ca 1345}
ff48177d
MA
1346
1347/* At the end of the grammar file, some C source code must
63c2d5de 1348 be stored. It is going to be associated to the epilogue
ff48177d
MA
1349 directive. */
1350static void
1351read_additionnal_code (void)
1352{
9101a310 1353 int c;
63c2d5de 1354 struct obstack el_obstack;
342b8b6e 1355
63c2d5de 1356 obstack_init (&el_obstack);
ff48177d 1357
710ddc4f
MA
1358 if (!no_lines_flag)
1359 {
1360 obstack_fgrow2 (&el_obstack, muscle_find ("linef"),
1361 lineno, quotearg_style (c_quoting_style,
b7c49edf 1362 muscle_find ("filename")));
710ddc4f
MA
1363 }
1364
ff48177d 1365 while ((c = getc (finput)) != EOF)
2b7ed18a 1366 copy_character (&el_obstack, c);
342b8b6e 1367
63c2d5de 1368 obstack_1grow (&el_obstack, 0);
11d82f03 1369 muscle_insert ("epilogue", obstack_finish (&el_obstack));
ff48177d
MA
1370}
1371
a70083a3 1372\f
a70083a3
AD
1373/*---------------------------------------------------------------.
1374| Convert the rules into the representation using RRHS, RLHS and |
d9b739c3 1375| RITEM. |
a70083a3 1376`---------------------------------------------------------------*/
1ff442ca 1377
4a120d45 1378static void
118fb205 1379packgram (void)
1ff442ca 1380{
0c2d3f4c 1381 unsigned int itemno;
a70083a3
AD
1382 int ruleno;
1383 symbol_list *p;
1ff442ca 1384
a900a624 1385 ritem = XCALLOC (item_number_t, nritems);
1a2b5d37 1386 rules = XCALLOC (rule_t, nrules) - 1;
1ff442ca
NF
1387
1388 itemno = 0;
1389 ruleno = 1;
1390
1391 p = grammar;
1392 while (p)
1393 {
db8837cb 1394 symbol_t *ruleprec = p->ruleprec;
d7e1f00c 1395 rules[ruleno].user_number = ruleno;
c3b407f4 1396 rules[ruleno].number = ruleno;
bba97eb2 1397 rules[ruleno].lhs = p->sym;
99013900 1398 rules[ruleno].rhs = ritem + itemno;
1a2b5d37
AD
1399 rules[ruleno].line = p->line;
1400 rules[ruleno].useful = TRUE;
1401 rules[ruleno].action = p->action;
1402 rules[ruleno].action_line = p->action_line;
1ff442ca
NF
1403
1404 p = p->next;
1405 while (p && p->sym)
1406 {
a49aecd5 1407 /* item_number_t = symbol_number_t.
5fbb0954 1408 But the former needs to contain more: negative rule numbers. */
a49aecd5 1409 ritem[itemno++] = symbol_number_as_item_number (p->sym->number);
1ff442ca
NF
1410 /* A rule gets by default the precedence and associativity
1411 of the last token in it. */
d7020c20 1412 if (p->sym->class == token_sym)
03b31c0c 1413 rules[ruleno].prec = p->sym;
a70083a3
AD
1414 if (p)
1415 p = p->next;
1ff442ca
NF
1416 }
1417
1418 /* If this rule has a %prec,
a70083a3 1419 the specified symbol's precedence replaces the default. */
1ff442ca
NF
1420 if (ruleprec)
1421 {
03b31c0c
AD
1422 rules[ruleno].precsym = ruleprec;
1423 rules[ruleno].prec = ruleprec;
1ff442ca 1424 }
1ff442ca 1425 ritem[itemno++] = -ruleno;
f3849179 1426 ++ruleno;
1ff442ca 1427
a70083a3
AD
1428 if (p)
1429 p = p->next;
1ff442ca
NF
1430 }
1431
5123689b 1432 assert (itemno == nritems);
3067fbef
AD
1433
1434 if (trace_flag)
1435 ritem_print (stderr);
1ff442ca 1436}
a70083a3 1437\f
fdbcd8e2
AD
1438/*------------------------------------------------------------------.
1439| Read in the grammar specification and record it in the format |
1440| described in gram.h. All actions are copied into ACTION_OBSTACK, |
1441| in each case forming the body of a C function (YYACTION) which |
1442| contains a switch statement to decide which action to execute. |
1443`------------------------------------------------------------------*/
a70083a3
AD
1444
1445void
1446reader (void)
1447{
342b8b6e 1448 lex_init ();
a70083a3
AD
1449 lineno = 1;
1450
11d82f03
MA
1451 /* Initialize the muscle obstack. */
1452 obstack_init (&muscle_obstack);
82e236e2 1453
a70083a3 1454 /* Initialize the symbol table. */
db8837cb 1455 symbols_new ();
b6610515 1456
30171f79
AD
1457 /* Construct the axiom symbol. */
1458 axiom = getsym ("$axiom");
1459 axiom->class = nterm_sym;
d9b739c3 1460 axiom->number = nvars++;
30171f79 1461
a70083a3
AD
1462 /* Construct the error token */
1463 errtoken = getsym ("error");
d7020c20 1464 errtoken->class = token_sym;
72a23c97 1465 errtoken->number = ntokens++;
b6610515 1466
a70083a3
AD
1467 /* Construct a token that represents all undefined literal tokens.
1468 It is always token number 2. */
1469 undeftoken = getsym ("$undefined.");
d7020c20 1470 undeftoken->class = token_sym;
72a23c97 1471 undeftoken->number = ntokens++;
a70083a3 1472
331dbc1b
AD
1473 /* Initialize the obstacks. */
1474 obstack_init (&action_obstack);
331dbc1b 1475 obstack_init (&output_obstack);
0dd1580a
RA
1476 obstack_init (&pre_prologue_obstack);
1477 obstack_init (&post_prologue_obstack);
331dbc1b
AD
1478
1479 finput = xfopen (infile, "r");
1480
896fe5c1
AD
1481 /* Read the declaration section. Copy %{ ... %} groups to
1482 TABLE_OBSTACK and FDEFINES file. Also notice any %token, %left,
1483 etc. found there. */
a70083a3 1484 read_declarations ();
b7c49edf
AD
1485
1486 /* If the user did not define her EOFTOKEN, do it now. */
1487 if (!eoftoken)
1488 {
1489 eoftoken = getsym ("$");
1490 eoftoken->class = token_sym;
72a23c97 1491 eoftoken->number = 0;
b7c49edf
AD
1492 /* Value specified by POSIX. */
1493 eoftoken->user_token_number = 0;
1494 }
1495
a70083a3 1496 /* Read in the grammar, build grammar in list form. Write out
fdbcd8e2 1497 actions. */
a70083a3 1498 readgram ();
ff48177d
MA
1499 /* Some C code is given at the end of the grammar file. */
1500 read_additionnal_code ();
b0c4483e 1501
331dbc1b
AD
1502 lex_free ();
1503 xfclose (finput);
1504
a70083a3
AD
1505 /* Assign the symbols their symbol numbers. Write #defines for the
1506 token symbols into FDEFINES if requested. */
2f1afb73 1507 symbols_pack ();
93ede233 1508
a70083a3
AD
1509 /* Convert the grammar into the format described in gram.h. */
1510 packgram ();
8419d367
AD
1511
1512 /* The grammar as a symbol_list is no longer needed. */
1513 LIST_FREE (symbol_list, grammar);
a70083a3 1514}