X-Git-Url: https://jxself.org/git/?p=a56.git;a=blobdiff_plain;f=src%2Fkeybld.c;fp=src%2Fkeybld.c;h=f3d6ce6d6564433b3421dab5d487dbb23c01cbc7;hp=0000000000000000000000000000000000000000;hb=34923afb4a618598083726717bf2f20d310f4f6e;hpb=c6db6f4c5cb82f5e09472163bf11be0c165965ee diff --git a/src/keybld.c b/src/keybld.c new file mode 100644 index 0000000..f3d6ce6 --- /dev/null +++ b/src/keybld.c @@ -0,0 +1,231 @@ +/* + * 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); + tmp[tp - buf] = '\0'; + } 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"); + +}