/* * Copyright (c) 1978 Charles H. Forsyth */ /* * W A R N I N G * * This file is NOT identical with ytab.c. Several changes which were * made directly to ytab.c have not been made to lex.y * * If you have access to yacc and rebuild ytab.c from lex.y, it is * essential that you compare the current ytab.c with the new version, * incorporating the necessary changes. */ /* * lex -- grammar/lexical analyser */ %{ #include #include "lexlex.h" char copr[] "Copyright (c) 1978 Charles H. Forsyth"; struct des { struct nfa *d_start; struct nfa *d_final; }; struct nlist { struct nlist *nl_next; struct nfa *nl_base; struct nfa *nl_end; struct nfa *nl_start; struct nfa *nl_final; char *nl_name; } *nlist; int strlen; extern struct nfa *elem(); extern struct des *newdp(); extern struct nlist *lookup(); extern char *spccl(); %} %term NAME CCLASS STRING CONCAT %left ';' %left '=' %left '/' %left '|' %left '(' NAME STRING CCLASS %left CONCAT %left '*' %% %{ struct nfa *np, *nbase; char *cp; struct des *dp; struct trans *tp; struct nlist *nl; int i, c; %} lexfile: auxiliary_section translation_section | ; auxiliary_section: auxiliaries '%' '%' | '%' '%' ; auxiliaries: auxiliaries auxiliary | auxiliary ; auxiliary: namedef '=' regexp ';' ={ dp = $3; nl = $1; np = nl->nl_base; nl->nl_start = dp->d_start; nl->nl_final = dp->d_final; nl->nl_end = nfap; printf("NFA for %s\n", nl->nl_name); nfaprint(dp->d_start, nl->nl_base); nbase = lalloc(i = nl->nl_end-nl->nl_base, sizeof(*nbase), "nfa storage"); copynfa(nl, nbase, dp); nl->nl_start = dp->d_start; nl->nl_final = dp->d_final; nl->nl_end = nbase+i; nl->nl_base = nbase; nfap = np; ignore = spccl(nl->nl_name, "ignore", dp); breakc = spccl(nl->nl_name, "break", dp); illeg = spccl(nl->nl_name, "illegal", dp); } | '%' '{' ={ copycode(); } ; namedef: NAME ={ $$ = lookup($1); $$->nl_base = nfap; if ($$->nl_start) error("%s redefined", $$->nl_name); } ; name: NAME ={ $$ = lookup($1); } ; regexp: CCLASS ={ np = elem(CCL, $1); $$ = newdp(np, np->n_succ[0] = elem(FIN)); } | STRING ={ cp = $1; if (strlen == 0) { np = elem(EPSILON); $$ = newdp(np, np->n_succ[0] = elem(FIN)); return; } $$ = np = elem(*cp++); while (--strlen > 0) np = np->n_succ[0] = elem(*cp++); $$ = newdp($$, np->n_succ[0] = elem(FIN)); } | name ={ if ((nl = $1)->nl_end == 0) { error("%s not defined", nl->nl_name); nl->nl_base = nl->nl_end = elem(FIN); nl->nl_start = nl->nl_final = nl->nl_base; } $$ = dp = lalloc(1, sizeof(*dp), "dfa input"); nbase = nfap; i = nl->nl_end-nl->nl_base; if ((nfap += i) >= &nfa[MAXNFA]) { error("Out of NFA nodes"); exit(1); } copynfa(nl, nbase, dp); } | regexp '*' ={ $$ = dp = $1; dp->d_start = newnfa(EPSILON, np = dp->d_start, 0); dp->d_final->n_char = EPSILON; dp->d_final->n_succ[0] = np; dp->d_final->n_succ[1] = np = elem(FIN); dp->d_start->n_succ[1] = np; dp->d_final = np; } | regexp '|' regexp ={ $$ = dp = $1; dp->d_start = newnfa(EPSILON, dp->d_start, $3->d_start); dp->d_final->n_char = EPSILON; dp->d_final = dp->d_final->n_succ[0] = np = elem(FIN); dp = $3; dp->d_final->n_char = EPSILON; dp->d_final->n_succ[0] = np; cfree($3); } | regexp regexp %prec CONCAT ={ $$ = $1; dp = $2; np = $$->d_final; $$->d_final = dp->d_final; np->n_char = dp->d_start->n_char; np->n_ccl = dp->d_start->n_ccl; np->n_succ[0] = dp->d_start->n_succ[0]; np->n_succ[1] = dp->d_start->n_succ[1]; cfree($2); } | '(' regexp ')' ={ $$ = $2; } ; translation_section: translations ={ ending(); trans1: printf("\nNFA for complete syntax\n"); printf("state 0\n"); for (tp = trans; tp < transp; tp++) printf("\tepsilon\t%d\n", tp->t_start-nfa); for (tp = trans; tp < transp; tp++) nfaprint(tp->t_start, nfa); dfabuild(); dfamin(); dfaprint(); dfawrite(); stats(); } | ={ goto trans1; } ; translations: translations translation | llactr translation ; llactr: ={ llactr(); } ; translation: pattern action ={ dp = $1; newtrans(dp->d_start, dp->d_final); } | '%' '{' ={ copycode(); } | '%' '%' ={ ending(); while ((c = get()) != EOF) putc(c, llout); } ; action: '{' ={ action(); } ; pattern: regexp '/' regexp ={ if (nlook >= NBPW) error("More than %d translations with lookahead",NBPW); $$ = dp = $1; np = dp->d_final; np->n_char = EPSILON; np->n_flag |= LOOK; np->n_succ[0] = $3->d_start; dp->d_final = $3->d_final; np->n_look = nlook; dp->d_final->n_look = nlook++; dp->d_final->n_flag |= FLOOK; cfree($3); } | regexp ; %% /* * Lexical analyser * (it isn't done with lex...) */ char buffer[150]; yylex() { register c; register char *cp; int lno; if (yyline == 0) yyline++; loop: c = get(); if (isupper(c)) { name(c); for (cp = yylval; c = *cp; cp++) if (isupper(c)) *cp = tolower(c); return(STRING); } else if (islower(c) || c == '_') { name(c); return(NAME); } switch (c) { case EOF: return(0); case '[': return(cclass()); case '(': case ')': case '{': case '}': case '*': case '|': case '=': case ';': case '%': return(c); case '/': if ((c = get()) != '*') { unget(c); return('/'); } lno = yyline; for (; c != EOF; c = get()) if (c == '*') if ((c = get()) == '/') goto loop; else unget(c); yyline = lno; error("End of file in comment"); case '\'': case '"': yylval = buffer; string(c); return(STRING); case '\n': case ' ': case '\t': goto loop; default: yylval = buffer; if (c == '\\') { unget(c); c = mapch(EOF); } buffer[0] = c; buffer[1] = 0; strlen = 1; return(STRING); } } char ccl[(NCHARS+1)/NBPC]; cclass() { register c, i, lc; int compl; compl = 0; for (i = 0; i < sizeof ccl; i++) ccl[i] = 0; if ((c = get()) == '^') compl++; else unget(c); lc = -1; while ((c = mapc(']')) != EOF) { if (c == '-' && lc >= 0) { if ((c = mapc(']')) == EOF) break; for (i = lc; i <= c; i++) ccl[i/NBPC] |= 1<<(i%NBPC); lc = -1; continue; } ccl[c/NBPC] |= 1<<(c%NBPC); lc = c; } if (compl) { for (i = 0; i < sizeof ccl; i++) ccl[i] ^= -1; if (aflag == 0) for (i = 0200; i < (1<= '0' && c <= '7') { i = 0; for (v = 0; c>='0' && c<='7' && i++<3; c = get()) v = v*010 + c-'0'; unget(c); return(v&0377); } switch (c) { case 'n': return('\n'); case 't': return('\t'); case 'b': return('\b'); case 'r': return('\r'); case '\n': yyline++; return(mapc(ec)); } default: return(c); } } name(c) register c; { register char *cp; for (yylval=cp=buffer; isalpha(c) || isdigit(c) || c=='_'; c=get()) *cp++ = c; *cp = 0; strlen = cp-buffer; unget(c); } /* * Miscellaneous functions * used only by lex.y */ struct nfa * elem(k, v) { struct nfa *fp; fp = newnfa(k, 0, 0); if (k == CCL) fp->n_ccl = v; return(fp); } struct des * newdp(st, fi) struct nfa *st, *fi; { register struct des *dp; dp = lalloc(1, sizeof(*dp), "dfa input"); dp->d_start = st; dp->d_final = fi; return(dp); } action() { register c; int lno, lev; newcase(transp-trans); lno = yyline; lev = 0; for (; (c = get()) != EOF && (c != '}' || lev); putc(c, llout)) if (c == '{') lev++; else if (c == '}') lev--; else if (c == '\'' || c == '"') { putc(c, llout); skipstr(c); } fprintf(llout, "\n\tbreak;\n"); if (c == EOF) { yyline = lno; error("End of file in action"); } } skipstr(ec) register ec; { register c; while ((c = get()) != ec && c != EOF) { putc(c, llout); if (c == '\\' && (c = get()) != EOF) putc(c, llout); } } copycode() { int lno; register c; setline(); lno = yyline; for (; (c = get()) != EOF; putc(c, llout)) if (c == '%') { if ((c = get()) == '}') return; unget(c); c = '%'; } yyline = lno; error("Incomplete %{ declaration"); exit(1); } struct nlist * lookup(s) register char *s; { register struct nlist *nl; register char *cp; int i; for (nl = nlist; nl; nl = nl->nl_next) if (streq(s, nl->nl_name)) return(nl); nl = lalloc(1, sizeof(*nl), "namelist"); nl->nl_start = nl->nl_end = nl->nl_base = nl->nl_end = 0; nl->nl_next = nlist; nlist = nl; i = 0; for (cp = s; *cp++;) i++; nl->nl_name = cp = lalloc(i+1, sizeof(*cp), "namelist"); while (*cp++ = *s++) ; return(nl); } copynfa(nl, nbase, dp) struct nlist *nl; struct des *dp; struct nfa *nbase; { register struct nfa *np, *ob; register j; int i, ix; ob = nl->nl_base; i = nl->nl_end-ob; copy(ob, sizeof(*np), i, nbase); for (np = nbase; i-- > 0; np++) { np->n_flag &= ~NPRT; for (j = 0; j < 2; j++) if (np->n_succ[j]) np->n_succ[j] = (np->n_succ[j]-ob)+nbase; } dp->d_start = (nl->nl_start-ob)+nbase; dp->d_final = (nl->nl_final-ob)+nbase; } char * spccl(nm, isit, dp) char *nm, *isit; register struct des *dp; { if (!streq(nm, isit)) return(0); if (dp->d_start->n_char == CCL && dp->d_start->n_succ[0] == dp->d_final) return(dp->d_start->n_ccl); error("Illegal %s class", isit); return(0); } get() { register c; if ((c = getc(stdin)) == '\n') yyline++; return(c); } unget(c) register c; { if (c == '\n') yyline--; ungetc(c, stdin); } error(s) char *s; { if (yyline) fprintf(stderr, "%d: ", yyline); fprintf(stderr, "%r", &s); if (yychar > 256) fprintf(stderr, " near `%s'", yysterm[yychar-256]); else if (yychar < 256 && yychar > 0) fprintf(stderr, " near `%c'", yychar); fprintf(stderr, "\n"); }