/* * Copyright (C) 1990-1994 Quinn C. Jensen * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. The author makes no representations * about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. * */ static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; /* * keybld - builds a finite-state parser for the given keyword list * */ #include #include "a56.h" char buf[1024]; main() { int line = 0; while(gets(buf)) { char *bp = buf; line++; while(*bp != '\t' && *bp != ' ') bp++; *bp++ = '\0'; while(*bp == '\t' || *bp == ' ') bp++; if(strcmp(buf, ".code") == 0) { printf("%s\n", bp); } else if(add_tok(buf, bp) == -1) { fprintf(stderr, "input line %d: ambiguous\n", line); } } dump_machine(); return 0; } #define MAX_CHAR 'z' #define TRANSITIONS (MAX_CHAR + 1) struct state { int number; char *seen; struct trans { char action; void *arg; } trans[TRANSITIONS]; struct state *next; } empty_state, *stop = NULL, *scur = NULL, *new_state(); int n_states = 0; /* actions */ #define NOMATCH 0 /* argument is nothing */ #define GOTO 1 /* argument is target state */ #define TERMINAL 2 /* argument is which user action to perform */ struct user_action { char *action; struct user_action *next; } *utop = NULL, *ucur = NULL; int n_user_actions = 0; add_tok(tok, actions) char *tok, *actions; { struct state *scur; struct user_action *unew = (struct user_action *)alloc(sizeof *unew); unew->action = strsave(actions); unew->next = NULL; if(ucur) ucur->next = unew; ucur = unew; if(utop == NULL) utop = unew; if(stop == NULL) new_state(NULL); if(follow(*tok, tok + 1, stop) == -1) return -1; n_user_actions++; return 0; } follow(c, tp, sp) char c; char *tp; struct state *sp; { struct trans *arcp, *arcup; if(c >= 'a' && c <= 'z') { c -= 'a' - 'A'; } arcp = sp->trans + c; if(c >= 'A' && c <= 'Z') { arcup = sp->trans + c + 'a' - 'A'; } else { arcup = arcp; } if(c == '\0') { if(arcp->action == TERMINAL) { return -1; } else { arcp->action = arcup->action = TERMINAL; arcp->arg = arcup->arg = (void *)n_user_actions; return 0; } } else { if(arcp->action == GOTO) { return follow(*tp, tp + 1, arcp->arg); } else { struct state *new = new_state(tp); arcp->action = arcup->action = GOTO; arcp->arg = arcup->arg = (void *)new; return follow(*tp, tp + 1, new); } } } struct state *new_state(tp) char *tp; { struct state *snew = (struct state *)alloc(sizeof *snew); char tmp[1024]; *snew = empty_state; snew->number = n_states++; snew->next = NULL; if(scur) scur->next = snew; scur = snew; if(stop == NULL) stop = snew; if(tp) strncpy(tmp, buf, tp - buf); else strcpy(tmp, ""); snew->seen = strsave(tmp); return snew; } dump_machine() { struct state *sp; struct user_action *up; int n, a; printf("/* state machine generated by keybld */\n"); printf("/* states=%d actions=%d */\n", n_states, n_user_actions); printf("/* %d bytes required for transition table storage */\n", sizeof(short) * TRANSITIONS * n_states); printf("short transitions[%d][%d] = {\n", n_states, TRANSITIONS); for(n = 0, sp = stop; sp; sp = sp->next, n++) { printf(" /* state %d: \"%s\" */\n", n, sp->seen); printf(" {"); for(a = 0; a < TRANSITIONS; a++) { struct trans *tp = sp->trans + a; switch(tp->action) { case GOTO: printf("%d", ((struct state *)tp->arg)->number); break; case TERMINAL: printf("%d", -(int)tp->arg - 1); break; case NOMATCH: printf("0"); break; } printf(",%s", a % 20 == 19 ? "\n\t\t" : ""); }; printf("},\n"); } printf("};\n"); printf("\ \n\ kparse(kp)\n\ char *kp;\n\ {\n\ int state = 0;\n\ \n\ for(;;) {\n\ short transition = transitions[state][*kp];\n"); printf("\ if(transition == 0) {\n\ return 0;\n\ } else if(transition > 0) {\n\ kp++;\n\ state = transition;\n\ } else {\n\ switch(-transition) {\n"); for(n = 1, up = utop; up; up = up->next, n++) { printf("\ case %d:\n\ %s;\n\ break;\n", n, up->action); } printf("\ }\n\ return transition;\n\ }\n\ }\n\ }\n"); }