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