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