2 * Copyright (C) 1990-1994 Quinn C. Jensen
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without fee,
6 * provided that the above copyright notice appear in all copies and
7 * that both that copyright notice and this permission notice appear
8 * in supporting documentation. The author makes no representations
9 * about the suitability of this software for any purpose. It is
10 * provided "as is" without express or implied warranty.
13 static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
16 * keybld - builds a finite-state parser for the given keyword list
32 while(*bp != '\t' && *bp != ' ') bp++;
34 while(*bp == '\t' || *bp == ' ') bp++;
35 if(strcmp(buf, ".code") == 0) {
37 } else if(add_tok(buf, bp) == -1) {
38 fprintf(stderr, "input line %d: ambiguous\n", line);
48 #define TRANSITIONS (MAX_CHAR + 1)
58 } empty_state, *stop = NULL, *scur = NULL, *new_state();
62 #define NOMATCH 0 /* argument is nothing */
63 #define GOTO 1 /* argument is target state */
64 #define TERMINAL 2 /* argument is which user action to perform */
68 struct user_action *next;
69 } *utop = NULL, *ucur = NULL;
70 int n_user_actions = 0;
76 struct user_action *unew = (struct user_action *)alloc(sizeof *unew);
77 unew->action = strsave(actions);
88 if(follow(*tok, tok + 1, stop) == -1)
100 struct trans *arcp, *arcup;
102 if(c >= 'a' && c <= 'z') {
105 arcp = sp->trans + c;
107 if(c >= 'A' && c <= 'Z') {
108 arcup = sp->trans + c + 'a' - 'A';
114 if(arcp->action == TERMINAL) {
117 arcp->action = arcup->action = TERMINAL;
118 arcp->arg = arcup->arg = (void *)n_user_actions;
122 if(arcp->action == GOTO) {
123 return follow(*tp, tp + 1, arcp->arg);
125 struct state *new = new_state(tp);
126 arcp->action = arcup->action = GOTO;
127 arcp->arg = arcup->arg = (void *)new;
128 return follow(*tp, tp + 1, new);
133 struct state *new_state(tp)
136 struct state *snew = (struct state *)alloc(sizeof *snew);
141 snew->number = n_states++;
153 strncpy(tmp, buf, tp - buf);
154 tmp[tp - buf] = '\0';
156 strcpy(tmp, "<nothing>");
158 snew->seen = strsave(tmp);
166 struct user_action *up;
169 printf("/* state machine generated by keybld */\n");
170 printf("/* states=%d actions=%d */\n", n_states, n_user_actions);
171 printf("/* %d bytes required for transition table storage */\n",
172 sizeof(short) * TRANSITIONS * n_states);
174 printf("short transitions[%d][%d] = {\n", n_states, TRANSITIONS);
175 for(n = 0, sp = stop; sp; sp = sp->next, n++) {
176 printf(" /* state %d: \"%s\" */\n", n, sp->seen);
178 for(a = 0; a < TRANSITIONS; a++) {
179 struct trans *tp = sp->trans + a;
182 printf("%d", ((struct state *)tp->arg)->number);
185 printf("%d", -(int)tp->arg - 1);
191 printf(",%s", a % 20 == 19 ? "\n\t\t" : "");
206 short transition = transitions[state][*kp];\n");
209 if(transition == 0) {\n\
211 } else if(transition > 0) {\n\
213 state = transition;\n\
215 switch(-transition) {\n");
217 for(n = 1, up = utop; up; up = up->next, n++) {
221 break;\n", n, up->action);
226 return transition;\n\