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