diff --git a/grammar/Makefile b/grammar/Makefile index c2c7344..98655c7 100644 --- a/grammar/Makefile +++ b/grammar/Makefile @@ -10,11 +10,8 @@ build: build/parser.c: grammar.y | build peg $^ > $@ -build/full.c: main.c build/parser.c - cat $^ > $@ - -build/parser: build/full.c +build/parser: main.c | build/parser.c $(CC) -O3 -o $@ $^ -build/parser_debug: build/full.c +build/parser_debug: main.c $(CC) -O3 -o $@ $^ -DYY_DEBUG diff --git a/grammar/main.c b/grammar/main.c index d7f57a9..217abcd 100644 --- a/grammar/main.c +++ b/grammar/main.c @@ -1,10 +1,50 @@ #include -int yyparse(); +FILE* input = NULL; +static int lineno = 0; +static char* filename= NULL; + +#define YY_CTX_LOCAL + +#define YY_INPUT(ctx, buf, result, max) { \ + int c = getc(input); \ + if (c == '\n') ++lineno; \ + result = (EOF == c) ? 0 : (*(buf) = c, 1); \ +} + +#include "build/parser.c" + +void yyerror(yycontext* ctx, char* message) { + fprintf(stderr, "%s:%d: %s", filename, lineno, message); + + if (ctx->__pos < ctx->__limit || !feof(input)) { + // Find the offending line. + int pos = ctx->__limit; + while (ctx->__pos < pos) { + if (ctx->__buf[pos] == '\n') { + ++pos; + break; + } + + --pos; + } + + ctx->__buf[ctx->__limit] = '\0'; + fprintf(stderr, "%s", ctx->__buf + pos); + } + + fprintf(stderr, "\n"); +} int main() { - if (yyparse() == 0) { - fprintf(stderr, "Failed!\n"); + input = stdin; + lineno = 1; + filename = ""; + + yycontext ctx; + memset(&ctx, 0, sizeof(yycontext)); + if (yyparse(&ctx) == 0) { + yyerror(&ctx, "syntax error\n"); return 1; }