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