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