#include #include #include static int ok = 1; static int calls = 0; static char outbuf[1024]; static char *outp = outbuf; static char inbuf[16777216]; static char *inptr = inbuf; static char *tok; static int toklen; static void literal(char *s, int n) { while (*inptr && strchr(" \n\t", *inptr)) inptr++; if ((ok = !memcmp(inptr, s, n))) inptr += n; } static void die() { fprintf(stderr, "Parse failure at byte %d\n", (int)(inptr-inbuf)); exit(1); } static void writeline() { fwrite(outbuf, 1, outp-outbuf, stdout); putchar('\n'); memset(outbuf, ' ', 8); outp = outbuf + 8; } /* hmm, maybe inline notin and between? */ static void notin(char *s) { char c = *inptr; if ((ok = (c && c != '\n' && !strchr(s, c)))) inptr++; } static void between(char *s) { char c = *inptr; if ((ok = (c && c != '\n' && c >= s[0] && c <= s[1]))) inptr++; } void start_parsing() { parse_program(); } int parse_program() { int me = calls++; (void)me; /* suppress unused warning */ parse_preamble(); if (ok) { do { parse_comment(); if (ok) { } } while (ok); ok = 1; if (!ok) die(); parse_firstrule(); if (!ok) die(); do { parse_rule(); if (ok) { } if (!ok) { ok = 1; parse_comment(); if (ok) { } } } while (ok); ok = 1; if (!ok) die(); parse_epilogue(); if (!ok) die(); } return 0; } int parse_comment() { int me = calls++; (void)me; /* suppress unused warning */ literal("#", strlen("#")); if (ok) { do { notin(""); if (ok) { } } while (ok); ok = 1; if (!ok) die(); } return 0; } int parse_preamble() { int me = calls++; (void)me; /* suppress unused warning */ outp = outbuf; strcpy(outp, "#include "); outp += strlen("#include "); writeline(); if (ok) { outp = outbuf; strcpy(outp, "#include "); outp += strlen("#include "); writeline(); outp = outbuf; strcpy(outp, "#include "); outp += strlen("#include "); writeline(); writeline(); outp = outbuf; strcpy(outp, "static int ok = 1;"); outp += strlen("static int ok = 1;"); writeline(); outp = outbuf; strcpy(outp, "static int calls = 0;"); outp += strlen("static int calls = 0;"); writeline(); outp = outbuf; strcpy(outp, "static char outbuf[1024];"); outp += strlen("static char outbuf[1024];"); writeline(); outp = outbuf; strcpy(outp, "static char *outp = outbuf;"); outp += strlen("static char *outp = outbuf;"); writeline(); outp = outbuf; strcpy(outp, "static char inbuf[16777216];"); outp += strlen("static char inbuf[16777216];"); writeline(); outp = outbuf; strcpy(outp, "static char *inptr = inbuf;"); outp += strlen("static char *inptr = inbuf;"); writeline(); outp = outbuf; strcpy(outp, "static char *tok;"); outp += strlen("static char *tok;"); writeline(); outp = outbuf; strcpy(outp, "static int toklen;"); outp += strlen("static int toklen;"); writeline(); writeline(); outp = outbuf; strcpy(outp, "static void literal(char *s, int n)"); outp += strlen("static void literal(char *s, int n)"); writeline(); outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); parse_fnord(); if (!ok) die(); strcpy(outp, "if ((ok = !memcmp(inptr, s, n))) inptr += n;"); outp += strlen("if ((ok = !memcmp(inptr, s, n))) inptr += n;"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); outp = outbuf; strcpy(outp, "static void die()"); outp += strlen("static void die()"); writeline(); outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); strcpy(outp, "fprintf(stderr, "); outp += strlen("fprintf(stderr, "); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, "Parse failure at byte %d"); outp += strlen("Parse failure at byte %d"); strcpy(outp, "\\"); outp += strlen("\\"); strcpy(outp, "n"); outp += strlen("n"); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ", (int)(inptr-inbuf));"); outp += strlen(", (int)(inptr-inbuf));"); writeline(); strcpy(outp, "exit(1);"); outp += strlen("exit(1);"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); outp = outbuf; strcpy(outp, "static void writeline()"); outp += strlen("static void writeline()"); writeline(); outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); strcpy(outp, "fwrite(outbuf, 1, outp-outbuf, stdout);"); outp += strlen("fwrite(outbuf, 1, outp-outbuf, stdout);"); writeline(); strcpy(outp, "putchar('"); outp += strlen("putchar('"); strcpy(outp, "\\"); outp += strlen("\\"); strcpy(outp, "n');"); outp += strlen("n');"); writeline(); strcpy(outp, "memset(outbuf, ' ', 8);"); outp += strlen("memset(outbuf, ' ', 8);"); writeline(); strcpy(outp, "outp = outbuf + 8;"); outp += strlen("outp = outbuf + 8;"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); strcpy(outp, "/* hmm, maybe inline notin and between? */"); outp += strlen("/* hmm, maybe inline notin and between? */"); writeline(); outp = outbuf; strcpy(outp, "static void notin(char *s)"); outp += strlen("static void notin(char *s)"); writeline(); outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); strcpy(outp, "char c = *inptr;"); outp += strlen("char c = *inptr;"); writeline(); strcpy(outp, "if ((ok = (c && c != '"); outp += strlen("if ((ok = (c && c != '"); strcpy(outp, "\\"); outp += strlen("\\"); strcpy(outp, "n' && !strchr(s, c)))) inptr++;"); outp += strlen("n' && !strchr(s, c)))) inptr++;"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); outp = outbuf; strcpy(outp, "static void between(char *s)"); outp += strlen("static void between(char *s)"); writeline(); outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); strcpy(outp, "char c = *inptr;"); outp += strlen("char c = *inptr;"); writeline(); strcpy(outp, "if ((ok = (c && c != '"); outp += strlen("if ((ok = (c && c != '"); strcpy(outp, "\\"); outp += strlen("\\"); strcpy(outp, "n' && c >= s[0] && c <= s[1]))) inptr++;"); outp += strlen("n' && c >= s[0] && c <= s[1]))) inptr++;"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); } return 0; } int parse_fnord() { int me = calls++; (void)me; /* suppress unused warning */ strcpy(outp, "while (*inptr && strchr("); outp += strlen("while (*inptr && strchr("); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, " "); outp += strlen(" "); strcpy(outp, "\\"); outp += strlen("\\"); strcpy(outp, "n"); outp += strlen("n"); strcpy(outp, "\\"); outp += strlen("\\"); strcpy(outp, "t"); outp += strlen("t"); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ", *inptr)) inptr++;"); outp += strlen(", *inptr)) inptr++;"); writeline(); if (ok) { } return 0; } int parse_rule() { int me = calls++; (void)me; /* suppress unused warning */ literal("-", strlen("-")); if (ok) { parse_name(); if (!ok) die(); outp = outbuf; strcpy(outp, "int parse_"); outp += strlen("int parse_"); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "()"); outp += strlen("()"); writeline(); outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); parse_function_prologue(); if (!ok) die(); literal(":", strlen(":")); if (!ok) die(); parse_terms(); if (!ok) die(); strcpy(outp, "return 0;"); outp += strlen("return 0;"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); } return 0; } int parse_function_prologue() { int me = calls++; (void)me; /* suppress unused warning */ strcpy(outp, "int me = calls++;"); outp += strlen("int me = calls++;"); writeline(); if (ok) { strcpy(outp, "(void)me; /* suppress unused warning */"); outp += strlen("(void)me; /* suppress unused warning */"); writeline(); } return 0; } int parse_firstrule() { int me = calls++; (void)me; /* suppress unused warning */ literal("-", strlen("-")); if (ok) { parse_name(); if (!ok) die(); outp = outbuf; strcpy(outp, "void start_parsing()"); outp += strlen("void start_parsing()"); writeline(); outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); strcpy(outp, "parse_"); outp += strlen("parse_"); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "();"); outp += strlen("();"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); outp = outbuf; strcpy(outp, "int parse_"); outp += strlen("int parse_"); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "()"); outp += strlen("()"); writeline(); outp = outbuf; strcpy(outp, "\{"); outp += strlen("\{"); writeline(); parse_function_prologue(); if (!ok) die(); literal(":", strlen(":")); if (!ok) die(); parse_terms(); if (!ok) die(); strcpy(outp, "return 0;"); outp += strlen("return 0;"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); } return 0; } int parse_epilogue() { int me = calls++; (void)me; /* suppress unused warning */ outp = outbuf; strcpy(outp, "int main(int argc, char **argv)"); outp += strlen("int main(int argc, char **argv)"); writeline(); if (ok) { outp = outbuf; strcpy(outp, "{"); outp += strlen("{"); writeline(); strcpy(outp, "size_t n;"); outp += strlen("size_t n;"); writeline(); strcpy(outp, "size_t max = sizeof(inbuf) - 100; /* allow for literals */"); outp += strlen("size_t max = sizeof(inbuf) - 100; /* allow for literals */"); writeline(); strcpy(outp, "FILE *input = fopen(argv[1], "); outp += strlen("FILE *input = fopen(argv[1], "); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, "r"); outp += strlen("r"); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ");"); outp += strlen(");"); writeline(); strcpy(outp, "if (!input) {perror(argv[1]); return 1;"); outp += strlen("if (!input) {perror(argv[1]); return 1;"); strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); strcpy(outp, "n = fread(inbuf, 1, max, input);"); outp += strlen("n = fread(inbuf, 1, max, input);"); writeline(); strcpy(outp, "if (n == max) {"); outp += strlen("if (n == max) {"); writeline(); strcpy(outp, " fprintf(stderr, "); outp += strlen(" fprintf(stderr, "); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, "Input file %s too large"); outp += strlen("Input file %s too large"); strcpy(outp, "\\"); outp += strlen("\\"); strcpy(outp, "n"); outp += strlen("n"); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ", argv[1]);"); outp += strlen(", argv[1]);"); writeline(); strcpy(outp, " return 1;"); outp += strlen(" return 1;"); writeline(); strcpy(outp, "\}"); outp += strlen("\}"); writeline(); strcpy(outp, "inbuf[n] = 0;"); outp += strlen("inbuf[n] = 0;"); writeline(); strcpy(outp, "if (ferror(input)) {"); outp += strlen("if (ferror(input)) {"); writeline(); strcpy(outp, " perror("); outp += strlen(" perror("); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, "reading input file; maybe:"); outp += strlen("reading input file; maybe:"); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ");"); outp += strlen(");"); writeline(); strcpy(outp, " return 1;"); outp += strlen(" return 1;"); writeline(); strcpy(outp, "\}"); outp += strlen("\}"); writeline(); writeline(); strcpy(outp, "start_parsing();"); outp += strlen("start_parsing();"); writeline(); strcpy(outp, "return 0;"); outp += strlen("return 0;"); writeline(); outp = outbuf; strcpy(outp, "\}"); outp += strlen("\}"); writeline(); } return 0; } int parse_terms() { int me = calls++; (void)me; /* suppress unused warning */ parse_term(); if (ok) { do { literal(",", strlen(",")); if (ok) { writeline(); strcpy(outp, "if (!ok) {"); outp += strlen("if (!ok) {"); writeline(); strcpy(outp, "ok = 1;"); outp += strlen("ok = 1;"); writeline(); parse_term(); if (!ok) die(); strcpy(outp, "\}"); outp += strlen("\}"); writeline(); } } while (ok); ok = 1; if (!ok) die(); } return 0; } int parse_term() { int me = calls++; (void)me; /* suppress unused warning */ parse_factor(); if (ok) { } if (!ok) { ok = 1; parse_output(); if (ok) { } } if (ok) { strcpy(outp, "if (ok) {"); outp += strlen("if (ok) {"); writeline(); do { parse_factor(); if (ok) { strcpy(outp, "if (!ok) die();"); outp += strlen("if (!ok) die();"); writeline(); } if (!ok) { ok = 1; parse_output(); if (ok) { } } } while (ok); ok = 1; if (!ok) die(); strcpy(outp, "\}"); outp += strlen("\}"); writeline(); } return 0; } int parse_factor() { int me = calls++; (void)me; /* suppress unused warning */ parse_string(); if (ok) { strcpy(outp, "literal("); outp += strlen("literal("); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, ", strlen("); outp += strlen(", strlen("); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "));"); outp += strlen("));"); writeline(); } if (!ok) { ok = 1; literal("(", strlen("(")); if (ok) { parse_terms(); if (!ok) die(); literal(")", strlen(")")); if (!ok) die(); } } if (!ok) { ok = 1; literal("[", strlen("[")); if (ok) { strcpy(outp, "do {"); outp += strlen("do {"); writeline(); parse_terms(); if (!ok) die(); strcpy(outp, "\}"); outp += strlen("\}"); strcpy(outp, " while (ok);"); outp += strlen(" while (ok);"); writeline(); strcpy(outp, "ok = 1;"); outp += strlen("ok = 1;"); writeline(); literal("]", strlen("]")); if (!ok) die(); } } if (!ok) { ok = 1; parse_name(); if (ok) { strcpy(outp, "parse_"); outp += strlen("parse_"); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "();"); outp += strlen("();"); writeline(); } } if (!ok) { ok = 1; literal("<<", strlen("<<")); if (ok) { strcpy(outp, "tok = inptr;"); outp += strlen("tok = inptr;"); writeline(); parse_terms(); if (!ok) die(); literal(">>", strlen(">>")); if (!ok) die(); strcpy(outp, "toklen = inptr - tok;"); outp += strlen("toklen = inptr - tok;"); writeline(); } } if (!ok) { ok = 1; literal(":fnord", strlen(":fnord")); if (ok) { parse_fnord(); if (!ok) die(); parse_factor(); if (!ok) die(); } } if (!ok) { ok = 1; literal(":notin", strlen(":notin")); if (ok) { parse_string(); if (!ok) die(); strcpy(outp, "notin("); outp += strlen("notin("); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, ");"); outp += strlen(");"); writeline(); } } if (!ok) { ok = 1; literal(":between", strlen(":between")); if (ok) { parse_string(); if (!ok) die(); strcpy(outp, "between("); outp += strlen("between("); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, ");"); outp += strlen(");"); writeline(); } } return 0; } int parse_output() { int me = calls++; (void)me; /* suppress unused warning */ parse_quasiquote(); if (ok) { } if (!ok) { ok = 1; literal("@", strlen("@")); if (ok) { strcpy(outp, "outp = outbuf;"); outp += strlen("outp = outbuf;"); writeline(); parse_var(); if (ok) { } if (!ok) { ok = 1; parse_quasiquote(); if (ok) { } } if (!ok) die(); } } if (ok) { strcpy(outp, "writeline();"); outp += strlen("writeline();"); writeline(); } return 0; } int parse_quasiquote() { int me = calls++; (void)me; /* suppress unused warning */ literal("{", strlen("{")); if (ok) { do { tok = inptr; parse_ch(); if (ok) { do { parse_ch(); if (ok) { } } while (ok); ok = 1; if (!ok) die(); } if (!ok) { ok = 1; between("\\\\"); if (ok) { notin(""); if (!ok) die(); } } toklen = inptr - tok; if (ok) { strcpy(outp, "strcpy(outp, "); outp += strlen("strcpy(outp, "); strcpy(outp, "\""); outp += strlen("\""); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ");"); outp += strlen(");"); writeline(); strcpy(outp, "outp += strlen("); outp += strlen("outp += strlen("); strcpy(outp, "\""); outp += strlen("\""); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ");"); outp += strlen(");"); writeline(); } if (!ok) { ok = 1; literal("$", strlen("$")); if (ok) { parse_var(); if (!ok) die(); } } } while (ok); ok = 1; if (!ok) die(); literal("}", strlen("}")); if (!ok) die(); } return 0; } int parse_ch() { int me = calls++; (void)me; /* suppress unused warning */ notin("$}\\"); if (ok) { } return 0; } int parse_var() { int me = calls++; (void)me; /* suppress unused warning */ literal("it", strlen("it")); if (ok) { strcpy(outp, "memcpy(outp, tok, toklen);"); outp += strlen("memcpy(outp, tok, toklen);"); writeline(); strcpy(outp, "outp += toklen;"); outp += strlen("outp += toklen;"); writeline(); } if (!ok) { ok = 1; parse_name(); if (ok) { strcpy(outp, "outp += sprintf(outp, "); outp += strlen("outp += sprintf(outp, "); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, "%s%d"); outp += strlen("%s%d"); strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ", "); outp += strlen(", "); strcpy(outp, "\""); outp += strlen("\""); memcpy(outp, tok, toklen); outp += toklen; strcpy(outp, "\""); outp += strlen("\""); strcpy(outp, ", me);"); outp += strlen(", me);"); writeline(); } } return 0; } int parse_string() { int me = calls++; (void)me; /* suppress unused warning */ while (*inptr && strchr(" \n\t", *inptr)) inptr++; tok = inptr; parse_quotes(); if (ok) { do { notin("\"\\"); if (ok) { } if (!ok) { ok = 1; between("\\\\"); if (ok) { notin(""); if (!ok) die(); } } } while (ok); ok = 1; if (!ok) die(); parse_quotes(); if (!ok) die(); } toklen = inptr - tok; if (ok) { } return 0; } int parse_quotes() { int me = calls++; (void)me; /* suppress unused warning */ literal("\"", strlen("\"")); if (ok) { } return 0; } int parse_name() { int me = calls++; (void)me; /* suppress unused warning */ while (*inptr && strchr(" \n\t", *inptr)) inptr++; tok = inptr; parse_letter(); if (ok) { do { parse_letter(); if (ok) { } if (!ok) { ok = 1; between("09"); if (ok) { } } } while (ok); ok = 1; if (!ok) die(); } toklen = inptr - tok; if (ok) { } return 0; } int parse_letter() { int me = calls++; (void)me; /* suppress unused warning */ between("az"); if (ok) { } if (!ok) { ok = 1; between("AZ"); if (ok) { } } if (!ok) { ok = 1; between("__"); if (ok) { } } return 0; } int main(int argc, char **argv) { size_t n; size_t max = sizeof(inbuf) - 100; /* allow for literals */ FILE *input = fopen(argv[1], "r"); if (!input) {perror(argv[1]); return 1;} n = fread(inbuf, 1, max, input); if (n == max) { fprintf(stderr, "Input file %s too large\n", argv[1]); return 1; } inbuf[n] = 0; if (ferror(input)) { perror("reading input file; maybe:"); return 1; } start_parsing(); return 0; }