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