Mercurial > hg > index.cgi
view src/buildkeywordtab.c @ 123:5681cdada362
Redo keyword table handling to handle keywords differing in length
Some keywords differ only due to length. That is, the shorter keyword
matches the leading characters of the longer one. Make the keyword table
builder and processor handle these cases. Also re-implement the handler
based on evolved understanding of its requirements.
author | William Astle <lost@l-w.ca> |
---|---|
date | Mon, 01 Jan 2024 15:15:45 -0700 |
parents | 5d5472b11ccd |
children | 8770e6f977c3 |
line wrap: on
line source
/* Build the keyword parse table for lwbasic */ #define _POSIX_C_SOURCE 200809L // for getline() #include <stdio.h> #include <stdlib.h> #include <string.h> struct treenode { int ccode; char *toksym; struct treenode *nextsibling; struct treenode *firstchild; }; /* lookaheaddepth will start at 255 and count down which gives an appropriate two's complement negative number. */ int treedepth = 0; void print_tree(FILE *fp, struct treenode *tn, char *lookahead, int lookaheaddepth) { struct treenode *tn1; int depth = ++treedepth; fprintf(fp, "parse_wt%d fdb parse_wt%de-parse_wt%d-2\n", depth, depth, depth); for (tn1 = tn -> firstchild; tn1; tn1 = tn1 -> nextsibling) { // if there are child nodes, insert the sub tree if (tn1 -> firstchild) { fprintf(fp, " fcb 0x%02x,token_eot\n", tn1 -> ccode); if (tn1 -> toksym) { print_tree(fp, tn1, tn1 -> toksym, 255); } else { if (lookahead) { print_tree(fp, tn1, lookahead, lookaheaddepth - 1); } else { print_tree(fp, tn1, NULL, 0); } } } // if there is also a terminal symbol here if (tn1 -> toksym) { fprintf(fp, " fcb 0x%02x,%s\n", tn1 -> ccode, tn1 -> toksym); } } // handle lookahead failure if (lookahead) { fprintf(fp, " fcb 0x%02x,%s\n", lookaheaddepth, lookahead); } fprintf(fp, "parse_wt%de\n", depth); } int main(int argc, char **argv) { FILE *infile, *outfile; struct treenode *treeroot; struct treenode *tnp, *tn, *tnprev; char *linebuf = NULL; size_t bufsize = 0; ssize_t rval; char *ptr, *ptr2; if (argc != 3) { fprintf(stderr, "Usage: %s <source> <output>\n", argv[0]); exit(1); } infile = fopen(argv[1], "rb"); if (!infile) { perror("Opening input file"); exit(1); } treeroot = calloc(1, sizeof(struct treenode)); while (1) { rval = getline(&linebuf, &bufsize, infile); if (rval == -1) { if (feof(infile)) break; perror("Reading keyword list line"); fclose(infile); if (linebuf) free(linebuf); exit(1); } ptr = linebuf + rval - 1; // lose any line terminators while (*ptr == '\r' || *ptr == '\n') *ptr-- = '\0'; ptr = strchr(linebuf, ','); if (!ptr) { fprintf(stderr, "WARNING: malformed input line\n"); continue; } *ptr++ = '\0'; // put a NUL break in tnp = treeroot; for (ptr2 = linebuf; *ptr2; ptr2++) { for (tn = tnp -> firstchild, tnprev = NULL; tn; tn = tn -> nextsibling) { if (tn -> ccode == *ptr2) break; tnprev = tn; } if (!tn) { tn = calloc(1, sizeof(struct treenode)); tn -> ccode = *ptr2; if (!*(ptr2 + 1)) tn -> toksym = strdup(ptr); if (tnprev) tnprev -> nextsibling = tn; else tnp -> firstchild = tn; fprintf(stderr, "Create entry: %c, %s\n", tn -> ccode, tn -> toksym); } tnp = tn; } } fclose(infile); outfile = fopen(argv[2], "wb"); if (!outfile) { perror("Opening output file"); exit(1); } fprintf(outfile, "; This file is automatically generated. Edit %s and rebuild to make changes.\n", argv[1]); fprintf(outfile, " *pragmapush list\n *pragma list\n"); fprintf(outfile, "parse_wordtab\n"); print_tree(outfile, treeroot, NULL, 0); fprintf(outfile, " *pragmapop list\n"); fclose(outfile); exit(0); }