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