%{ #include #include #include #include #include #include #include #define YYSTYPE char * void prttok(FILE *iop, int type, YYSTYPE val); #define YYPRINT(file, type, value) prttok(file, type, value) char **fstk[512], ***topstk = fstk; char *toklst[256], **toktop; char labbuf[256]; size_t yyleng; /* Length of the token currently processed (without \0) */ int line = 1; #define PRESENT 0x01 #define ACTIVE 0x02 struct symbol { struct symbol *next; char ty; unsigned flg; }; void yyerror(const char *fmt, ...) { va_list ap; fprintf(stderr, "%d: ", line); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); } char ***pushstk(char **p) { if (topstk == fstk + sizeof fstk / sizeof *fstk) return NULL; *topstk++ = p; return topstk; } void popstk(void) { while (topstk > fstk && *--topstk != NULL) { /* Remove nonterminal symbol association. */ if ((*topstk)[1][1] == 'f') { register struct symbol *sym = (struct symbol *)((*topstk)[3] - sizeof *sym); sym->flg &= ~ACTIVE; } free(*topstk); } } void dumplst(FILE *iop, char **q) { if (!*q) return; fprintf(iop, "\"%s\"", *q); while (*++q) fprintf(iop, ", \"%s\"", *q); } void dumpstk(void) { char ***p; for (p = fstk; p < topstk; p++) { if (!*p) { fprintf(stderr, "---------\n"); continue; } fprintf(stderr, "<%s, ", (*p)[0] ? (*p)[0] : "<>"); dumplst(stderr, *p + 1); fprintf(stderr, ">\n"); } } void printnt(char *s) { /* Print a yacc style nonterminal */ char *graph = "-|"; /* Characters yacc can't handle in NT idents */ char *replac[] = {"mt", "st"}; /* replacement for them */ while (*s) { char *t = strchr(graph, *s); if (t) fputs(replac[t - graph], stdout); else putchar(*s); s++; } } void printt(char *s) { /* print a yacc style string terminal.*/ putchar('\"'); while (*s) { if (*s == '\\' || *s == '\"') putchar('\\'); putchar(*s++); } putchar('\"'); } int yylex(void); %} %token TOKEN %% stmlst : stmt | stmlst stmt ; stortk : TOKEN { /* Store token */ struct symbol *sym; ENTRY e = {$1, NULL}, *ep; if ((ep = hsearch(e, FIND))) { sym = ep->data; $$ = ep->key; if (sym->ty == $-1[1]) break; yyerror("duplicate declaration of %s", $1); YYERROR; } sym = e.data = malloc(yyleng + 1 + sizeof *sym); e.key = (char *)e.data + sizeof *sym; strcpy(e.key, $1); sym->next = NULL; sym->ty = $-1[1]; sym->flg = 0; if (!hsearch(e, ENTER)) { free(sym); yyerror("hash table overflow storing %s.", $1); YYERROR; } $$ = e.key; } ; retrtk : TOKEN { /* Retrieve token */ ENTRY e = {$1, NULL}, *ep; if (!(ep = hsearch(e, FIND))) { dumpstk(); yyerror("token %s found undeclared", $1); YYERROR; } assert(ep->data == (struct symbol *)(ep->key - sizeof (struct symbol))); $$ = ep->key; } ; initok : /* EMPTY */ { toktop = toklst; } ; puttok : /* EMPTY */ { if (toktop == toklst + sizeof toklst / sizeof *toklst) { yyerror("token buffer overflow."); YYERROR; } *toktop++ = $0; } ; stklst : initok stortk puttok | stklst stortk puttok ; rtklst : initok retrtk puttok | rtklst retrtk puttok ; label : TOKEN { $$ = strcpy(labbuf, $1); } ; proof : rtklst '=' TOKEN | proof TOKEN ; lnull : /* EMPTY */ { /* Null label */ $$ = NULL; } ; putstk : /* EMPTY */ { /* Put statement on stack. * * expects