Mercurial > hg > index.cgi
diff src/buildkeywordtab.c @ 121:5d5472b11ccd
Initital skeleton of separation of separate parsing scheme
This is the first commit in a long series related to separating the parsing
of the input code from the execution of the code. It should allow for more
efficient, and probably simpler, execution while giving quicker feedback
when someone types in syntactically invalid code.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sun, 31 Dec 2023 17:44:39 -0700 |
parents | |
children | 5681cdada362 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/buildkeywordtab.c Sun Dec 31 17:44:39 2023 -0700 @@ -0,0 +1,122 @@ +/* +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; +}; + +int treedepth = 0; +void print_tree(FILE *fp, struct treenode *tn) +{ + 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) + { + fprintf(fp, " fcb 0x%02x,%s\n", tn1 -> ccode, tn1 -> toksym ? tn1 -> toksym : "token_eot"); + if (tn1 -> firstchild) + print_tree(fp, tn1); + } + + 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, "parse_wordtab\n"); + print_tree(outfile, treeroot); + + fclose(outfile); + exit(0); +}