1 /**************************************************************************/
2 /* */
3 /* OCaml */
4 /* */
5 /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
6 /* */
7 /* Copyright 1996 Institut National de Recherche en Informatique et */
8 /* en Automatique. */
9 /* */
10 /* All rights reserved. This file is distributed under the terms of */
11 /* the GNU Lesser General Public License version 2.1, with the */
12 /* special exception on linking described in the file LICENSE. */
13 /* */
14 /**************************************************************************/
15
16 /* Based on public-domain code from Berkeley Yacc */
17
18 #include <string.h>
19 #include "defs.h"
20
21 /* The line size must be a positive integer. One hundred was chosen */
22 /* because few lines in Yacc input grammars exceed 100 characters. */
23 /* Note that if a line exceeds LINESIZE characters, the line buffer */
24 /* will be expanded to accommodate it. */
25
26 #define LINESIZE 100
27
28 char *cache;
29 int cinc, cache_size;
30
31 int ntags, tagmax;
32 char **tag_table;
33
34 char saw_eof;
35 char *cptr, *line;
36 int linesize;
37
38 bucket *goal;
39 int prec;
40 int gensym;
41 char last_was_action;
42
43 int maxitems;
44 bucket **pitem;
45
46 int maxrules;
47 bucket **plhs;
48
49 int name_pool_size;
50 char *name_pool;
51
52 static unsigned char caml_ident_start[32] =
53 "\000\000\000\000\000\000\000\000\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\377\377\177\377\377\377\177\377";
54 static unsigned char caml_ident_body[32] =
55 "\000\000\000\000\200\000\377\003\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\377\377\177\377\377\377\177\377";
56
57 #define In_bitmap(bm,c) (bm[(unsigned char)(c) >> 3] & (1 << ((c) & 7)))
58
59 void start_rule (register bucket *bp, int s_lineno);
60
61 static char *buffer;
62 static size_t length;
63 static size_t capacity;
64 static void push_stack(char x) {
65 if (length - 1 >= capacity) {
66 buffer = realloc(buffer, capacity = 3*length/2 + 100);
67 if (!buffer) no_space();
68 }
69 buffer[++length] = x;
70 buffer[0] = '\1';
71 }
72
73 static void pop_stack(char x) {
74 if (!buffer || buffer[length--] != x) {
75 switch (x) {
76 case '{': x = '}'; break;
77 case '(': x = ')'; break;
78 default: break;
79 }
80 fprintf(stderr, "Mismatched parentheses or braces: '%c'\n", x);
81 syntax_error(lineno, line, cptr - 1);
82 }
83 }
84
85 void cachec(int c)
86 {
87 assert(cinc >= 0);
88 if (cinc >= cache_size)
89 {
90 cache_size += 256;
91 cache = REALLOC(cache, cache_size);
92 if (cache == 0) no_space();
93 }
94 cache[cinc] = c;
95 ++cinc;
96 }
97
98
99 void get_line(void)
100 {
101 register FILE *f = input_file;
102 register int c;
103 register int i;
104
105 if (saw_eof || (c = getc(f)) == EOF)
106 {
107 if (line) { FREE(line); line = 0; }
108 cptr = 0;
109 saw_eof = 1;
110 return;
111 }
112
113 if (line == 0 || linesize != (LINESIZE + 1))
114 {
115 if (line) FREE(line);
116 linesize = LINESIZE + 1;
117 line = MALLOC(linesize);
118 if (line == 0) no_space();
119 }
120
121 i = 0;
122 ++lineno;
123 for (;;)
124 {
125 line[i] = c;
126 if (++i >= linesize)
127 {
128 linesize += LINESIZE;
129 line = REALLOC(line, linesize);
130 if (line == 0) no_space();
131 }
132 if (c == '\n') {
133 if (i >= 2 && line[i-2] == '\r') {
134 line[i-2] = '\n'; i--;
135 }
136 line[i] = '\0'; cptr = line; return;
137 }
138 c = getc(f);
139 if (c == EOF) { saw_eof = 1; c = '\n'; }
140 }
141 }
142
143
144 char *
145 dup_line(void)
146 {
147 register char *p, *s, *t;
148
149 if (line == 0) return (0);
150 s = line;
151 while (*s != '\n') ++s;
152 p = MALLOC(s - line + 1);
153 if (p == 0) no_space();
154
155 s = line;
156 t = p;
157 while ((*t++ = *s++) != '\n') continue;
158 return (p);
159 }
160
161
162 void skip_comment(void)
163 {
164 register char *s;
165
166 int st_lineno = lineno;
167 char *st_line = dup_line();
168 char *st_cptr = st_line + (cptr - line);
169
170 s = cptr + 2;
171 for (;;)
172 {
173 if (*s == '*' && s[1] == '/')
174 {
175 cptr = s + 2;
176 FREE(st_line);
177 return;
178 }
179 if (*s == '\n')
180 {
181 get_line();
182 if (line == 0)
183 unterminated_comment(st_lineno, st_line, st_cptr);
184 s = cptr;
185 }
186 else
187 ++s;
188 }
189 }
190
191 static void process_quoted_string(char c, FILE *const f)
192 {
193 int s_lineno = lineno;
194 char *s_line = dup_line();
195 char *s_cptr = s_line + (cptr - line - 1);
196
197 char quote = c;
198 for (;;)
199 {
200 c = *cptr++;
201 putc(c, f);
202 if (c == quote)
203 {
204 FREE(s_line);
205 return;
206 }
207 if (c == '\n')
208 unterminated_string(s_lineno, s_line, s_cptr);
209 if (c == '\\')
210 {
211 c = *cptr++;
212 putc(c, f);
213 if (c == '\n')
214 {
215 get_line();
216 if (line == 0)
217 unterminated_string(s_lineno, s_line, s_cptr);
218 }
219 }
220 }
221 }
222
223 int process_apostrophe(FILE *const f)
224 {
225 if (cptr[0] != 0 && cptr[0] != '\\' && cptr[1] == '\'') {
226 fwrite(cptr, 1, 2, f);
227 cptr += 2;
228 } else if (cptr[0] == '\\'
229 && (isdigit((unsigned char) cptr[1]) || cptr[1] == 'x')
230 && isdigit((unsigned char) cptr[2])
231 && isdigit((unsigned char) cptr[3])
232 && cptr[4] == '\'') {
233 fwrite(cptr, 1, 5, f);
234 cptr += 5;
235 } else if (cptr[0] == '\\'
236 && cptr[1] == 'o'
237 && cptr[2] >= '0' && cptr[2] <= '3'
238 && cptr[3] >= '0' && cptr[3] <= '7'
239 && cptr[4] >= '0' && cptr[4] <= '7'
240 && cptr[5] == '\'') {
241 fwrite(cptr, 1, 6, f);
242 cptr += 6;
243 } else if (cptr[0] == '\\' && cptr[2] == '\'') {
244 fwrite(cptr, 1, 3, f);
245 cptr += 3;
246 } else {
247 return 0;
248 }
249 return 1;
250 }
251
252 void process_apostrophe_body(FILE *f)
253 {
254 if (!process_apostrophe(f)) {
255 while (In_bitmap(caml_ident_body, *cptr)) {
256 putc(*cptr, f);
257 cptr++;
258 }
259 }
260 }
261
262
263 static void process_open_curly_bracket(FILE *f) {
264 if (In_bitmap(caml_ident_start, *cptr) || *cptr == '|')
265 {
266 char *newcptr = cptr;
267 size_t size = 0;
268 char *buf;
269 while(In_bitmap(caml_ident_body, *newcptr)) { newcptr++; }
270 if (*newcptr == '|')
271 { /* Raw string */
272 int s_lineno;
273 char *s_line;
274 char *s_cptr;
275
276 size = newcptr - cptr;
277 buf = MALLOC(size + 2);
278 if (!buf) no_space();
279 memcpy(buf, cptr, size);
280 buf[size] = '}';
281 buf[size + 1] = '\0';
282 fwrite(cptr, 1, size + 1, f);
283 cptr = newcptr + 1;
284 s_lineno = lineno;
285 s_line = dup_line();
286 s_cptr = s_line + (cptr - line - 1);
287
288 for (;;)
289 {
290 char c = *cptr++;
291 putc(c, f);
292 if (c == '|')
293 {
294 int match = 1;
295 size_t i;
296 for (i = 0; i <= size; ++i) {
297 if (cptr[i] != buf[i]) {
298 newcptr--;
299 match = 0;
300 break;
301 }
302 }
303 if (match) {
304 FREE(s_line);
305 FREE(buf);
306 fwrite(cptr, 1, size, f);
307 cptr += size;
308 return;
309 }
310 }
311 if (c == '\n')
312 {
313 get_line();
314 if (line == 0)
315 unterminated_string(s_lineno, s_line, s_cptr);
316 }
317 }
318 FREE(buf);
319 return;
320 }
321 }
322 return;
323 }
324
325 static void process_comment(FILE *const f) {
326 char c = *cptr;
327 unsigned depth = 1;
328 if (c == '*')
329 {
330 int c_lineno = lineno;
331 char *c_line = dup_line();
332 char *c_cptr = c_line + (cptr - line - 1);
333
334 putc('*', f);
335 ++cptr;
336 for (;;)
337 {
338 c = *cptr++;
339 putc(c, f);
340
341 switch (c)
342 {
343 case '*':
344 if (*cptr == ')')
345 {
346 depth--;
347 if (depth == 0) {
348 FREE(c_line);
349 return;
350 }
351 }
352 continue;
353 case '\n':
354 get_line();
355 if (line == 0)
356 unterminated_comment(c_lineno, c_line, c_cptr);
357 continue;
358 case '(':
359 if (*cptr == '*') ++depth;
360 continue;
361 case '\'':
362 process_apostrophe(f);
363 continue;
364 case '"':
365 process_quoted_string(c, f);
366 continue;
367 case '{':
368 process_open_curly_bracket(f);
369 continue;
370 default:
371 if (In_bitmap(caml_ident_start, c)) {
372 while (In_bitmap(caml_ident_body, *cptr)) cptr++;
373 }
374 continue;
375 }
376 }
377 }
378 }
379
380 char *substring (char *str, int start, int len)
381 {
382 int i;
383 char *buf = MALLOC (len+1);
384 if (buf == NULL) return NULL;
385 for (i = 0; i < len; i++){
386 buf[i] = str[start+i];
387 }
388 buf[i] = '\0'; /* PR#4796 */
389 return buf;
390 }
391
392 void parse_line_directive (void)
393 {
394 int i = 0, j = 0;
395 int line_number = 0;
396 char *file_name = NULL;
397
398 again:
399 if (line == 0) return;
400 if (line[i] != '#') return;
401 ++ i;
402 while (line[i] == ' ' || line[i] == '\t') ++ i;
403 if (line[i] < '0' || line[i] > '9') return;
404 while (line[i] >= '0' && line[i] <= '9'){
405 line_number = line_number * 10 + line[i] - '0';
406 ++ i;
407 }
408 while (line[i] == ' ' || line[i] == '\t') ++ i;
409 if (line[i] == '"'){
410 ++ i;
411 j = i;
412 while (line[j] != '"' && line[j] != '\0') ++j;
413 if (line[j] == '"'){
414 file_name = substring (line, i, j - i);
415 if (file_name == NULL) no_space ();
416 }
417 }
418 lineno = line_number - 1;
419 if (file_name != NULL){
420 if (virtual_input_file_name != NULL) FREE (virtual_input_file_name);
421 virtual_input_file_name = file_name;
422 }
423 get_line ();
424 goto again;
425 }
426
427 int
428 nextc(void)
429 {
430 register char *s;
431
432 if (line == 0)
433 {
434 get_line();
435 parse_line_directive ();
436 if (line == 0)
437 return (EOF);
438 }
439
440 s = cptr;
441 for (;;)
442 {
443 switch (*s)
444 {
445 case '\n':
446 get_line();
447 parse_line_directive ();
448 if (line == 0) return (EOF);
449 s = cptr;
450 break;
451
452 case ' ':
453 case '\t':
454 case '\f':
455 case '\r':
456 case '\v':
457 case ',':
458 case ';':
459 ++s;
460 break;
461
462 case '\\':
463 cptr = s;
464 return ('%');
465
466 case '/':
467 if (s[1] == '*')
468 {
469 cptr = s;
470 skip_comment();
471 s = cptr;
472 break;
473 }
474 else if (s[1] == '/')
475 {
476 get_line();
477 parse_line_directive ();
478 if (line == 0) return (EOF);
479 s = cptr;
480 break;
481 }
482 /* fall through */
483
484 default:
485 cptr = s;
486 return (*s);
487 }
488 }
489 }
490
491
492 int
493 keyword(void)
494 {
495 register int c;
496 char *t_cptr = cptr;
497
498 c = *++cptr;
499 if (isalpha(c))
500 {
501 cinc = 0;
502 for (;;)
503 {
504 if (isalpha(c))
505 {
506 if (isupper(c)) c = tolower(c);
507 cachec(c);
508 }
509 else if (isdigit(c) || c == '_' || c == '.' || c == '$')
510 cachec(c);
511 else
512 break;
513 c = *++cptr;
514 }
515 cachec(NUL);
516
517 if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
518 return (TOKEN);
519 if (strcmp(cache, "type") == 0)
520 return (TYPE);
521 if (strcmp(cache, "left") == 0)
522 return (LEFT);
523 if (strcmp(cache, "right") == 0)
524 return (RIGHT);
525 if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
526 return (NONASSOC);
527 if (strcmp(cache, "start") == 0)
528 return (START);
529 }
530 else
531 {
532 ++cptr;
533 if (c == '{')
534 return (TEXT);
535 if (c == '%' || c == '\\')
536 return (MARK);
537 if (c == '<')
538 return (LEFT);
539 if (c == '>')
540 return (RIGHT);
541 if (c == '0')
542 return (TOKEN);
543 if (c == '2')
544 return (NONASSOC);
545 }
546 syntax_error(lineno, line, t_cptr);
547 /*NOTREACHED*/
548 return 0;
549 }
550
551 void copy_text(void)
552 {
553 register int c;
554 register FILE *f = text_file;
555 int need_newline = 0;
556 int t_lineno = lineno;
557 char *t_line = dup_line();
558 char *t_cptr = t_line + (cptr - line - 2);
559
560 if (*cptr == '\n')
561 {
562 get_line();
563 if (line == 0)
564 unterminated_text(t_lineno, t_line, t_cptr);
565 }
566 fprintf(f, line_format, lineno, input_file_name_disp);
567
568 loop:
569 c = *cptr++;
570 switch (c)
571 {
572 case '\n':
573 putc('\n', f);
574 need_newline = 0;
575 get_line();
576 if (line) goto loop;
577 unterminated_text(t_lineno, t_line, t_cptr);
578
579 case '"':
580 putc(c, f);
581 process_quoted_string(c, f);
582 goto loop;
583
584 case '\'':
585 putc(c, f);
586 process_apostrophe_body(f);
587 goto loop;
588
589 case '(':
590 putc(c, f);
591 need_newline = 1;
592 process_comment(f);
593 goto loop;
594
595 case '%':
596 case '\\':
597 if (*cptr == '}')
598 {
599 if (need_newline) putc('\n', f);
600 ++cptr;
601 FREE(t_line);
602 return;
603 }
604 /* fall through */
605
606 case '{':
607 putc(c, f);
608 process_open_curly_bracket(f);
609 goto loop;
610 default:
611 putc(c, f);
612 if (In_bitmap(caml_ident_start, c)) {
613 while (In_bitmap(caml_ident_body, *cptr)) {
614 putc(*cptr, f);
615 cptr++;
616 }
617 }
618 need_newline = 1;
619 goto loop;
620 }
621 }
622
623 int
624 hexval(int c)
625 {
626 if (c >= '0' && c <= '9')
627 return (c - '0');
628 if (c >= 'A' && c <= 'F')
629 return (c - 'A' + 10);
630 if (c >= 'a' && c <= 'f')
631 return (c - 'a' + 10);
632 return (-1);
633 }
634
635
636 bucket *
637 get_literal(void)
638 {
639 register int c, quote;
640 register int i;
641 register int n;
642 register char *s;
643 register bucket *bp;
644 int s_lineno = lineno;
645 char *s_line = dup_line();
646 char *s_cptr = s_line + (cptr - line);
647
648 quote = *cptr++;
649 cinc = 0;
650 for (;;)
651 {
652 c = *cptr++;
653 if (c == quote) break;
654 if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
655 if (c == '\\')
656 {
657 char *c_cptr = cptr - 1;
658
659 c = *cptr++;
660 switch (c)
661 {
662 case '\n':
663 get_line();
664 if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
665 continue;
666
667 case '0': case '1': case '2': case '3':
668 case '4': case '5': case '6': case '7':
669 n = c - '0';
670 c = *cptr;
671 if (IS_OCTAL(c))
672 {
673 n = (n << 3) + (c - '0');
674 c = *++cptr;
675 if (IS_OCTAL(c))
676 {
677 n = (n << 3) + (c - '0');
678 ++cptr;
679 }
680 }
681 if (n > MAXCHAR) illegal_character(c_cptr);
682 c = n;
683 break;
684
685 case 'x':
686 c = *cptr++;
687 n = hexval(c);
688 if (n < 0 || n >= 16)
689 illegal_character(c_cptr);
690 for (;;)
691 {
692 c = *cptr;
693 i = hexval(c);
694 if (i < 0 || i >= 16) break;
695 ++cptr;
696 n = (n << 4) + i;
697 if (n > MAXCHAR) illegal_character(c_cptr);
698 }
699 c = n;
700 break;
701
702 case 'a': c = 7; break;
703 case 'b': c = '\b'; break;
704 case 'f': c = '\f'; break;
705 case 'n': c = '\n'; break;
706 case 'r': c = '\r'; break;
707 case 't': c = '\t'; break;
708 case 'v': c = '\v'; break;
709 }
710 }
711 cachec(c);
712 }
713 FREE(s_line);
714
715 n = cinc;
716 s = MALLOC(n);
717 if (s == 0) no_space();
718
719 for (i = 0; i < n; ++i)
720 s[i] = cache[i];
721
722 cinc = 0;
723 if (n == 1)
724 cachec('\'');
725 else
726 cachec('"');
727
728 for (i = 0; i < n; ++i)
729 {
730 c = ((unsigned char *)s)[i];
731 if (c == '\\' || c == cache[0])
732 {
733 cachec('\\');
734 cachec(c);
735 }
736 else if (isprint(c))
737 cachec(c);
738 else
739 {
740 cachec('\\');
741 switch (c)
742 {
743 case 7: cachec('a'); break;
744 case '\b': cachec('b'); break;
745 case '\f': cachec('f'); break;
746 case '\n': cachec('n'); break;
747 case '\r': cachec('r'); break;
748 case '\t': cachec('t'); break;
749 case '\v': cachec('v'); break;
750 default:
751 cachec(((c >> 6) & 7) + '0');
752 cachec(((c >> 3) & 7) + '0');
753 cachec((c & 7) + '0');
754 break;
755 }
756 }
757 }
758
759 if (n == 1)
760 cachec('\'');
761 else
762 cachec('"');
763
764 cachec(NUL);
765 bp = lookup(cache);
766 bp->class = TERM;
767 if (n == 1 && bp->value == UNDEFINED)
768 bp->value = *(unsigned char *)s;
769 FREE(s);
770
771 return (bp);
772 }
773
774
775 int
776 is_reserved(char *name)
777 {
778 char *s;
779
780 if (strcmp(name, ".") == 0 ||
781 strcmp(name, "$accept") == 0 ||
782 strcmp(name, "$end") == 0)
783 return (1);
784
785 if (name[0] == '$' && name[1] == '$' && isdigit((unsigned char) name[2]))
786 {
787 s = name + 3;
788 while (isdigit((unsigned char) *s)) ++s;
789 if (*s == NUL) return (1);
790 }
791
792 return (0);
793 }
794
795
796 bucket *
797 get_name(void)
798 {
799 register int c;
800
801 cinc = 0;
802 for (c = *cptr; IS_IDENT(c); c = *++cptr)
803 cachec(c);
804 cachec(NUL);
805
806 if (is_reserved(cache)) used_reserved(cache);
807
808 return (lookup(cache));
809 }
810
811
812 int
813 get_number(void)
814 {
815 register int c;
816 register int n;
817
818 n = 0;
819 for (c = *cptr; isdigit(c); c = *++cptr)
820 n = 10*n + (c - '0');
821
822 return (n);
823 }
824
825
826 char *
827 get_tag(void)
828 {
829 register int c;
830 register int i;
831 register char *s;
832 char *t_line = dup_line();
833 long bracket_depth;
834
835 cinc = 0;
836 bracket_depth = 0;
837 while (1) {
838 c = *++cptr;
839 if (c == EOF) unexpected_EOF();
840 if (c == '\n') syntax_error(lineno, line, cptr);
841 if (c == '>' && 0 == bracket_depth && cptr[-1] != '-') break;
842 if (c == '[') ++ bracket_depth;
843 if (c == ']') -- bracket_depth;
844 cachec(c);
845 }
846 ++cptr;
847 cachec(NUL);
848
849 for (i = 0; i < ntags; ++i)
850 {
851 if (strcmp(cache, tag_table[i]) == 0)
852 return (tag_table[i]);
853 }
854
855 if (ntags >= tagmax)
856 {
857 tagmax += 16;
858 tag_table = (char **)
859 (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
860 : MALLOC(tagmax*sizeof(char *)));
861 if (tag_table == 0) no_space();
862 }
863
864 s = MALLOC(cinc);
865 if (s == 0) no_space();
866 strcpy(s, cache);
867 tag_table[ntags] = s;
868 ++ntags;
869 FREE(t_line);
870 return (s);
871 }
872
873
874 void declare_tokens(int assoc)
875 {
876 register int c;
877 register bucket *bp;
878 char *tag = 0;
879
880 if (assoc != TOKEN) ++prec;
881
882 c = nextc();
883 if (c == EOF) unexpected_EOF();
884 if (c == '<')
885 {
886 tag = get_tag();
887 c = nextc();
888 if (c == EOF) unexpected_EOF();
889 }
890
891 for (;;)
892 {
893 if (isalpha(c) || c == '_' || c == '.' || c == '$')
894 bp = get_name();
895 else if (c == '\'' || c == '"')
896 bp = get_literal();
897 else
898 return;
899
900 if (bp == goal) tokenized_start(bp->name);
901 bp->class = TERM;
902
903 if (tag)
904 {
905 if (bp->tag && tag != bp->tag)
906 retyped_warning(bp->name);
907 bp->tag = tag;
908 }
909
910 if (assoc == TOKEN)
911 {
912 bp->true_token = 1;
913 }
914 else
915 {
916 if (bp->prec && prec != bp->prec)
917 reprec_warning(bp->name);
918 bp->assoc = assoc;
919 bp->prec = prec;
920 }
921
922 if (strcmp(bp->name, "EOF") == 0)
923 bp->value = 0;
924
925 c = nextc();
926 if (c == EOF) unexpected_EOF();
927 if (isdigit(c))
928 {
929 int value = get_number();
930 if (bp->value != UNDEFINED && value != bp->value)
931 revalued_warning(bp->name);
932 bp->value = value;
933 c = nextc();
934 if (c == EOF) unexpected_EOF();
935 }
936 }
937 }
938
939
940 void declare_types(void)
941 {
942 register int c;
943 register bucket *bp;
944 char *tag;
945
946 c = nextc();
947 if (c == EOF) unexpected_EOF();
948 if (c != '<') syntax_error(lineno, line, cptr);
949 tag = get_tag();
950
951 for (;;)
952 {
953 c = nextc();
954 if (isalpha(c) || c == '_' || c == '.' || c == '$')
955 bp = get_name();
956 else if (c == '\'' || c == '"')
957 bp = get_literal();
958 else
959 return;
960
961 if (bp->tag && tag != bp->tag)
962 retyped_warning(bp->name);
963 bp->tag = tag;
964 }
965 }
966
967
968 void declare_start(void)
969 {
970 register int c;
971 register bucket *bp;
972 static int entry_counter = 0;
973
974 for (;;) {
975 c = nextc();
976 if (!isalpha(c) && c != '_' && c != '.' && c != '$') return;
977 bp = get_name();
978
979 if (bp->class == TERM)
980 terminal_start(bp->name);
981 bp->entry = ++entry_counter;
982 if (entry_counter == 256)
983 too_many_entries();
984 }
985 }
986
987
988 void read_declarations(void)
989 {
990 register int c, k;
991
992 cache_size = 256;
993 cache = MALLOC(cache_size);
994 if (cache == 0) no_space();
995
996 for (;;)
997 {
998 c = nextc();
999 if (c == EOF) unexpected_EOF();
1000 if (c != '%') syntax_error(lineno, line, cptr);
1001 switch (k = keyword())
1002 {
1003 case MARK:
1004 return;
1005
1006 case TEXT:
1007 copy_text();
1008 break;
1009
1010 case TOKEN:
1011 case LEFT:
1012 case RIGHT:
1013 case NONASSOC:
1014 declare_tokens(k);
1015 break;
1016
1017 case TYPE:
1018 declare_types();
1019 break;
1020
1021 case START:
1022 declare_start();
1023 break;
1024 }
1025 }
1026 }
1027
1028 void output_token_type(void)
1029 {
1030 bucket * bp;
1031 int n;
1032
1033 fprintf(interface_file, "type token =\n");
1034 if (!rflag) ++outline;
1035 fprintf(output_file, "type token =\n");
1036 n = 0;
1037 for (bp = first_symbol; bp; bp = bp->next) {
1038 if (bp->class == TERM && bp->true_token) {
1039 fprintf(interface_file, " | %s", bp->name);
1040 fprintf(output_file, " | %s", bp->name);
1041 if (bp->tag) {
1042 /* Print the type expression in parentheses to make sure
1043 that the constructor is unary */
1044 fprintf(interface_file, " of (%s)", bp->tag);
1045 fprintf(output_file, " of (%s)", bp->tag);
1046 }
1047 fprintf(interface_file, "\n");
1048 if (!rflag) ++outline;
1049 fprintf(output_file, "\n");
1050 n++;
1051 }
1052 }
1053 fprintf(interface_file, "\n");
1054 if (!rflag) ++outline;
1055 fprintf(output_file, "\n");
1056 }
1057
1058 void initialize_grammar(void)
1059 {
1060 nitems = 4;
1061 maxitems = 300;
1062 pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
1063 if (pitem == 0) no_space();
1064 pitem[0] = 0;
1065 pitem[1] = 0;
1066 pitem[2] = 0;
1067 pitem[3] = 0;
1068
1069 nrules = 3;
1070 maxrules = 100;
1071 plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
1072 if (plhs == 0) no_space();
1073 plhs[0] = 0;
1074 plhs[1] = 0;
1075 plhs[2] = 0;
1076 rprec = (short *) MALLOC(maxrules*sizeof(short));
1077 if (rprec == 0) no_space();
1078 rprec[0] = 0;
1079 rprec[1] = 0;
1080 rprec[2] = 0;
1081 rassoc = (char *) MALLOC(maxrules*sizeof(char));
1082 if (rassoc == 0) no_space();
1083 rassoc[0] = TOKEN;
1084 rassoc[1] = TOKEN;
1085 rassoc[2] = TOKEN;
1086 }
1087
1088
1089 void expand_items(void)
1090 {
1091 maxitems += 300;
1092 pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
1093 if (pitem == 0) no_space();
1094 }
1095
1096
1097 void expand_rules(void)
1098 {
1099 maxrules += 100;
1100 plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
1101 if (plhs == 0) no_space();
1102 rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
1103 if (rprec == 0) no_space();
1104 rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
1105 if (rassoc == 0) no_space();
1106 }
1107
1108
1109 void advance_to_start(void)
1110 {
1111 register int c;
1112 register bucket *bp;
1113 char *s_cptr;
1114 int s_lineno;
1115
1116 for (;;)
1117 {
1118 c = nextc();
1119 if (c != '%') break;
1120 s_cptr = cptr;
1121 switch (keyword())
1122 {
1123 case MARK:
1124 no_grammar();
1125
1126 case TEXT:
1127 copy_text();
1128 break;
1129
1130 case START:
1131 declare_start();
1132 break;
1133
1134 default:
1135 syntax_error(lineno, line, s_cptr);
1136 }
1137 }
1138
1139 c = nextc();
1140 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1141 syntax_error(lineno, line, cptr);
1142 bp = get_name();
1143 if (goal == 0)
1144 {
1145 if (bp->class == TERM)
1146 terminal_start(bp->name);
1147 goal = bp;
1148 }
1149
1150 s_lineno = lineno;
1151 c = nextc();
1152 if (c == EOF) unexpected_EOF();
1153 if (c != ':') syntax_error(lineno, line, cptr);
1154 start_rule(bp, s_lineno);
1155 ++cptr;
1156 }
1157
1158
1159 int at_first;
1160
1161 void start_rule(register bucket *bp, int s_lineno)
1162 {
1163 if (bp->class == TERM)
1164 terminal_lhs(s_lineno);
1165 bp->class = NONTERM;
1166 if (nrules >= maxrules)
1167 expand_rules();
1168 plhs[nrules] = bp;
1169 rprec[nrules] = UNDEFINED;
1170 rassoc[nrules] = TOKEN;
1171 at_first = 1;
1172 }
1173
1174
1175 void end_rule(void)
1176 {
1177 if (!last_was_action) default_action_error();
1178
1179 last_was_action = 0;
1180 if (nitems >= maxitems) expand_items();
1181 pitem[nitems] = 0;
1182 ++nitems;
1183 ++nrules;
1184 }
1185
1186
1187 void insert_empty_rule(void)
1188 {
1189 register bucket *bp, **bpp;
1190
1191 assert(cache);
1192 sprintf(cache, "$$%d", ++gensym);
1193 bp = make_bucket(cache);
1194 last_symbol->next = bp;
1195 last_symbol = bp;
1196 bp->tag = plhs[nrules]->tag;
1197 bp->class = NONTERM;
1198
1199 if ((nitems += 2) > maxitems)
1200 expand_items();
1201 bpp = pitem + nitems - 1;
1202 *bpp-- = bp;
1203 while ((bpp[0] = bpp[-1])) --bpp;
1204
1205 if (++nrules >= maxrules)
1206 expand_rules();
1207 plhs[nrules] = plhs[nrules-1];
1208 plhs[nrules-1] = bp;
1209 rprec[nrules] = rprec[nrules-1];
1210 rprec[nrules-1] = 0;
1211 rassoc[nrules] = rassoc[nrules-1];
1212 rassoc[nrules-1] = TOKEN;
1213 }
1214
1215
1216 void add_symbol(void)
1217 {
1218 register int c;
1219 register bucket *bp;
1220 int s_lineno = lineno;
1221 char *ecptr = cptr;
1222
1223 c = *cptr;
1224 if (c == '\'' || c == '"')
1225 bp = get_literal();
1226 else
1227 bp = get_name();
1228
1229 c = nextc();
1230 if (c == ':')
1231 {
1232 end_rule();
1233 start_rule(bp, s_lineno);
1234 ++cptr;
1235 return;
1236 }
1237
1238 if (last_was_action) syntax_error (lineno, line, ecptr);
1239 last_was_action = 0;
1240
1241 if (++nitems > maxitems)
1242 expand_items();
1243 pitem[nitems-1] = bp;
1244 }
1245
1246
1247 void copy_action(void)
1248 {
1249 register int c;
1250 register int i, n;
1251 int depth;
1252 bucket *item;
1253 char *tagres;
1254 register FILE *f = action_file;
1255 int a_lineno = lineno;
1256 char *a_line = dup_line();
1257 char *a_cptr = a_line + (cptr - line);
1258
1259 push_stack('{');
1260 if (last_was_action) syntax_error (lineno, line, cptr);
1261 last_was_action = 1;
1262
1263 /*
1264 fprintf(f, "(* Rule %d, file %s, line %d *)\n",
1265 nrules-2, input_file_name, lineno);
1266 */
1267 if (sflag)
1268 fprintf(f, "yyact.(%d) <- (fun __caml_parser_env ->\n", nrules-2);
1269 else
1270 fprintf(f, "; (fun __caml_parser_env ->\n");
1271
1272 n = 0;
1273 for (i = nitems - 1; pitem[i]; --i) ++n;
1274
1275 for (i = 1; i <= n; i++) {
1276 item = pitem[nitems + i - n - 1];
1277 if (item->class == TERM && !item->tag) continue;
1278 fprintf(f, " let _%d = ", i);
1279 if (item->tag)
1280 fprintf(f, "(Parsing.peek_val __caml_parser_env %d : %s) in\n", n - i,
1281 item->tag);
1282 else if (sflag)
1283 fprintf(f, "Parsing.peek_val __caml_parser_env %d in\n", n - i);
1284 else
1285 fprintf(f, "(Parsing.peek_val __caml_parser_env %d : '%s) in\n", n - i,
1286 item->name);
1287 }
1288 fprintf(f, " Obj.repr(\n");
1289 fprintf(f, line_format, lineno, input_file_name_disp);
1290 for (i = 0; i < cptr - line; i++) fputc(' ', f);
1291 fputc ('(', f);
1292
1293 depth = 1;
1294 cptr++;
1295
1296 loop:
1297 c = *cptr;
1298 if (c == '$')
1299 {
1300 if (isdigit((unsigned char) cptr[1]))
1301 {
1302 ++cptr;
1303 i = get_number();
1304
1305 if (i <= 0 || i > n)
1306 unknown_rhs(i);
1307 item = pitem[nitems + i - n - 1];
1308 if (item->class == TERM && !item->tag)
1309 illegal_token_ref(i, item->name);
1310 fprintf(f, "_%d", i);
1311 goto loop;
1312 }
1313 }
1314 if (c == '_' || c == '$' || In_bitmap(caml_ident_start, c))
1315 {
1316 do
1317 {
1318 putc(c, f);
1319 c = *++cptr;
1320 } while (c == '_' || c == '$' || In_bitmap(caml_ident_body, c));
1321 goto loop;
1322 }
1323 if (c == '}' && depth == 1) {
1324 fprintf(f, ")\n# 0\n ");
1325 cptr++;
1326 pop_stack('{');
1327 tagres = plhs[nrules]->tag;
1328 if (tagres)
1329 fprintf(f, " : %s))\n", tagres);
1330 else if (sflag)
1331 fprintf(f, "))\n");
1332 else
1333 fprintf(f, " : '%s))\n", plhs[nrules]->name);
1334 if (sflag)
1335 fprintf(f, "\n");
1336 FREE(a_line);
1337 return;
1338 }
1339 putc(c, f);
1340 ++cptr;
1341 switch (c)
1342 {
1343 case '\n':
1344 get_line();
1345 if (line) goto loop;
1346 unterminated_action(a_lineno, a_line, a_cptr);
1347
1348 case '{':
1349 process_open_curly_bracket(f);
1350 /* Even if there is a raw string, we deliberately keep the
1351 * closing '}' in the buffer */
1352 push_stack('{');
1353 ++depth;
1354 goto loop;
1355
1356 case '}':
1357 --depth;
1358 pop_stack('{');
1359 goto loop;
1360
1361 case '"':
1362 process_quoted_string('"', f);
1363 goto loop;
1364
1365 case '\'':
1366 process_apostrophe_body(f);
1367 goto loop;
1368
1369 case '(':
1370 push_stack('(');
1371 process_comment(f);
1372 goto loop;
1373
1374 case ')':
1375 pop_stack('(');
1376 goto loop;
1377
1378 default:
1379 goto loop;
1380 }
1381 }
1382
1383
1384 int
1385 mark_symbol(void)
1386 {
1387 register int c;
1388 register bucket *bp;
1389
1390 c = cptr[1];
1391 if (c == '%' || c == '\\')
1392 {
1393 cptr += 2;
1394 return (1);
1395 }
1396
1397 if (c == '=')
1398 cptr += 2;
1399 else if ((c == 'p' || c == 'P') &&
1400 ((c = cptr[2]) == 'r' || c == 'R') &&
1401 ((c = cptr[3]) == 'e' || c == 'E') &&
1402 ((c = cptr[4]) == 'c' || c == 'C') &&
1403 ((c = cptr[5], !IS_IDENT(c))))
1404 cptr += 5;
1405 else
1406 syntax_error(lineno, line, cptr);
1407
1408 c = nextc();
1409 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1410 bp = get_name();
1411 else if (c == '\'' || c == '"')
1412 bp = get_literal();
1413 else
1414 {
1415 syntax_error(lineno, line, cptr);
1416 /*NOTREACHED*/
1417 }
1418
1419 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1420 prec_redeclared();
1421
1422 rprec[nrules] = bp->prec;
1423 rassoc[nrules] = bp->assoc;
1424 return (0);
1425 }
1426
1427
1428 void read_grammar(void)
1429 {
1430 register int c;
1431
1432 initialize_grammar();
1433 advance_to_start();
1434
1435 for (;;)
1436 {
1437 c = nextc();
1438 if (c == '|' && at_first){
1439 ++cptr;
1440 c = nextc();
1441 }
1442 at_first = 0;
1443 if (c == EOF) break;
1444 if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
1445 c == '"')
1446 add_symbol();
1447 else if (c == '{' || c == '=')
1448 copy_action();
1449 else if (c == '|')
1450 {
1451 end_rule();
1452 start_rule(plhs[nrules-1], 0);
1453 ++cptr;
1454 }
1455 else if (c == '%')
1456 {
1457 if (mark_symbol()) break;
1458 }
1459 else
1460 syntax_error(lineno, line, cptr);
1461 }
1462 end_rule();
1463 }
1464
1465
1466 void free_tags(void)
1467 {
1468 register int i;
1469
1470 if (tag_table == 0) return;
1471
1472 for (i = 0; i < ntags; ++i)
1473 {
1474 assert(tag_table[i]);
1475 FREE(tag_table[i]);
1476 }
1477 FREE(tag_table);
1478 }
1479
1480
1481 void pack_names(void)
1482 {
1483 register bucket *bp;
1484 register char *p, *s, *t;
1485
1486 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
1487 for (bp = first_symbol; bp; bp = bp->next)
1488 name_pool_size += strlen(bp->name) + 1;
1489 name_pool = MALLOC(name_pool_size);
1490 if (name_pool == 0) no_space();
1491
1492 strcpy(name_pool, "$accept");
1493 strcpy(name_pool+8, "$end");
1494 t = name_pool + 13;
1495 for (bp = first_symbol; bp; bp = bp->next)
1496 {
1497 p = t;
1498 s = bp->name;
1499 while ((*t++ = *s++)) continue;
1500 FREE(bp->name);
1501 bp->name = p;
1502 }
1503 }
1504
1505
1506 void check_symbols(void)
1507 {
1508 register bucket *bp;
1509
1510 if (goal->class == UNKNOWN)
1511 undefined_goal(goal->name);
1512
1513 for (bp = first_symbol; bp; bp = bp->next)
1514 {
1515 if (bp->class == UNKNOWN)
1516 {
1517 undefined_symbol(bp->name);
1518 bp->class = TERM;
1519 }
1520 }
1521 }
1522
1523
1524 void pack_symbols(void)
1525 {
1526 register bucket *bp;
1527 register bucket **v;
1528 register int i, j, k, n;
1529
1530 nsyms = 2;
1531 ntokens = 1;
1532 for (bp = first_symbol; bp; bp = bp->next)
1533 {
1534 ++nsyms;
1535 if (bp->class == TERM) ++ntokens;
1536 }
1537 start_symbol = ntokens;
1538 nvars = nsyms - ntokens;
1539
1540 symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
1541 if (symbol_name == 0) no_space();
1542 symbol_value = (short *) MALLOC(nsyms*sizeof(short));
1543 if (symbol_value == 0) no_space();
1544 symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
1545 if (symbol_prec == 0) no_space();
1546 symbol_assoc = MALLOC(nsyms);
1547 if (symbol_assoc == 0) no_space();
1548 symbol_tag = (char **) MALLOC(nsyms*sizeof(char *));
1549 if (symbol_tag == 0) no_space();
1550 symbol_true_token = (char *) MALLOC(nsyms*sizeof(char));
1551 if (symbol_true_token == 0) no_space();
1552
1553 v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
1554 if (v == 0) no_space();
1555
1556 v[0] = 0;
1557 v[start_symbol] = 0;
1558
1559 i = 1;
1560 j = start_symbol + 1;
1561 for (bp = first_symbol; bp; bp = bp->next)
1562 {
1563 if (bp->class == TERM)
1564 v[i++] = bp;
1565 else
1566 v[j++] = bp;
1567 }
1568 assert(i == ntokens && j == nsyms);
1569
1570 for (i = 1; i < ntokens; ++i)
1571 v[i]->index = i;
1572
1573 goal->index = start_symbol + 1;
1574 k = start_symbol + 2;
1575 while (++i < nsyms)
1576 if (v[i] != goal)
1577 {
1578 v[i]->index = k;
1579 ++k;
1580 }
1581
1582 goal->value = 0;
1583 k = 1;
1584 for (i = start_symbol + 1; i < nsyms; ++i)
1585 {
1586 if (v[i] != goal)
1587 {
1588 v[i]->value = k;
1589 ++k;
1590 }
1591 }
1592
1593 k = 0;
1594 for (i = 1; i < ntokens; ++i)
1595 {
1596 n = v[i]->value;
1597 if (n > 256)
1598 {
1599 for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
1600 symbol_value[j] = symbol_value[j-1];
1601 symbol_value[j] = n;
1602 }
1603 }
1604
1605 if (v[1]->value == UNDEFINED)
1606 v[1]->value = 256;
1607
1608 j = 0;
1609 n = 257;
1610 for (i = 2; i < ntokens; ++i)
1611 {
1612 if (v[i]->value == UNDEFINED)
1613 {
1614 while (j < k && n == symbol_value[j])
1615 {
1616 while (++j < k && n == symbol_value[j]) continue;
1617 ++n;
1618 }
1619 v[i]->value = n;
1620 ++n;
1621 }
1622 }
1623
1624 symbol_name[0] = name_pool + 8;
1625 symbol_value[0] = 0;
1626 symbol_prec[0] = 0;
1627 symbol_assoc[0] = TOKEN;
1628 symbol_tag[0] = "";
1629 symbol_true_token[0] = 0;
1630 for (i = 1; i < ntokens; ++i)
1631 {
1632 symbol_name[i] = v[i]->name;
1633 symbol_value[i] = v[i]->value;
1634 symbol_prec[i] = v[i]->prec;
1635 symbol_assoc[i] = v[i]->assoc;
1636 symbol_tag[i] = v[i]->tag;
1637 symbol_true_token[i] = v[i]->true_token;
1638 }
1639 symbol_name[start_symbol] = name_pool;
1640 symbol_value[start_symbol] = -1;
1641 symbol_prec[start_symbol] = 0;
1642 symbol_assoc[start_symbol] = TOKEN;
1643 symbol_tag[start_symbol] = "";
1644 symbol_true_token[start_symbol] = 0;
1645 for (++i; i < nsyms; ++i)
1646 {
1647 k = v[i]->index;
1648 symbol_name[k] = v[i]->name;
1649 symbol_value[k] = v[i]->value;
1650 symbol_prec[k] = v[i]->prec;
1651 symbol_assoc[k] = v[i]->assoc;
1652 symbol_tag[i] = v[i]->tag;
1653 symbol_true_token[i] = v[i]->true_token;
1654 }
1655
1656 FREE(v);
1657 }
1658
1659 static int is_polymorphic(char * s)
1660 {
1661 while (*s != 0) {
1662 char c = *s++;
1663 if (c == '\'' || c == '#') return 1;
1664 if (c == '[') {
1665 c = *s;
1666 while (c == ' ' || c == '\t' || c == '\r' || c == '\n') c = *++s;
1667 if (c == '<' || c == '>') return 1;
1668 }
1669 if (In_bitmap(caml_ident_start, c)) {
1670 while (In_bitmap(caml_ident_body, *s)) s++;
1671 }
1672 }
1673 return 0;
1674 }
1675
1676 void make_goal(void)
1677 {
1678 static char name[7] = "'\\xxx'";
1679 bucket * bp;
1680 bucket * bc;
1681
1682 goal = lookup("%entry%");
1683 ntotalrules = nrules - 2;
1684 for(bp = first_symbol; bp != 0; bp = bp->next) {
1685 if (bp->entry) {
1686 start_rule(goal, 0);
1687 if (nitems + 2> maxitems)
1688 expand_items();
1689 name[2] = '0' + ((bp->entry >> 6) & 7);
1690 name[3] = '0' + ((bp->entry >> 3) & 7);
1691 name[4] = '0' + (bp->entry & 7);
1692 bc = lookup(name);
1693 bc->class = TERM;
1694 bc->value = (unsigned char) bp->entry;
1695 pitem[nitems++] = bc;
1696 pitem[nitems++] = bp;
1697 if (bp->tag == NULL)
1698 entry_without_type(bp->name);
1699 if (is_polymorphic(bp->tag))
1700 polymorphic_entry_point(bp->name);
1701 fprintf(entry_file,
1702 "let %s (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) =\n (Parsing.yyparse yytables %d lexfun lexbuf : %s)\n",
1703 bp->name, bp->entry, bp->tag);
1704 fprintf(interface_file,
1705 "val %s :\n (Lexing.lexbuf -> token) -> Lexing.lexbuf -> %s\n",
1706 bp->name,
1707 bp->tag);
1708 fprintf(action_file,
1709 "(* Entry %s *)\n", bp->name);
1710 if (sflag)
1711 fprintf(action_file,
1712 "yyact.(%d) <- (fun __caml_parser_env -> raise "
1713 "(Parsing.YYexit (Parsing.peek_val __caml_parser_env 0)))\n",
1714 ntotalrules);
1715 else
1716 fprintf(action_file,
1717 "; (fun __caml_parser_env -> raise "
1718 "(Parsing.YYexit (Parsing.peek_val __caml_parser_env 0)))\n");
1719 ntotalrules++;
1720 last_was_action = 1;
1721 end_rule();
1722 }
1723 }
1724 }
1725
1726 void pack_grammar(void)
1727 {
1728 register int i, j;
1729 int assoc, prec;
1730
1731 ritem = (short *) MALLOC(nitems*sizeof(short));
1732 if (ritem == 0) no_space();
1733 rlhs = (short *) MALLOC(nrules*sizeof(short));
1734 if (rlhs == 0) no_space();
1735 rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
1736 if (rrhs == 0) no_space();
1737 rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
1738 if (rprec == 0) no_space();
1739 rassoc = REALLOC(rassoc, nrules);
1740 if (rassoc == 0) no_space();
1741
1742 ritem[0] = -1;
1743 ritem[1] = goal->index;
1744 ritem[2] = 0;
1745 ritem[3] = -2;
1746 rlhs[0] = 0;
1747 rlhs[1] = 0;
1748 rlhs[2] = start_symbol;
1749 rrhs[0] = 0;
1750 rrhs[1] = 0;
1751 rrhs[2] = 1;
1752
1753 j = 4;
1754 for (i = 3; i < nrules; ++i)
1755 {
1756 rlhs[i] = plhs[i]->index;
1757 rrhs[i] = j;
1758 assoc = TOKEN;
1759 prec = 0;
1760 while (pitem[j])
1761 {
1762 ritem[j] = pitem[j]->index;
1763 if (pitem[j]->class == TERM)
1764 {
1765 prec = pitem[j]->prec;
1766 assoc = pitem[j]->assoc;
1767 }
1768 ++j;
1769 }
1770 ritem[j] = -i;
1771 ++j;
1772 if (rprec[i] == UNDEFINED)
1773 {
1774 rprec[i] = prec;
1775 rassoc[i] = assoc;
1776 }
1777 }
1778 rrhs[i] = j;
1779
1780 FREE(plhs);
1781 FREE(pitem);
1782 }
1783
1784
1785 void print_grammar(void)
1786 {
1787 register int i, j, k;
1788 int spacing = 0;
1789 register FILE *f = verbose_file;
1790
1791 if (!vflag) return;
1792
1793 k = 1;
1794 for (i = 2; i < nrules; ++i)
1795 {
1796 if (rlhs[i] != rlhs[i-1])
1797 {
1798 if (i != 2) fprintf(f, "\n");
1799 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
1800 spacing = strlen(symbol_name[rlhs[i]]) + 1;
1801 }
1802 else
1803 {
1804 fprintf(f, "%4d ", i - 2);
1805 j = spacing;
1806 while (--j >= 0) putc(' ', f);
1807 putc('|', f);
1808 }
1809
1810 while (ritem[k] >= 0)
1811 {
1812 fprintf(f, " %s", symbol_name[ritem[k]]);
1813 ++k;
1814 }
1815 ++k;
1816 putc('\n', f);
1817 }
1818 }
1819
1820
1821 void reader(void)
1822 {
1823 virtual_input_file_name = caml_stat_strdup_of_os(input_file_name);
1824 if (!virtual_input_file_name) no_space();
1825 create_symbol_table();
1826 read_declarations();
1827 output_token_type();
1828 read_grammar();
1829 make_goal();
1830 free_symbol_table();
1831 free_tags();
1832 pack_names();
1833 check_symbols();
1834 pack_symbols();
1835 pack_grammar();
1836 free_symbols();
1837 print_grammar();
1838 }
1839