]> git.saurik.com Git - bison.git/blob - src/reader.c
* configure.in: Check the protos of strchr ans strspn.
[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;
72 static bucket *undeftoken;
73
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 }
577 else
578 {
579 complain (_("`%s' is invalid in %s"),
580 token_buffer,
581 (what_is == token_sym) ? "%token" : "%nterm");
582 skip_to_char ('%');
583 }
584 }
585
586 }
587
588
589 /*------------------------------.
590 | Parse what comes after %start |
591 `------------------------------*/
592
593 static void
594 parse_start_decl (void)
595 {
596 if (start_flag)
597 complain (_("multiple %s declarations"), "%start");
598 if (lex () != tok_identifier)
599 complain (_("invalid %s declaration"), "%start");
600 else
601 {
602 start_flag = 1;
603 startval = symval;
604 }
605 }
606
607 /*-----------------------------------------------------------.
608 | read in a %type declaration and record its information for |
609 | get_type_name to access |
610 `-----------------------------------------------------------*/
611
612 static void
613 parse_type_decl (void)
614 {
615 char *name;
616
617 if (lex () != tok_typename)
618 {
619 complain ("%s", _("%type declaration has no <typename>"));
620 skip_to_char ('%');
621 return;
622 }
623
624 name = xstrdup (token_buffer);
625
626 for (;;)
627 {
628 token_t t;
629 int tmp_char = ungetc (skip_white_space (), finput);
630
631 if (tmp_char == '%')
632 return;
633 if (tmp_char == EOF)
634 fatal (_("Premature EOF after %s"), token_buffer);
635
636 t = lex ();
637
638 switch (t)
639 {
640
641 case tok_comma:
642 case tok_semicolon:
643 break;
644
645 case tok_identifier:
646 if (symval->type_name == NULL)
647 symval->type_name = name;
648 else if (strcmp (name, symval->type_name) != 0)
649 complain (_("type redeclaration for %s"), symval->tag);
650
651 break;
652
653 default:
654 complain (_("invalid %%type declaration due to item: %s"),
655 token_buffer);
656 skip_to_char ('%');
657 }
658 }
659 }
660
661
662
663 /*----------------------------------------------------------------.
664 | Read in a %left, %right or %nonassoc declaration and record its |
665 | information. |
666 `----------------------------------------------------------------*/
667
668 static void
669 parse_assoc_decl (associativity assoc)
670 {
671 char *name = NULL;
672 int prev = 0;
673
674 lastprec++; /* Assign a new precedence level, never 0. */
675
676 for (;;)
677 {
678 token_t t;
679 int tmp_char = ungetc (skip_white_space (), finput);
680
681 if (tmp_char == '%')
682 return;
683 if (tmp_char == EOF)
684 fatal (_("Premature EOF after %s"), token_buffer);
685
686 t = lex ();
687
688 switch (t)
689 {
690 case tok_typename:
691 name = xstrdup (token_buffer);
692 break;
693
694 case tok_comma:
695 break;
696
697 case tok_identifier:
698 if (symval->prec != 0)
699 complain (_("redefining precedence of %s"), symval->tag);
700 symval->prec = lastprec;
701 symval->assoc = assoc;
702 if (symval->class == nterm_sym)
703 complain (_("symbol %s redefined"), symval->tag);
704 symval->class = token_sym;
705 if (name)
706 { /* record the type, if one is specified */
707 if (symval->type_name == NULL)
708 symval->type_name = name;
709 else if (strcmp (name, symval->type_name) != 0)
710 complain (_("type redeclaration for %s"), symval->tag);
711 }
712 break;
713
714 case tok_number:
715 if (prev == tok_identifier)
716 {
717 symval->user_token_number = numval;
718 }
719 else
720 {
721 complain (_
722 ("invalid text (%s) - number should be after identifier"),
723 token_buffer);
724 skip_to_char ('%');
725 }
726 break;
727
728 case tok_semicolon:
729 return;
730
731 default:
732 complain (_("unexpected item: %s"), token_buffer);
733 skip_to_char ('%');
734 }
735
736 prev = t;
737 }
738 }
739
740
741
742 /*--------------------------------------------------------------.
743 | Copy the union declaration into the stype muscle |
744 | (and fdefines), where it is made into the definition of |
745 | YYSTYPE, the type of elements of the parser value stack. |
746 `--------------------------------------------------------------*/
747
748 static void
749 parse_union_decl (void)
750 {
751 int c;
752 int count = 0;
753 bool done = FALSE;
754 struct obstack union_obstack;
755 if (typed)
756 complain (_("multiple %s declarations"), "%union");
757
758 typed = 1;
759
760 obstack_init (&union_obstack);
761 obstack_sgrow (&union_obstack, "union");
762
763 while (!done)
764 {
765 c = xgetc (finput);
766
767 /* If C contains '/', it is output by copy_comment (). */
768 if (c != '/')
769 obstack_1grow (&union_obstack, c);
770
771 switch (c)
772 {
773 case '\n':
774 lineno++;
775 break;
776
777 case '/':
778 copy_comment (finput, &union_obstack);
779 break;
780
781 case '{':
782 count++;
783 break;
784
785 case '}':
786 /* FIXME: Errr. How could this happen???. --akim */
787 if (count == 0)
788 complain (_("unmatched %s"), "`}'");
789 count--;
790 if (!count)
791 done = TRUE;
792 break;
793 }
794 }
795
796 /* JF don't choke on trailing semi */
797 c = skip_white_space ();
798 if (c != ';')
799 ungetc (c, finput);
800 obstack_1grow (&union_obstack, 0);
801 muscle_insert ("stype", obstack_finish (&union_obstack));
802 }
803
804
805 /*-------------------------------------------------------.
806 | Parse the declaration %expect N which says to expect N |
807 | shift-reduce conflicts. |
808 `-------------------------------------------------------*/
809
810 static void
811 parse_expect_decl (void)
812 {
813 int c = skip_white_space ();
814 ungetc (c, finput);
815
816 if (!isdigit (c))
817 complain (_("argument of %%expect is not an integer"));
818 else
819 expected_conflicts = read_signed_integer (finput);
820 }
821
822
823 /*-------------------------------------------------------------------.
824 | Parse what comes after %thong. the full syntax is |
825 | |
826 | %thong <type> token number literal |
827 | |
828 | the <type> or number may be omitted. The number specifies the |
829 | user_token_number. |
830 | |
831 | Two symbols are entered in the table, one for the token symbol and |
832 | one for the literal. Both are given the <type>, if any, from the |
833 | declaration. The ->user_token_number of the first is SALIAS and |
834 | the ->user_token_number of the second is set to the number, if |
835 | any, from the declaration. The two symbols are linked via |
836 | pointers in their ->alias fields. |
837 | |
838 | During OUTPUT_DEFINES_TABLE, the symbol is reported thereafter, |
839 | only the literal string is retained it is the literal string that |
840 | is output to yytname |
841 `-------------------------------------------------------------------*/
842
843 static void
844 parse_thong_decl (void)
845 {
846 token_t token;
847 struct bucket *symbol;
848 char *typename = 0;
849 int usrtoknum = SUNDEF;
850
851 token = lex (); /* fetch typename or first token */
852 if (token == tok_typename)
853 {
854 typename = xstrdup (token_buffer);
855 value_components_used = 1;
856 token = lex (); /* fetch first token */
857 }
858
859 /* process first token */
860
861 if (token != tok_identifier)
862 {
863 complain (_("unrecognized item %s, expected an identifier"),
864 token_buffer);
865 skip_to_char ('%');
866 return;
867 }
868 symval->class = token_sym;
869 symval->type_name = typename;
870 symval->user_token_number = SALIAS;
871 symbol = symval;
872
873 token = lex (); /* get number or literal string */
874
875 if (token == tok_number)
876 {
877 usrtoknum = numval;
878 token = lex (); /* okay, did number, now get literal */
879 }
880
881 /* process literal string token */
882
883 if (token != tok_identifier || *symval->tag != '\"')
884 {
885 complain (_("expected string constant instead of %s"), token_buffer);
886 skip_to_char ('%');
887 return;
888 }
889 symval->class = token_sym;
890 symval->type_name = typename;
891 symval->user_token_number = usrtoknum;
892
893 symval->alias = symbol;
894 symbol->alias = symval;
895
896 /* symbol and symval combined are only one symbol. */
897 nsyms--;
898 }
899
900
901 static void
902 parse_muscle_decl (void)
903 {
904 int ch = ungetc (skip_white_space (), finput);
905 char* muscle_key;
906 char* muscle_value;
907
908 /* Read key. */
909 if (!isalpha (ch) && ch != '_')
910 {
911 complain (_("invalid %s declaration"), "%define");
912 skip_to_char ('%');
913 return;
914 }
915 copy_identifier (finput, &muscle_obstack);
916 obstack_1grow (&muscle_obstack, 0);
917 muscle_key = obstack_finish (&muscle_obstack);
918
919 /* Read value. */
920 ch = skip_white_space ();
921 if (ch != '"')
922 {
923 ungetc (ch, finput);
924 if (ch != EOF)
925 {
926 complain (_("invalid %s declaration"), "%define");
927 skip_to_char ('%');
928 return;
929 }
930 else
931 fatal (_("Premature EOF after %s"), "\"");
932 }
933 copy_string2 (finput, &muscle_obstack, '"', 0);
934 obstack_1grow (&muscle_obstack, 0);
935 muscle_value = obstack_finish (&muscle_obstack);
936
937 /* Store the (key, value) pair in the environment. */
938 muscle_insert (muscle_key, muscle_value);
939 }
940
941
942
943 /*---------------------------------.
944 | Parse a double quoted parameter. |
945 `---------------------------------*/
946
947 static const char *
948 parse_dquoted_param (const char *from)
949 {
950 struct obstack param_obstack;
951 const char *param = NULL;
952 int c;
953
954 obstack_init (&param_obstack);
955 c = skip_white_space ();
956
957 if (c != '"')
958 {
959 complain (_("invalid %s declaration"), from);
960 ungetc (c, finput);
961 skip_to_char ('%');
962 return NULL;
963 }
964
965 while ((c = literalchar ()) != '"')
966 obstack_1grow (&param_obstack, c);
967
968 obstack_1grow (&param_obstack, '\0');
969 param = obstack_finish (&param_obstack);
970
971 if (c != '"' || strlen (param) == 0)
972 {
973 complain (_("invalid %s declaration"), from);
974 if (c != '"')
975 ungetc (c, finput);
976 skip_to_char ('%');
977 return NULL;
978 }
979
980 return param;
981 }
982
983 /*----------------------------------.
984 | Parse what comes after %skeleton. |
985 `----------------------------------*/
986
987 static void
988 parse_skel_decl (void)
989 {
990 skeleton = parse_dquoted_param ("%skeleton");
991 }
992
993 /*----------------------------------------------------------------.
994 | Read from finput until `%%' is seen. Discard the `%%'. Handle |
995 | any `%' declarations, and copy the contents of any `%{ ... %}' |
996 | groups to ATTRS_OBSTACK. |
997 `----------------------------------------------------------------*/
998
999 static void
1000 read_declarations (void)
1001 {
1002 for (;;)
1003 {
1004 int c = skip_white_space ();
1005
1006 if (c == '%')
1007 {
1008 token_t tok = parse_percent_token ();
1009
1010 switch (tok)
1011 {
1012 case tok_two_percents:
1013 return;
1014
1015 case tok_percent_left_curly:
1016 copy_definition ();
1017 break;
1018
1019 case tok_token:
1020 parse_token_decl (token_sym, nterm_sym);
1021 break;
1022
1023 case tok_nterm:
1024 parse_token_decl (nterm_sym, token_sym);
1025 break;
1026
1027 case tok_type:
1028 parse_type_decl ();
1029 break;
1030
1031 case tok_start:
1032 parse_start_decl ();
1033 break;
1034
1035 case tok_union:
1036 parse_union_decl ();
1037 break;
1038
1039 case tok_expect:
1040 parse_expect_decl ();
1041 break;
1042
1043 case tok_thong:
1044 parse_thong_decl ();
1045 break;
1046
1047 case tok_left:
1048 parse_assoc_decl (left_assoc);
1049 break;
1050
1051 case tok_right:
1052 parse_assoc_decl (right_assoc);
1053 break;
1054
1055 case tok_nonassoc:
1056 parse_assoc_decl (non_assoc);
1057 break;
1058
1059 case tok_define:
1060 parse_muscle_decl ();
1061 break;
1062
1063 case tok_skel:
1064 parse_skel_decl ();
1065 break;
1066
1067 case tok_noop:
1068 break;
1069
1070 case tok_stropt:
1071 case tok_intopt:
1072 case tok_obsolete:
1073 abort ();
1074 break;
1075
1076 case tok_illegal:
1077 default:
1078 complain (_("unrecognized: %s"), token_buffer);
1079 skip_to_char ('%');
1080 }
1081 }
1082 else if (c == EOF)
1083 fatal (_("no input grammar"));
1084 else
1085 {
1086 char buf[] = "c";
1087 buf[0] = c;
1088 complain (_("unknown character: %s"), quote (buf));
1089 skip_to_char ('%');
1090 }
1091 }
1092 }
1093 \f
1094 /*-------------------------------------------------------------------.
1095 | Assuming that a `{' has just been seen, copy everything up to the |
1096 | matching `}' into the actions file. STACK_OFFSET is the number of |
1097 | values in the current rule so far, which says where to find `$0' |
1098 | with respect to the top of the stack. |
1099 | |
1100 | This routine is used both for actions and guards. Only |
1101 | ACTION_OBSTACK is used, but this is fine, since we use only |
1102 | pointers to relevant portions inside this obstack. |
1103 `-------------------------------------------------------------------*/
1104
1105 static void
1106 parse_braces (symbol_list *rule, int stack_offset)
1107 {
1108 int c;
1109 int count;
1110
1111 count = 1;
1112 while (count > 0)
1113 {
1114 while ((c = getc (finput)) != '}')
1115 switch (c)
1116 {
1117 case '\n':
1118 obstack_1grow (&action_obstack, c);
1119 lineno++;
1120 break;
1121
1122 case '{':
1123 obstack_1grow (&action_obstack, c);
1124 count++;
1125 break;
1126
1127 case '\'':
1128 case '"':
1129 copy_string (finput, &action_obstack, c);
1130 break;
1131
1132 case '/':
1133 copy_comment (finput, &action_obstack);
1134 break;
1135
1136 case '$':
1137 copy_dollar (finput, &action_obstack,
1138 rule, stack_offset);
1139 break;
1140
1141 case '@':
1142 copy_at (finput, &action_obstack,
1143 stack_offset);
1144 break;
1145
1146 case EOF:
1147 fatal (_("unmatched %s"), "`{'");
1148
1149 default:
1150 obstack_1grow (&action_obstack, c);
1151 }
1152
1153 /* Above loop exits when C is '}'. */
1154 if (--count)
1155 {
1156 obstack_1grow (&action_obstack, c);
1157 c = getc (finput);
1158 }
1159 }
1160
1161 obstack_1grow (&action_obstack, '\0');
1162 }
1163
1164
1165 static void
1166 parse_action (symbol_list *rule, int stack_offset)
1167 {
1168 rule->action_line = lineno;
1169 parse_braces (rule, stack_offset);
1170 rule->action = obstack_finish (&action_obstack);
1171 }
1172
1173
1174 static void
1175 parse_guard (symbol_list *rule, int stack_offset)
1176 {
1177 token_t t = lex ();
1178 if (t != tok_left_curly)
1179 complain (_("invalid %s declaration"), "%guard");
1180 rule->guard_line = lineno;
1181 parse_braces (rule, stack_offset);
1182 rule->guard = obstack_finish (&action_obstack);
1183 }
1184
1185 \f
1186
1187 /*-------------------------------------------------------------------.
1188 | Generate a dummy symbol, a nonterminal, whose name cannot conflict |
1189 | with the user's names. |
1190 `-------------------------------------------------------------------*/
1191
1192 static bucket *
1193 gensym (void)
1194 {
1195 /* Incremented for each generated symbol */
1196 static int gensym_count = 0;
1197 static char buf[256];
1198
1199 bucket *sym;
1200
1201 sprintf (buf, "@%d", ++gensym_count);
1202 token_buffer = buf;
1203 sym = getsym (token_buffer);
1204 sym->class = nterm_sym;
1205 sym->value = nvars++;
1206 return sym;
1207 }
1208 \f
1209 /*-------------------------------------------------------------------.
1210 | Parse the input grammar into a one symbol_list structure. Each |
1211 | rule is represented by a sequence of symbols: the left hand side |
1212 | followed by the contents of the right hand side, followed by a |
1213 | null pointer instead of a symbol to terminate the rule. The next |
1214 | symbol is the lhs of the following rule. |
1215 | |
1216 | All guards and actions are copied out to the appropriate files, |
1217 | labelled by the rule number they apply to. |
1218 | |
1219 | Bison used to allow some %directives in the rules sections, but |
1220 | this is no longer consider appropriate: (i) the documented grammar |
1221 | doesn't claim it, (ii), it would promote bad style, (iii), error |
1222 | recovery for %directives consists in skipping the junk until a `%' |
1223 | is seen and helrp synchronizing. This scheme is definitely wrong |
1224 | in the rules section. |
1225 `-------------------------------------------------------------------*/
1226
1227 static void
1228 readgram (void)
1229 {
1230 token_t t;
1231 bucket *lhs = NULL;
1232 symbol_list *p = NULL;
1233 symbol_list *p1 = NULL;
1234 bucket *bp;
1235
1236 /* Points to first symbol_list of current rule. its symbol is the
1237 lhs of the rule. */
1238 symbol_list *crule = NULL;
1239 /* Points to the symbol_list preceding crule. */
1240 symbol_list *crule1 = NULL;
1241
1242 t = lex ();
1243
1244 while (t != tok_two_percents && t != tok_eof)
1245 if (t == tok_identifier || t == tok_bar)
1246 {
1247 int action_flag = 0;
1248 /* Number of symbols in rhs of this rule so far */
1249 int rulelength = 0;
1250 int xactions = 0; /* JF for error checking */
1251 bucket *first_rhs = 0;
1252
1253 if (t == tok_identifier)
1254 {
1255 lhs = symval;
1256
1257 if (!start_flag)
1258 {
1259 startval = lhs;
1260 start_flag = 1;
1261 }
1262
1263 t = lex ();
1264 if (t != tok_colon)
1265 {
1266 complain (_("ill-formed rule: initial symbol not followed by colon"));
1267 unlex (t);
1268 }
1269 }
1270
1271 if (nrules == 0 && t == tok_bar)
1272 {
1273 complain (_("grammar starts with vertical bar"));
1274 lhs = symval; /* BOGUS: use a random symval */
1275 }
1276 /* start a new rule and record its lhs. */
1277
1278 nrules++;
1279 nitems++;
1280
1281 p = symbol_list_new (lhs);
1282
1283 crule1 = p1;
1284 if (p1)
1285 p1->next = p;
1286 else
1287 grammar = p;
1288
1289 p1 = p;
1290 crule = p;
1291
1292 /* mark the rule's lhs as a nonterminal if not already so. */
1293
1294 if (lhs->class == unknown_sym)
1295 {
1296 lhs->class = nterm_sym;
1297 lhs->value = nvars;
1298 nvars++;
1299 }
1300 else if (lhs->class == token_sym)
1301 complain (_("rule given for %s, which is a token"), lhs->tag);
1302
1303 /* read the rhs of the rule. */
1304
1305 for (;;)
1306 {
1307 t = lex ();
1308 if (t == tok_prec)
1309 {
1310 t = lex ();
1311 crule->ruleprec = symval;
1312 t = lex ();
1313 }
1314
1315 if (!(t == tok_identifier || t == tok_left_curly))
1316 break;
1317
1318 /* If next token is an identifier, see if a colon follows it.
1319 If one does, exit this rule now. */
1320 if (t == tok_identifier)
1321 {
1322 bucket *ssave;
1323 token_t t1;
1324
1325 ssave = symval;
1326 t1 = lex ();
1327 unlex (t1);
1328 symval = ssave;
1329 if (t1 == tok_colon)
1330 break;
1331
1332 if (!first_rhs) /* JF */
1333 first_rhs = symval;
1334 /* Not followed by colon =>
1335 process as part of this rule's rhs. */
1336 }
1337
1338 /* If we just passed an action, that action was in the middle
1339 of a rule, so make a dummy rule to reduce it to a
1340 non-terminal. */
1341 if (action_flag)
1342 {
1343 /* Since the action was written out with this rule's
1344 number, we must give the new rule this number by
1345 inserting the new rule before it. */
1346
1347 /* Make a dummy nonterminal, a gensym. */
1348 bucket *sdummy = gensym ();
1349
1350 /* Make a new rule, whose body is empty, before the
1351 current one, so that the action just read can
1352 belong to it. */
1353 nrules++;
1354 nitems++;
1355 p = symbol_list_new (sdummy);
1356 /* Attach its lineno to that of the host rule. */
1357 p->line = crule->line;
1358 if (crule1)
1359 crule1->next = p;
1360 else
1361 grammar = p;
1362 /* End of the rule. */
1363 crule1 = symbol_list_new (NULL);
1364 crule1->next = crule;
1365
1366 p->next = crule1;
1367
1368 /* Insert the dummy generated by that rule into this
1369 rule. */
1370 nitems++;
1371 p = symbol_list_new (sdummy);
1372 p1->next = p;
1373 p1 = p;
1374
1375 action_flag = 0;
1376 }
1377
1378 if (t == tok_identifier)
1379 {
1380 nitems++;
1381 p = symbol_list_new (symval);
1382 p1->next = p;
1383 p1 = p;
1384 }
1385 else /* handle an action. */
1386 {
1387 parse_action (crule, rulelength);
1388 action_flag = 1;
1389 xactions++; /* JF */
1390 }
1391 rulelength++;
1392 } /* end of read rhs of rule */
1393
1394 /* Put an empty link in the list to mark the end of this rule */
1395 p = symbol_list_new (NULL);
1396 p1->next = p;
1397 p1 = p;
1398
1399 if (t == tok_prec)
1400 {
1401 complain (_("two @prec's in a row"));
1402 t = lex ();
1403 crule->ruleprec = symval;
1404 t = lex ();
1405 }
1406
1407 if (t == tok_guard)
1408 {
1409 if (!semantic_parser)
1410 complain (_("%%guard present but %%semantic_parser not specified"));
1411
1412 parse_guard (crule, rulelength);
1413 t = lex ();
1414 }
1415
1416 if (t == tok_left_curly)
1417 {
1418 /* This case never occurs -wjh */
1419 if (action_flag)
1420 complain (_("two actions at end of one rule"));
1421 parse_action (crule, rulelength);
1422 action_flag = 1;
1423 xactions++; /* -wjh */
1424 t = lex ();
1425 }
1426 /* If $$ is being set in default way, report if any type
1427 mismatch. */
1428 else if (!xactions
1429 && first_rhs && lhs->type_name != first_rhs->type_name)
1430 {
1431 if (lhs->type_name == 0
1432 || first_rhs->type_name == 0
1433 || strcmp (lhs->type_name, first_rhs->type_name))
1434 complain (_("type clash (`%s' `%s') on default action"),
1435 lhs->type_name ? lhs->type_name : "",
1436 first_rhs->type_name ? first_rhs->type_name : "");
1437 }
1438 /* Warn if there is no default for $$ but we need one. */
1439 else if (!xactions && !first_rhs && lhs->type_name != 0)
1440 complain (_("empty rule for typed nonterminal, and no action"));
1441 if (t == tok_semicolon)
1442 t = lex ();
1443 }
1444 else
1445 {
1446 complain (_("invalid input: %s"), quote (token_buffer));
1447 t = lex ();
1448 }
1449
1450
1451 /* grammar has been read. Do some checking */
1452
1453 if (nsyms > MAXSHORT)
1454 fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
1455 MAXSHORT);
1456 if (nrules == 0)
1457 fatal (_("no rules in the input grammar"));
1458
1459 /* Report any undefined symbols and consider them nonterminals. */
1460
1461 for (bp = firstsymbol; bp; bp = bp->next)
1462 if (bp->class == unknown_sym)
1463 {
1464 complain (_
1465 ("symbol %s is used, but is not defined as a token and has no rules"),
1466 bp->tag);
1467 bp->class = nterm_sym;
1468 bp->value = nvars++;
1469 }
1470
1471 ntokens = nsyms - nvars;
1472 }
1473
1474 /* At the end of the grammar file, some C source code must
1475 be stored. It is going to be associated to the epilogue
1476 directive. */
1477 static void
1478 read_additionnal_code (void)
1479 {
1480 char c;
1481 struct obstack el_obstack;
1482
1483 obstack_init (&el_obstack);
1484
1485 if (!no_lines_flag)
1486 {
1487 obstack_fgrow2 (&el_obstack, muscle_find ("linef"),
1488 lineno, quotearg_style (c_quoting_style,
1489 muscle_find("filename")));
1490 }
1491
1492 while ((c = getc (finput)) != EOF)
1493 obstack_1grow (&el_obstack, c);
1494
1495 obstack_1grow (&el_obstack, 0);
1496 muscle_insert ("epilogue", obstack_finish (&el_obstack));
1497 }
1498
1499 \f
1500 /*------------------------------------------------------------------.
1501 | Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
1502 | number. |
1503 `------------------------------------------------------------------*/
1504
1505 static void
1506 token_translations_init (void)
1507 {
1508 bucket *bp = NULL;
1509 int i;
1510
1511 token_translations = XCALLOC (short, max_user_token_number + 1);
1512
1513 /* Initialize all entries for literal tokens to 2, the internal
1514 token number for $undefined., which represents all invalid
1515 inputs. */
1516 for (i = 0; i <= max_user_token_number; i++)
1517 token_translations[i] = 2;
1518
1519 for (bp = firstsymbol; bp; bp = bp->next)
1520 {
1521 /* Non-terminal? */
1522 if (bp->value >= ntokens)
1523 continue;
1524 /* A token string alias? */
1525 if (bp->user_token_number == SALIAS)
1526 continue;
1527
1528 assert (bp->user_token_number != SUNDEF);
1529
1530 /* A token which translation has already been set? */
1531 if (token_translations[bp->user_token_number] != 2)
1532 complain (_("tokens %s and %s both assigned number %d"),
1533 tags[token_translations[bp->user_token_number]],
1534 bp->tag, bp->user_token_number);
1535 token_translations[bp->user_token_number] = bp->value;
1536 }
1537 }
1538
1539
1540 /*------------------------------------------------------------------.
1541 | Assign symbol numbers, and write definition of token names into |
1542 | FDEFINES. Set up vectors TAGS and SPREC of names and precedences |
1543 | of symbols. |
1544 `------------------------------------------------------------------*/
1545
1546 static void
1547 packsymbols (void)
1548 {
1549 bucket *bp = NULL;
1550 int tokno = 1;
1551 int last_user_token_number;
1552 static char DOLLAR[] = "$";
1553
1554 tags = XCALLOC (char *, nsyms + 1);
1555 user_toknums = XCALLOC (short, nsyms + 1);
1556
1557 sprec = XCALLOC (short, nsyms);
1558 sassoc = XCALLOC (short, nsyms);
1559
1560 /* The EOF token. */
1561 tags[0] = DOLLAR;
1562 user_toknums[0] = 0;
1563
1564 max_user_token_number = 256;
1565 last_user_token_number = 256;
1566
1567 for (bp = firstsymbol; bp; bp = bp->next)
1568 {
1569 if (bp->class == nterm_sym)
1570 {
1571 bp->value += ntokens;
1572 }
1573 else if (bp->alias)
1574 {
1575 /* this symbol and its alias are a single token defn.
1576 allocate a tokno, and assign to both check agreement of
1577 ->prec and ->assoc fields and make both the same */
1578 if (bp->value == 0)
1579 bp->value = bp->alias->value = tokno++;
1580
1581 if (bp->prec != bp->alias->prec)
1582 {
1583 if (bp->prec != 0 && bp->alias->prec != 0
1584 && bp->user_token_number == SALIAS)
1585 complain (_("conflicting precedences for %s and %s"),
1586 bp->tag, bp->alias->tag);
1587 if (bp->prec != 0)
1588 bp->alias->prec = bp->prec;
1589 else
1590 bp->prec = bp->alias->prec;
1591 }
1592
1593 if (bp->assoc != bp->alias->assoc)
1594 {
1595 if (bp->assoc != 0 && bp->alias->assoc != 0
1596 && bp->user_token_number == SALIAS)
1597 complain (_("conflicting assoc values for %s and %s"),
1598 bp->tag, bp->alias->tag);
1599 if (bp->assoc != 0)
1600 bp->alias->assoc = bp->assoc;
1601 else
1602 bp->assoc = bp->alias->assoc;
1603 }
1604
1605 if (bp->user_token_number == SALIAS)
1606 continue; /* do not do processing below for SALIASs */
1607
1608 }
1609 else /* bp->class == token_sym */
1610 {
1611 bp->value = tokno++;
1612 }
1613
1614 if (bp->class == token_sym)
1615 {
1616 if (bp->user_token_number == SUNDEF)
1617 bp->user_token_number = ++last_user_token_number;
1618 if (bp->user_token_number > max_user_token_number)
1619 max_user_token_number = bp->user_token_number;
1620 }
1621
1622 tags[bp->value] = bp->tag;
1623 user_toknums[bp->value] = bp->user_token_number;
1624 sprec[bp->value] = bp->prec;
1625 sassoc[bp->value] = bp->assoc;
1626 }
1627
1628 token_translations_init ();
1629
1630 error_token_number = errtoken->value;
1631
1632 if (startval->class == unknown_sym)
1633 fatal (_("the start symbol %s is undefined"), startval->tag);
1634 else if (startval->class == token_sym)
1635 fatal (_("the start symbol %s is a token"), startval->tag);
1636
1637 start_symbol = startval->value;
1638 }
1639
1640
1641 /*---------------------------------------------------------------.
1642 | Save the definition of token names in the `TOKENDEFS' muscle. |
1643 `---------------------------------------------------------------*/
1644
1645 static void
1646 symbols_save (void)
1647 {
1648 struct obstack tokendefs;
1649 bucket *bp;
1650 obstack_init (&tokendefs);
1651
1652 for (bp = firstsymbol; bp; bp = bp->next)
1653 {
1654 char *symbol = bp->tag; /* get symbol */
1655
1656 if (bp->value >= ntokens)
1657 continue;
1658 if (bp->user_token_number == SALIAS)
1659 continue;
1660 if ('\'' == *symbol)
1661 continue; /* skip literal character */
1662 if (bp == errtoken)
1663 continue; /* skip error token */
1664 if ('\"' == *symbol)
1665 {
1666 /* use literal string only if given a symbol with an alias */
1667 if (bp->alias)
1668 symbol = bp->alias->tag;
1669 else
1670 continue;
1671 }
1672
1673 /* Don't #define nonliteral tokens whose names contain periods. */
1674 if (strchr (symbol, '.'))
1675 continue;
1676
1677 obstack_fgrow2 (&tokendefs, "# define %s\t%d\n",
1678 symbol, bp->user_token_number);
1679 if (semantic_parser)
1680 /* FIXME: This is probably wrong, and should be just as
1681 above. --akim. */
1682 obstack_fgrow2 (&tokendefs, "# define T%s\t%d\n", symbol, bp->value);
1683 }
1684
1685 obstack_1grow (&tokendefs, 0);
1686 muscle_insert ("tokendef", xstrdup (obstack_finish (&tokendefs)));
1687 obstack_free (&tokendefs, NULL);
1688 }
1689
1690
1691 /*---------------------------------------------------------------.
1692 | Convert the rules into the representation using RRHS, RLHS and |
1693 | RITEMS. |
1694 `---------------------------------------------------------------*/
1695
1696 static void
1697 packgram (void)
1698 {
1699 int itemno;
1700 int ruleno;
1701 symbol_list *p;
1702
1703 /* We use short to index items. */
1704 if (nitems >= MAXSHORT)
1705 fatal (_("too many items (max %d)"), MAXSHORT);
1706
1707 ritem = XCALLOC (short, nitems + 1);
1708 rule_table = XCALLOC (rule_t, nrules) - 1;
1709
1710 itemno = 0;
1711 ruleno = 1;
1712
1713 p = grammar;
1714 while (p)
1715 {
1716 bucket *ruleprec = p->ruleprec;
1717 rule_table[ruleno].lhs = p->sym->value;
1718 rule_table[ruleno].rhs = itemno;
1719 rule_table[ruleno].line = p->line;
1720 rule_table[ruleno].useful = TRUE;
1721 rule_table[ruleno].action = p->action;
1722 rule_table[ruleno].action_line = p->action_line;
1723 rule_table[ruleno].guard = p->guard;
1724 rule_table[ruleno].guard_line = p->guard_line;
1725
1726 p = p->next;
1727 while (p && p->sym)
1728 {
1729 ritem[itemno++] = p->sym->value;
1730 /* A rule gets by default the precedence and associativity
1731 of the last token in it. */
1732 if (p->sym->class == token_sym)
1733 {
1734 rule_table[ruleno].prec = p->sym->prec;
1735 rule_table[ruleno].assoc = p->sym->assoc;
1736 }
1737 if (p)
1738 p = p->next;
1739 }
1740
1741 /* If this rule has a %prec,
1742 the specified symbol's precedence replaces the default. */
1743 if (ruleprec)
1744 {
1745 rule_table[ruleno].prec = ruleprec->prec;
1746 rule_table[ruleno].assoc = ruleprec->assoc;
1747 rule_table[ruleno].precsym = ruleprec->value;
1748 }
1749
1750 ritem[itemno++] = -ruleno;
1751 ruleno++;
1752
1753 if (p)
1754 p = p->next;
1755 }
1756
1757 ritem[itemno] = 0;
1758
1759 if (trace_flag)
1760 ritem_print (stderr);
1761 }
1762 \f
1763 /*-------------------------------------------------------------------.
1764 | Read in the grammar specification and record it in the format |
1765 | described in gram.h. All guards are copied into the GUARD_OBSTACK |
1766 | and all actions into ACTION_OBSTACK, in each case forming the body |
1767 | of a C function (YYGUARD or YYACTION) which contains a switch |
1768 | statement to decide which guard or action to execute. |
1769 `-------------------------------------------------------------------*/
1770
1771 void
1772 reader (void)
1773 {
1774 start_flag = 0;
1775 startval = NULL; /* start symbol not specified yet. */
1776
1777 nsyms = 1;
1778 nvars = 0;
1779 nrules = 0;
1780 nitems = 0;
1781
1782 typed = 0;
1783 lastprec = 0;
1784
1785 semantic_parser = 0;
1786 pure_parser = 0;
1787
1788 grammar = NULL;
1789
1790 lex_init ();
1791 lineno = 1;
1792
1793 /* Initialize the muscle obstack. */
1794 obstack_init (&muscle_obstack);
1795
1796 /* Initialize the symbol table. */
1797 tabinit ();
1798
1799 /* Construct the error token */
1800 errtoken = getsym ("error");
1801 errtoken->class = token_sym;
1802 errtoken->user_token_number = 256; /* Value specified by POSIX. */
1803
1804 /* Construct a token that represents all undefined literal tokens.
1805 It is always token number 2. */
1806 undeftoken = getsym ("$undefined.");
1807 undeftoken->class = token_sym;
1808 undeftoken->user_token_number = 2;
1809
1810 /* Initialize the obstacks. */
1811 obstack_init (&action_obstack);
1812 obstack_init (&attrs_obstack);
1813 obstack_init (&output_obstack);
1814
1815 finput = xfopen (infile, "r");
1816
1817 /* Read the declaration section. Copy %{ ... %} groups to
1818 TABLE_OBSTACK and FDEFINES file. Also notice any %token, %left,
1819 etc. found there. */
1820 read_declarations ();
1821 /* Read in the grammar, build grammar in list form. Write out
1822 guards and actions. */
1823 readgram ();
1824 /* Some C code is given at the end of the grammar file. */
1825 read_additionnal_code ();
1826
1827 lex_free ();
1828 xfclose (finput);
1829
1830 /* Assign the symbols their symbol numbers. Write #defines for the
1831 token symbols into FDEFINES if requested. */
1832 packsymbols ();
1833 /* Save them. */
1834 symbols_save ();
1835
1836 /* Convert the grammar into the format described in gram.h. */
1837 packgram ();
1838 }