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