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