Mercurial > hg > index.cgi
view src/buildkeywordtab.c @ 126:ac183a519439
Update parsing scheme with a keyword lookup by token value and other framework
Add ability to turn a token code into a keyword string. Also correct some
details related to token table generation with some additiona adjustments
for token symbols.
Also rework token symbol definitions and creation of some parsing tables as
well as the main statement parsing loop.
author | William Astle <lost@l-w.ca> |
---|---|
date | Mon, 08 Jan 2024 22:58:08 -0700 |
parents | 8770e6f977c3 |
children | 5d4801c0566d |
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\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); }