source: trunk/minix/commands/byacc/reader.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

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