2009-11-20 Marek Safar <marek.safar@gmail.com>
[mcs.git] / jay / reader.c
blob7096a6b4bba1c3c1c007423b833e85067198ce01
1 /*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Robert Paul Corbett.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
37 #ifndef lint
38 static char sccsid[] = "@(#)reader.c 5.7 (Berkeley) 1/20/91";
39 #endif /* not lint */
41 #include "defs.h"
43 /* The line size must be a positive integer. One hundred was chosen */
44 /* because few lines in Yacc input grammars exceed 100 characters. */
45 /* Note that if a line exceeds LINESIZE characters, the line buffer */
46 /* will be expanded to accomodate it. */
48 #define LINESIZE 100
50 char *cache;
51 int cinc, cache_size;
53 int ntags, tagmax;
54 char **tag_table;
56 char saw_eof;
57 char *cptr, *line;
58 int linesize;
60 bucket *goal;
61 int prec;
62 int gensym;
63 char last_was_action;
65 int maxitems;
66 bucket **pitem;
68 int maxrules;
69 bucket **plhs;
71 int name_pool_size;
72 char *name_pool;
74 char *line_format = "\t\t\t\t\t// line %d \"%s\"\n";
75 char *default_line_format = "\t\t\t\t\t// line %d\n";
78 cachec(c)
79 int c;
81 assert(cinc >= 0);
82 if (cinc >= cache_size)
84 cache_size += 256;
85 cache = REALLOC(cache, cache_size);
86 if (cache == 0) no_space();
88 cache[cinc] = c;
89 ++cinc;
93 get_line()
95 register FILE *f = input_file;
96 register int c;
97 register int i;
99 if (saw_eof || (c = getc(f)) == EOF)
101 if (line) { FREE(line); line = 0; }
102 cptr = 0;
103 saw_eof = 1;
104 return;
107 if (line == 0 || linesize != (LINESIZE + 1))
109 if (line) FREE(line);
110 linesize = LINESIZE + 1;
111 line = MALLOC(linesize);
112 if (line == 0) no_space();
115 i = 0;
116 ++lineno;
117 for (;;)
119 line[i] = c;
120 if (c == '\n') { cptr = line; return; }
121 if (++i >= linesize)
123 linesize += LINESIZE;
124 line = REALLOC(line, linesize);
125 if (line == 0) no_space();
127 c = getc(f);
128 if (c == EOF)
130 line[i] = '\n';
131 saw_eof = 1;
132 cptr = line;
133 return;
139 char *
140 dup_line()
142 register char *p, *s, *t;
144 if (line == 0) return (0);
145 s = line;
146 while (*s != '\n') ++s;
147 p = MALLOC(s - line + 1);
148 if (p == 0) no_space();
150 s = line;
151 t = p;
152 while ((*t++ = *s++) != '\n') continue;
153 return (p);
157 skip_comment()
159 register char *s;
161 int st_lineno = lineno;
162 char *st_line = dup_line();
163 char *st_cptr = st_line + (cptr - line);
165 s = cptr + 2;
166 for (;;)
168 if (*s == '*' && s[1] == '/')
170 cptr = s + 2;
171 FREE(st_line);
172 return;
174 if (*s == '\n')
176 get_line();
177 if (line == 0)
178 unterminated_comment(st_lineno, st_line, st_cptr);
179 s = cptr;
181 else
182 ++s;
188 nextc()
190 register char *s;
192 if (line == 0)
194 get_line();
195 if (line == 0)
196 return (EOF);
199 s = cptr;
200 for (;;)
202 switch (*s)
204 case '\n':
205 get_line();
206 if (line == 0) return (EOF);
207 s = cptr;
208 break;
210 case ' ':
211 case '\t':
212 case '\f':
213 case '\r':
214 case '\v':
215 case ',':
216 case ';':
217 ++s;
218 break;
220 case '\\':
221 cptr = s;
222 return ('%');
224 case '/':
225 if (s[1] == '*')
227 cptr = s;
228 skip_comment();
229 s = cptr;
230 break;
232 else if (s[1] == '/')
234 get_line();
235 if (line == 0) return (EOF);
236 s = cptr;
237 break;
239 /* fall through */
241 default:
242 cptr = s;
243 return (*s);
250 keyword()
252 register int c;
253 char *t_cptr = cptr;
255 c = *++cptr;
256 if (isalpha(c))
258 cinc = 0;
259 for (;;)
261 if (isalpha(c))
263 if (isupper(c)) c = tolower(c);
264 cachec(c);
266 else if (isdigit(c) || c == '_' || c == '.' || c == '$')
267 cachec(c);
268 else
269 break;
270 c = *++cptr;
272 cachec(NUL);
274 if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
275 return (TOKEN);
276 if (strcmp(cache, "type") == 0)
277 return (TYPE);
278 if (strcmp(cache, "left") == 0)
279 return (LEFT);
280 if (strcmp(cache, "right") == 0)
281 return (RIGHT);
282 if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
283 return (NONASSOC);
284 if (strcmp(cache, "start") == 0)
285 return (START);
287 else
289 ++cptr;
290 if (c == '{')
291 return (TEXT);
292 if (c == '%' || c == '\\')
293 return (MARK);
294 if (c == '<')
295 return (LEFT);
296 if (c == '>')
297 return (RIGHT);
298 if (c == '0')
299 return (TOKEN);
300 if (c == '2')
301 return (NONASSOC);
303 syntax_error(lineno, line, t_cptr);
304 /*NOTREACHED*/
308 copy_text(f)
309 FILE *f;
311 register int c;
312 int quote;
313 int need_newline = 0;
314 int t_lineno = lineno;
315 char *t_line = dup_line();
316 char *t_cptr = t_line + (cptr - line - 2);
318 if (*cptr == '\n')
320 get_line();
321 if (line == 0)
322 unterminated_text(t_lineno, t_line, t_cptr);
324 fprintf(f, line_format, lineno, input_file_name);
326 loop:
327 c = *cptr++;
328 switch (c)
330 case '\n':
331 next_line:
332 putc('\n', f);
333 need_newline = 0;
334 get_line();
335 if (line) goto loop;
336 unterminated_text(t_lineno, t_line, t_cptr);
338 case '\'':
339 case '"':
341 int s_lineno = lineno;
342 char *s_line = dup_line();
343 char *s_cptr = s_line + (cptr - line - 1);
345 quote = c;
346 putc(c, f);
347 for (;;)
349 c = *cptr++;
350 putc(c, f);
351 if (c == quote)
353 need_newline = 1;
354 FREE(s_line);
355 goto loop;
357 if (c == '\n')
358 unterminated_string(s_lineno, s_line, s_cptr);
359 if (c == '\\')
361 c = *cptr++;
362 putc(c, f);
363 if (c == '\n')
365 get_line();
366 if (line == 0)
367 unterminated_string(s_lineno, s_line, s_cptr);
373 case '/':
374 putc(c, f);
375 need_newline = 1;
376 c = *cptr;
377 if (c == '/')
379 do putc(c, f); while ((c = *++cptr) != '\n');
380 goto next_line;
382 if (c == '*')
384 int c_lineno = lineno;
385 char *c_line = dup_line();
386 char *c_cptr = c_line + (cptr - line - 1);
388 putc('*', f);
389 ++cptr;
390 for (;;)
392 c = *cptr++;
393 putc(c, f);
394 if (c == '*' && *cptr == '/')
396 putc('/', f);
397 ++cptr;
398 FREE(c_line);
399 goto loop;
401 if (c == '\n')
403 get_line();
404 if (line == 0)
405 unterminated_comment(c_lineno, c_line, c_cptr);
409 need_newline = 1;
410 goto loop;
412 case '%':
413 case '\\':
414 if (*cptr == '}')
416 if (need_newline) putc('\n', f);
417 ++cptr;
418 FREE(t_line);
419 return;
421 /* fall through */
423 default:
424 putc(c, f);
425 need_newline = 1;
426 goto loop;
431 hexval(c)
432 int c;
434 if (c >= '0' && c <= '9')
435 return (c - '0');
436 if (c >= 'A' && c <= 'F')
437 return (c - 'A' + 10);
438 if (c >= 'a' && c <= 'f')
439 return (c - 'a' + 10);
440 return (-1);
444 bucket *
445 get_literal()
447 register int c, quote;
448 register int i;
449 register int n;
450 register char *s;
451 register bucket *bp;
452 int s_lineno = lineno;
453 char *s_line = dup_line();
454 char *s_cptr = s_line + (cptr - line);
456 quote = *cptr++;
457 cinc = 0;
458 for (;;)
460 c = *cptr++;
461 if (c == quote) break;
462 if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
463 if (c == '\\')
465 char *c_cptr = cptr - 1;
467 c = *cptr++;
468 switch (c)
470 case '\n':
471 get_line();
472 if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
473 continue;
475 case '0': case '1': case '2': case '3':
476 case '4': case '5': case '6': case '7':
477 n = c - '0';
478 c = *cptr;
479 if (IS_OCTAL(c))
481 n = (n << 3) + (c - '0');
482 c = *++cptr;
483 if (IS_OCTAL(c))
485 n = (n << 3) + (c - '0');
486 ++cptr;
489 if (n > MAXCHAR) illegal_character(c_cptr);
490 c = n;
491 break;
493 case 'x':
494 c = *cptr++;
495 n = hexval(c);
496 if (n < 0 || n >= 16)
497 illegal_character(c_cptr);
498 for (;;)
500 c = *cptr;
501 i = hexval(c);
502 if (i < 0 || i >= 16) break;
503 ++cptr;
504 n = (n << 4) + i;
505 if (n > MAXCHAR) illegal_character(c_cptr);
507 c = n;
508 break;
510 case 'a': c = 7; break;
511 case 'b': c = '\b'; break;
512 case 'f': c = '\f'; break;
513 case 'n': c = '\n'; break;
514 case 'r': c = '\r'; break;
515 case 't': c = '\t'; break;
516 case 'v': c = '\v'; break;
519 cachec(c);
521 FREE(s_line);
523 n = cinc;
524 s = MALLOC(n);
525 if (s == 0) no_space();
527 for (i = 0; i < n; ++i)
528 s[i] = cache[i];
530 cinc = 0;
531 if (n == 1)
532 cachec('\'');
533 else
534 cachec('"');
536 for (i = 0; i < n; ++i)
538 c = ((unsigned char *)s)[i];
539 if (c == '\\' || c == cache[0])
541 cachec('\\');
542 cachec(c);
544 else if (isprint(c))
545 cachec(c);
546 else
548 cachec('\\');
549 switch (c)
551 case 7: cachec('a'); break;
552 case '\b': cachec('b'); break;
553 case '\f': cachec('f'); break;
554 case '\n': cachec('n'); break;
555 case '\r': cachec('r'); break;
556 case '\t': cachec('t'); break;
557 case '\v': cachec('v'); break;
558 default:
559 cachec(((c >> 6) & 7) + '0');
560 cachec(((c >> 3) & 7) + '0');
561 cachec((c & 7) + '0');
562 break;
567 if (n == 1)
568 cachec('\'');
569 else
570 cachec('"');
572 cachec(NUL);
573 bp = lookup(cache);
574 bp->class = TERM;
575 if (n == 1 && bp->value == UNDEFINED)
576 bp->value = *(unsigned char *)s;
577 FREE(s);
579 return (bp);
584 is_reserved(name)
585 char *name;
587 char *s;
589 if (strcmp(name, ".") == 0 ||
590 strcmp(name, "$accept") == 0 ||
591 strcmp(name, "$end") == 0)
592 return (1);
594 if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
596 s = name + 3;
597 while (isdigit(*s)) ++s;
598 if (*s == NUL) return (1);
601 return (0);
605 bucket *
606 get_name()
608 register int c;
610 cinc = 0;
611 for (c = *cptr; IS_IDENT(c); c = *++cptr)
612 cachec(c);
613 cachec(NUL);
615 if (is_reserved(cache)) used_reserved(cache);
617 return (lookup(cache));
622 get_number()
624 register int c;
625 register int n;
627 n = 0;
628 for (c = *cptr; isdigit(c); c = *++cptr)
629 n = 10*n + (c - '0');
631 return (n);
635 char *
636 get_tag(int emptyOk)
638 register int c;
639 register int i;
640 register char *s;
641 int t_lineno = lineno;
642 char *t_line = dup_line();
643 char *t_cptr = t_line + (cptr - line);
645 ++cptr;
646 c = nextc();
647 if (c == EOF) unexpected_EOF();
648 if (emptyOk && c == '>') {
649 ++cptr; return 0; // 0 indicates empty tag if emptyOk
651 if (!isalpha(c) && c != '_' && c != '$')
652 illegal_tag(t_lineno, t_line, t_cptr);
654 cinc = 0;
655 do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
656 cachec(NUL);
658 c = nextc();
659 if (c == EOF) unexpected_EOF();
660 if (c != '>')
661 illegal_tag(t_lineno, t_line, t_cptr);
662 ++cptr;
664 for (i = 0; i < ntags; ++i)
666 if (strcmp(cache, tag_table[i]) == 0)
667 return (tag_table[i]);
670 if (ntags >= tagmax)
672 tagmax += 16;
673 tag_table = (char **)
674 (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
675 : MALLOC(tagmax*sizeof(char *)));
676 if (tag_table == 0) no_space();
679 s = MALLOC(cinc);
680 if (s == 0) no_space();
681 strcpy(s, cache);
682 tag_table[ntags] = s;
683 ++ntags;
684 FREE(t_line);
685 return (s);
689 declare_tokens(assoc)
690 int assoc;
692 register int c;
693 register bucket *bp;
694 int value;
695 char *tag = 0;
697 if (assoc != TOKEN) ++prec;
699 c = nextc();
700 if (c == EOF) unexpected_EOF();
701 if (c == '<')
703 tag = get_tag(0);
704 c = nextc();
705 if (c == EOF) unexpected_EOF();
708 for (;;)
710 if (isalpha(c) || c == '_' || c == '.' || c == '$')
711 bp = get_name();
712 else if (c == '\'' || c == '"')
713 bp = get_literal();
714 else
715 return;
717 if (bp == goal) tokenized_start(bp->name);
718 bp->class = TERM;
720 if (tag)
722 if (bp->tag && tag != bp->tag)
723 retyped_warning(bp->name);
724 bp->tag = tag;
727 if (assoc != TOKEN)
729 if (bp->prec && prec != bp->prec)
730 reprec_warning(bp->name);
731 bp->assoc = assoc;
732 bp->prec = prec;
735 c = nextc();
736 if (c == EOF) unexpected_EOF();
737 value = UNDEFINED;
738 if (isdigit(c))
740 value = get_number();
741 if (bp->value != UNDEFINED && value != bp->value)
742 revalued_warning(bp->name);
743 bp->value = value;
744 c = nextc();
745 if (c == EOF) unexpected_EOF();
751 declare_types()
753 register int c;
754 register bucket *bp;
755 char *tag;
757 c = nextc();
758 if (c == EOF) unexpected_EOF();
759 if (c != '<') syntax_error(lineno, line, cptr);
760 tag = get_tag(0);
762 for (;;)
764 c = nextc();
765 if (isalpha(c) || c == '_' || c == '.' || c == '$')
766 bp = get_name();
767 else if (c == '\'' || c == '"')
768 bp = get_literal();
769 else
770 return;
772 if (bp->tag && tag != bp->tag)
773 retyped_warning(bp->name);
774 bp->tag = tag;
779 declare_start()
781 register int c;
782 register bucket *bp;
784 c = nextc();
785 if (c == EOF) unexpected_EOF();
786 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
787 syntax_error(lineno, line, cptr);
788 bp = get_name();
789 if (bp->class == TERM)
790 terminal_start(bp->name);
791 if (goal && goal != bp)
792 restarted_warning();
793 goal = bp;
797 read_declarations()
799 register int c, k;
801 cache_size = 256;
802 cache = MALLOC(cache_size);
803 if (cache == 0) no_space();
805 for (;;)
807 c = nextc();
808 if (c == EOF) unexpected_EOF();
809 if (c != '%') syntax_error(lineno, line, cptr);
810 switch (k = keyword())
812 case MARK:
813 return;
815 case TEXT:
816 copy_text(prolog_file);
817 break;
819 case TOKEN:
820 case LEFT:
821 case RIGHT:
822 case NONASSOC:
823 declare_tokens(k);
824 break;
826 case TYPE:
827 declare_types();
828 break;
830 case START:
831 declare_start();
832 break;
838 initialize_grammar()
840 nitems = 4;
841 maxitems = 300;
842 pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
843 if (pitem == 0) no_space();
844 pitem[0] = 0;
845 pitem[1] = 0;
846 pitem[2] = 0;
847 pitem[3] = 0;
849 nrules = 3;
850 maxrules = 100;
851 plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
852 if (plhs == 0) no_space();
853 plhs[0] = 0;
854 plhs[1] = 0;
855 plhs[2] = 0;
856 rprec = (short *) MALLOC(maxrules*sizeof(short));
857 if (rprec == 0) no_space();
858 rprec[0] = 0;
859 rprec[1] = 0;
860 rprec[2] = 0;
861 rassoc = (char *) MALLOC(maxrules*sizeof(char));
862 if (rassoc == 0) no_space();
863 rassoc[0] = TOKEN;
864 rassoc[1] = TOKEN;
865 rassoc[2] = TOKEN;
869 expand_items()
871 maxitems += 300;
872 pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
873 if (pitem == 0) no_space();
877 expand_rules()
879 maxrules += 100;
880 plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
881 if (plhs == 0) no_space();
882 rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
883 if (rprec == 0) no_space();
884 rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
885 if (rassoc == 0) no_space();
889 advance_to_start()
891 register int c;
892 register bucket *bp;
893 char *s_cptr;
894 int s_lineno;
896 for (;;)
898 c = nextc();
899 if (c != '%') break;
900 s_cptr = cptr;
901 switch (keyword())
903 case MARK:
904 no_grammar();
906 case TEXT:
907 copy_text(local_file);
908 break;
910 case START:
911 declare_start();
912 break;
914 default:
915 syntax_error(lineno, line, s_cptr);
919 c = nextc();
920 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
921 syntax_error(lineno, line, cptr);
922 bp = get_name();
923 if (goal == 0)
925 if (bp->class == TERM)
926 terminal_start(bp->name);
927 goal = bp;
930 s_lineno = lineno;
931 c = nextc();
932 if (c == EOF) unexpected_EOF();
933 if (c != ':') syntax_error(lineno, line, cptr);
934 start_rule(bp, s_lineno);
935 ++cptr;
939 start_rule(bp, s_lineno)
940 register bucket *bp;
941 int s_lineno;
943 if (bp->class == TERM)
944 terminal_lhs(s_lineno);
945 bp->class = NONTERM;
946 if (nrules >= maxrules)
947 expand_rules();
948 plhs[nrules] = bp;
949 rprec[nrules] = UNDEFINED;
950 rassoc[nrules] = TOKEN;
954 end_rule()
956 register int i;
958 if (!last_was_action && plhs[nrules]->tag)
960 for (i = nitems - 1; pitem[i]; --i) continue;
961 if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
962 default_action_warning(); /** if classes don't match exactly **/
963 } /** bug: could be superclass... **/
965 last_was_action = 0;
966 if (nitems >= maxitems) expand_items();
967 pitem[nitems] = 0;
968 ++nitems;
969 ++nrules;
973 insert_empty_rule()
975 register bucket *bp, **bpp;
977 assert(cache);
978 sprintf(cache, "$$%d", ++gensym);
979 bp = make_bucket(cache);
980 last_symbol->next = bp;
981 last_symbol = bp;
982 bp->tag = plhs[nrules]->tag;
983 bp->class = NONTERM;
985 if ((nitems += 2) > maxitems)
986 expand_items();
987 bpp = pitem + nitems - 1;
988 *bpp-- = bp;
989 while (bpp[0] = bpp[-1]) --bpp;
991 if (++nrules >= maxrules)
992 expand_rules();
993 plhs[nrules] = plhs[nrules-1];
994 plhs[nrules-1] = bp;
995 rprec[nrules] = rprec[nrules-1];
996 rprec[nrules-1] = 0;
997 rassoc[nrules] = rassoc[nrules-1];
998 rassoc[nrules-1] = TOKEN;
1002 add_symbol()
1004 register int c;
1005 register bucket *bp;
1006 int s_lineno = lineno;
1008 c = *cptr;
1009 if (c == '\'' || c == '"')
1010 bp = get_literal();
1011 else
1012 bp = get_name();
1014 c = nextc();
1015 if (c == ':')
1017 end_rule();
1018 start_rule(bp, s_lineno);
1019 ++cptr;
1020 return;
1023 if (last_was_action)
1024 insert_empty_rule();
1025 last_was_action = 0;
1027 if (++nitems > maxitems)
1028 expand_items();
1029 pitem[nitems-1] = bp;
1033 copy_action()
1035 register int c;
1036 register int i, n;
1037 int depth;
1038 int quote;
1039 char *tag;
1040 register FILE *f = action_file;
1041 int a_lineno = lineno;
1042 char *a_line = dup_line();
1043 char *a_cptr = a_line + (cptr - line);
1045 if (last_was_action)
1046 insert_empty_rule();
1047 last_was_action = 1;
1049 fprintf(f, "case %d:\n", nrules - 2);
1050 fprintf(f, line_format, lineno, input_file_name);
1051 putc(' ', f); putc(' ', f);
1052 if (*cptr == '=') ++cptr;
1054 n = 0;
1055 for (i = nitems - 1; pitem[i]; --i) ++n;
1057 depth = 0;
1058 loop:
1059 c = *cptr;
1060 if (c == '$')
1062 if (cptr[1] == '<')
1064 int d_lineno = lineno;
1065 char *d_line = dup_line();
1066 char *d_cptr = d_line + (cptr - line);
1068 ++cptr;
1069 tag = get_tag(1);
1070 c = *cptr;
1071 if (c == '$')
1072 { if (tag && strcmp(tag, "Object"))
1073 fprintf(f, "((%s)yyVal)", tag);
1074 else fprintf(f, "yyVal");
1075 ++cptr;
1076 FREE(d_line);
1077 goto loop;
1079 else if (isdigit(c))
1081 i = get_number();
1082 if (i > n) dollar_warning(d_lineno, i);
1083 if (tag && strcmp(tag, "Object"))
1084 fprintf(f, "((%s)yyVals[%d+yyTop])", tag, i - n);
1085 else fprintf(f, "yyVals[%d+yyTop]", i - n);
1086 FREE(d_line);
1087 goto loop;
1089 else if (c == '-' && isdigit(cptr[1]))
1091 ++cptr;
1092 i = -get_number() - n;
1093 if (tag && strcmp(tag, "Object"))
1094 fprintf(f, "((%s)yyVals[%d+yyTop])", tag, i);
1095 else fprintf(f, "yyVals[%d+yyTop]", i);
1096 FREE(d_line);
1097 goto loop;
1099 else
1100 dollar_error(d_lineno, d_line, d_cptr);
1102 else if (cptr[1] == '$')
1104 if (ntags && plhs[nrules]->tag == 0)
1105 untyped_lhs();
1106 fprintf(f, "yyVal");
1107 cptr += 2;
1108 goto loop;
1110 else if (isdigit(cptr[1]))
1112 ++cptr;
1113 i = get_number();
1114 if (ntags)
1116 if (i <= 0 || i > n)
1117 unknown_rhs(i);
1118 tag = pitem[nitems + i - n - 1]->tag;
1119 if (tag == 0)
1120 untyped_rhs(i, pitem[nitems + i - n - 1]->name),
1121 fprintf(f, "yyVals[%d+yyTop]", i - n);
1122 else if (strcmp(tag, "Object"))
1123 fprintf(f, "((%s)yyVals[%d+yyTop])", tag, i - n);
1124 else
1125 fprintf(f, "yyVals[%d+yyTop]", i - n);
1127 else
1129 if (i > n)
1130 dollar_warning(lineno, i);
1131 fprintf(f, "yyVals[%d+yyTop]", i - n);
1133 goto loop;
1135 else if (cptr[1] == '-')
1137 cptr += 2;
1138 i = get_number();
1139 if (ntags)
1140 unknown_rhs(-i);
1141 fprintf(f, "yyVals[%d+yyTop]", -i - n);
1142 goto loop;
1145 if (isalpha(c) || c == '_' || c == '$')
1149 putc(c, f);
1150 c = *++cptr;
1151 } while (isalnum(c) || c == '_' || c == '$');
1152 goto loop;
1154 putc(c, f);
1155 ++cptr;
1156 switch (c)
1158 case '\n':
1159 next_line:
1160 get_line();
1161 if (line) goto loop;
1162 unterminated_action(a_lineno, a_line, a_cptr);
1164 case ';':
1165 if (depth > 0) goto loop;
1166 fprintf(f, "\nbreak;\n");
1167 return;
1169 case '{':
1170 ++depth;
1171 goto loop;
1173 case '}':
1174 if (--depth > 0) goto loop;
1175 fprintf(f, "\n break;\n");
1176 return;
1178 case '\'':
1179 case '"':
1181 int s_lineno = lineno;
1182 char *s_line = dup_line();
1183 char *s_cptr = s_line + (cptr - line - 1);
1185 quote = c;
1186 for (;;)
1188 c = *cptr++;
1189 putc(c, f);
1190 if (c == quote)
1192 FREE(s_line);
1193 goto loop;
1195 if (c == '\n')
1196 unterminated_string(s_lineno, s_line, s_cptr);
1197 if (c == '\\')
1199 c = *cptr++;
1200 putc(c, f);
1201 if (c == '\n')
1203 get_line();
1204 if (line == 0)
1205 unterminated_string(s_lineno, s_line, s_cptr);
1211 case '/':
1212 c = *cptr;
1213 if (c == '/')
1215 putc('*', f);
1216 while ((c = *++cptr) != '\n')
1218 if (c == '*' && cptr[1] == '/')
1219 fprintf(f, "* ");
1220 else
1221 putc(c, f);
1223 fprintf(f, "*/\n");
1224 goto next_line;
1226 if (c == '*')
1228 int c_lineno = lineno;
1229 char *c_line = dup_line();
1230 char *c_cptr = c_line + (cptr - line - 1);
1232 putc('*', f);
1233 ++cptr;
1234 for (;;)
1236 c = *cptr++;
1237 putc(c, f);
1238 if (c == '*' && *cptr == '/')
1240 putc('/', f);
1241 ++cptr;
1242 FREE(c_line);
1243 goto loop;
1245 if (c == '\n')
1247 get_line();
1248 if (line == 0)
1249 unterminated_comment(c_lineno, c_line, c_cptr);
1253 goto loop;
1255 default:
1256 goto loop;
1262 mark_symbol()
1264 register int c;
1265 register bucket *bp;
1267 c = cptr[1];
1268 if (c == '%' || c == '\\')
1270 cptr += 2;
1271 return (1);
1274 if (c == '=')
1275 cptr += 2;
1276 else if ((c == 'p' || c == 'P') &&
1277 ((c = cptr[2]) == 'r' || c == 'R') &&
1278 ((c = cptr[3]) == 'e' || c == 'E') &&
1279 ((c = cptr[4]) == 'c' || c == 'C') &&
1280 ((c = cptr[5], !IS_IDENT(c))))
1281 cptr += 5;
1282 else
1283 syntax_error(lineno, line, cptr);
1285 c = nextc();
1286 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1287 bp = get_name();
1288 else if (c == '\'' || c == '"')
1289 bp = get_literal();
1290 else
1292 syntax_error(lineno, line, cptr);
1293 /*NOTREACHED*/
1296 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1297 prec_redeclared();
1299 rprec[nrules] = bp->prec;
1300 rassoc[nrules] = bp->assoc;
1301 return (0);
1305 read_grammar()
1307 register int c;
1309 initialize_grammar();
1310 advance_to_start();
1312 for (;;)
1314 c = nextc();
1315 if (c == EOF) break;
1316 if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
1317 c == '"')
1318 add_symbol();
1319 else if (c == '{' || c == '=')
1320 copy_action();
1321 else if (c == '|')
1323 end_rule();
1324 start_rule(plhs[nrules-1], 0);
1325 ++cptr;
1327 else if (c == '%')
1329 if (mark_symbol()) break;
1331 else
1332 syntax_error(lineno, line, cptr);
1334 end_rule();
1338 free_tags()
1340 register int i;
1342 if (tag_table == 0) return;
1344 for (i = 0; i < ntags; ++i)
1346 assert(tag_table[i]);
1347 FREE(tag_table[i]);
1349 FREE(tag_table);
1353 pack_names()
1355 register bucket *bp;
1356 register char *p, *s, *t;
1358 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
1359 for (bp = first_symbol; bp; bp = bp->next)
1360 name_pool_size += strlen(bp->name) + 1;
1361 name_pool = MALLOC(name_pool_size);
1362 if (name_pool == 0) no_space();
1364 strcpy(name_pool, "$accept");
1365 strcpy(name_pool+8, "$end");
1366 t = name_pool + 13;
1367 for (bp = first_symbol; bp; bp = bp->next)
1369 p = t;
1370 s = bp->name;
1371 while (*t++ = *s++) continue;
1372 FREE(bp->name);
1373 bp->name = p;
1378 check_symbols()
1380 register bucket *bp;
1382 if (goal->class == UNKNOWN)
1383 undefined_goal(goal->name);
1385 for (bp = first_symbol; bp; bp = bp->next)
1387 if (bp->class == UNKNOWN)
1389 undefined_symbol_warning(bp->name);
1390 bp->class = TERM;
1396 pack_symbols()
1398 register bucket *bp;
1399 register bucket **v;
1400 register int i, j, k, n;
1402 nsyms = 2;
1403 ntokens = 1;
1404 for (bp = first_symbol; bp; bp = bp->next)
1406 ++nsyms;
1407 if (bp->class == TERM) ++ntokens;
1409 start_symbol = ntokens;
1410 nvars = nsyms - ntokens;
1412 symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
1413 if (symbol_name == 0) no_space();
1414 symbol_value = (short *) MALLOC(nsyms*sizeof(short));
1415 if (symbol_value == 0) no_space();
1416 symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
1417 if (symbol_prec == 0) no_space();
1418 symbol_assoc = MALLOC(nsyms);
1419 if (symbol_assoc == 0) no_space();
1421 v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
1422 if (v == 0) no_space();
1424 v[0] = 0;
1425 v[start_symbol] = 0;
1427 i = 1;
1428 j = start_symbol + 1;
1429 for (bp = first_symbol; bp; bp = bp->next)
1431 if (bp->class == TERM)
1432 v[i++] = bp;
1433 else
1434 v[j++] = bp;
1436 assert(i == ntokens && j == nsyms);
1438 for (i = 1; i < ntokens; ++i)
1439 v[i]->index = i;
1441 goal->index = start_symbol + 1;
1442 k = start_symbol + 2;
1443 while (++i < nsyms)
1444 if (v[i] != goal)
1446 v[i]->index = k;
1447 ++k;
1450 goal->value = 0;
1451 k = 1;
1452 for (i = start_symbol + 1; i < nsyms; ++i)
1454 if (v[i] != goal)
1456 v[i]->value = k;
1457 ++k;
1461 k = 0;
1462 for (i = 1; i < ntokens; ++i)
1464 n = v[i]->value;
1465 if (n > 256)
1467 for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
1468 symbol_value[j] = symbol_value[j-1];
1469 symbol_value[j] = n;
1473 if (v[1]->value == UNDEFINED)
1474 v[1]->value = 256;
1476 j = 0;
1477 n = 257;
1478 for (i = 2; i < ntokens; ++i)
1480 if (v[i]->value == UNDEFINED)
1482 while (j < k && n == symbol_value[j])
1484 while (++j < k && n == symbol_value[j]) continue;
1485 ++n;
1487 v[i]->value = n;
1488 ++n;
1492 symbol_name[0] = name_pool + 8;
1493 symbol_value[0] = 0;
1494 symbol_prec[0] = 0;
1495 symbol_assoc[0] = TOKEN;
1496 for (i = 1; i < ntokens; ++i)
1498 symbol_name[i] = v[i]->name;
1499 symbol_value[i] = v[i]->value;
1500 symbol_prec[i] = v[i]->prec;
1501 symbol_assoc[i] = v[i]->assoc;
1503 symbol_name[start_symbol] = name_pool;
1504 symbol_value[start_symbol] = -1;
1505 symbol_prec[start_symbol] = 0;
1506 symbol_assoc[start_symbol] = TOKEN;
1507 for (++i; i < nsyms; ++i)
1509 k = v[i]->index;
1510 symbol_name[k] = v[i]->name;
1511 symbol_value[k] = v[i]->value;
1512 symbol_prec[k] = v[i]->prec;
1513 symbol_assoc[k] = v[i]->assoc;
1516 FREE(v);
1520 pack_grammar()
1522 register int i, j;
1523 int assoc, prec;
1525 ritem = (short *) MALLOC(nitems*sizeof(short));
1526 if (ritem == 0) no_space();
1527 rlhs = (short *) MALLOC(nrules*sizeof(short));
1528 if (rlhs == 0) no_space();
1529 rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
1530 if (rrhs == 0) no_space();
1531 rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
1532 if (rprec == 0) no_space();
1533 rassoc = REALLOC(rassoc, nrules);
1534 if (rassoc == 0) no_space();
1536 ritem[0] = -1;
1537 ritem[1] = goal->index;
1538 ritem[2] = 0;
1539 ritem[3] = -2;
1540 rlhs[0] = 0;
1541 rlhs[1] = 0;
1542 rlhs[2] = start_symbol;
1543 rrhs[0] = 0;
1544 rrhs[1] = 0;
1545 rrhs[2] = 1;
1547 j = 4;
1548 for (i = 3; i < nrules; ++i)
1550 rlhs[i] = plhs[i]->index;
1551 rrhs[i] = j;
1552 assoc = TOKEN;
1553 prec = 0;
1554 while (pitem[j])
1556 ritem[j] = pitem[j]->index;
1557 if (pitem[j]->class == TERM)
1559 prec = pitem[j]->prec;
1560 assoc = pitem[j]->assoc;
1562 ++j;
1564 ritem[j] = -i;
1565 ++j;
1566 if (rprec[i] == UNDEFINED)
1568 rprec[i] = prec;
1569 rassoc[i] = assoc;
1572 rrhs[i] = j;
1574 FREE(plhs);
1575 FREE(pitem);
1579 print_grammar()
1581 register int i, j, k;
1582 int spacing;
1583 register FILE *f = verbose_file;
1585 if (!vflag) return;
1587 k = 1;
1588 for (i = 2; i < nrules; ++i)
1590 if (rlhs[i] != rlhs[i-1])
1592 if (i != 2) fprintf(f, "\n");
1593 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
1594 spacing = strlen(symbol_name[rlhs[i]]) + 1;
1596 else
1598 fprintf(f, "%4d ", i - 2);
1599 j = spacing;
1600 while (--j >= 0) putc(' ', f);
1601 putc('|', f);
1604 while (ritem[k] >= 0)
1606 fprintf(f, " %s", symbol_name[ritem[k]]);
1607 ++k;
1609 ++k;
1610 putc('\n', f);
1615 reader()
1617 create_symbol_table();
1618 read_declarations();
1619 read_grammar();
1620 free_symbol_table();
1621 free_tags();
1622 pack_names();
1623 check_symbols();
1624 pack_symbols();
1625 pack_grammar();
1626 free_symbols();
1627 print_grammar();