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