Mercurial > hg > index.cgi
view src/buildkeywordtab.c @ 124:8770e6f977c3
Rework parser to use parse_wordtab for symbols too
There's no reason not to use the parse_wordtab table thing to match the
symbols with their token codes. It takes less space than the combined code
and tables to do it separately.
author | William Astle <lost@l-w.ca> |
---|---|
date | Mon, 01 Jan 2024 15:57:59 -0700 |
parents | 5681cdada362 |
children | ac183a519439 |
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, '\t'); 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; } 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_wt\n"); print_tree(outfile, treeroot, NULL, 0); fprintf(outfile, " *pragmapop list\n"); fclose(outfile); exit(0); }