From 767e69459ca7b4c13fe93875177040ab3eec8b56 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 28 Sep 2015 00:06:47 +0100 Subject: Improve the parser error reporting The parser now reports the correct file and line number for errors. Additionally the @n location structure in rules now has a filename member in addition to first_line. These members are useful for adding location information in generated source. --- src/nsgenbind-ast.c | 18 ++--------- src/nsgenbind-lexer.l | 55 +++++++++++++++++++++++++++---- src/nsgenbind-parser.y | 87 +++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 126 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/nsgenbind-ast.c b/src/nsgenbind-ast.c index 2915010..749d3e8 100644 --- a/src/nsgenbind-ast.c +++ b/src/nsgenbind-ast.c @@ -29,7 +29,7 @@ static FILE *genbind_parsetracef; extern int nsgenbind_debug; extern int nsgenbind__flex_debug; extern void nsgenbind_restart(FILE*); -extern int nsgenbind_parse(struct genbind_node **genbind_ast); +extern int nsgenbind_parse(char *filename, struct genbind_node **genbind_ast); /* terminal nodes have a value only */ struct genbind_node { @@ -515,12 +515,6 @@ FILE *genbindopen(const char *filename) } prevfilepath = strndup(filename,fulllen); } -#if 0 - if (options->depfilehandle != NULL) { - fprintf(options->depfilehandle, " \\\n\t%s", - filename); - } -#endif return genfile; } @@ -529,7 +523,7 @@ FILE *genbindopen(const char *filename) fulllen = strlen(prevfilepath) + strlen(filename) + 2; fullname = malloc(fulllen); snprintf(fullname, fulllen, "%s/%s", prevfilepath, filename); - if (options->debug) { + if (options->verbose) { printf("Attempting to open Genbind file %s\n", fullname); } genfile = fopen(fullname, "r"); @@ -537,12 +531,6 @@ FILE *genbindopen(const char *filename) if (options->verbose) { printf("Opened Genbind file %s\n", fullname); } -#if 0 - if (options->depfilehandle != NULL) { - fprintf(options->depfilehandle, " \\\n\t%s", - fullname); - } -#endif free(fullname); return genfile; } @@ -599,7 +587,7 @@ int genbind_parsefile(char *infilename, struct genbind_node **ast) nsgenbind_restart(infile); /* process binding */ - ret = nsgenbind_parse(ast); + ret = nsgenbind_parse(infilename, ast); /* close tracefile if open */ if (genbind_parsetracef != NULL) { diff --git a/src/nsgenbind-lexer.l b/src/nsgenbind-lexer.l index f32a948..af77368 100644 --- a/src/nsgenbind-lexer.l +++ b/src/nsgenbind-lexer.l @@ -15,9 +15,10 @@ #include "nsgenbind-parser.h" #include "nsgenbind-ast.h" -#define YY_USER_ACTION yylloc->first_line = yylloc->last_line; \ - yylloc->first_column = yylloc->last_column + 1; \ - yylloc->last_column += yyleng; +#define YY_USER_ACTION \ + yylloc->first_line = yylloc->last_line = yylineno; \ + yylloc->first_column = yylloc->last_column + 1; \ + yylloc->last_column += yyleng; /* Ensure compatability with bison 2.6 and later */ @@ -29,6 +30,43 @@ #define YYLTYPE NSGENBIND_LTYPE #endif +static struct YYLTYPE *locations = NULL; + +static struct YYLTYPE *push_location(struct YYLTYPE *head, + struct YYLTYPE *loc, + const char *filename) +{ + struct YYLTYPE *res; + res = calloc(1, sizeof(struct YYLTYPE)); + /* copy current location and line number */ + *res = *loc; + res->start_line = yylineno; + res->next = head; + + /* reset current location */ + loc->first_line = loc->last_line = 1; + loc->first_column = loc->last_column = 1; + loc->filename = strdup(filename); + yylineno = 1; + + return res; +} + +static struct YYLTYPE *pop_location(struct YYLTYPE *head, struct YYLTYPE *loc) +{ + struct YYLTYPE *res = NULL; + + if (head != NULL) { + res = head->next; + *loc = *head; + free(head); + + yylineno = loc->start_line; + } + return res; +} + + %} /* lexer options */ @@ -165,8 +203,10 @@ unsigned return TOK_UNSIGNED; fprintf(stderr, "Unable to open include %s\n", yytext); exit(3); } - yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE )); - + + locations = push_location(locations, yylloc, yytext); + + yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); BEGIN(INITIAL); } @@ -178,9 +218,10 @@ unsigned return TOK_UNSIGNED; yypop_buffer_state(); if ( !YY_CURRENT_BUFFER ) { - yyterminate(); + yyterminate(); } else { - BEGIN(incl); + locations = pop_location(locations, yylloc); + BEGIN(incl); } } diff --git a/src/nsgenbind-parser.y b/src/nsgenbind-parser.y index 247a047..b52d0d0 100644 --- a/src/nsgenbind-parser.y +++ b/src/nsgenbind-parser.y @@ -1,4 +1,66 @@ -%{ +/* binding parser + * + * This file is part of nsgenbind. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2012 Vincent Sanders + */ + + /* bison prior to 2.4 cannot cope with %define api.pure so we use the + * deprecated directive + */ +%pure-parser + +%locations + +%error-verbose + /* would use api.prefix but it needs to be different between bison + * 2.5 and 2.6 + */ + +%code requires { + +#define YYLTYPE YYLTYPE +typedef struct YYLTYPE { + struct YYLTYPE *next; + int start_line; + char *filename; + + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; + + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + (Current).filename = YYRHSLOC (Rhs, 1).filename; \ + (Current).start_line = YYRHSLOC (Rhs, 1).start_line; \ + } else { /* empty RHS */ \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + (Current).filename = YYRHSLOC (Rhs, 0).filename; \ + (Current).start_line = YYRHSLOC (Rhs, 0).start_line; \ + } \ + while (0) + +} + +%initial-action { + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 1; + yylloc.filename = filename; +} + +%code { /* parser for the binding generation config file * * This file is part of nsgenbind. @@ -16,7 +78,6 @@ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) -#include "nsgenbind-parser.h" #include "nsgenbind-lexer.h" #include "webidl-ast.h" #include "nsgenbind-ast.h" @@ -24,12 +85,19 @@ char *errtxt; static void nsgenbind_error(YYLTYPE *locp, + char *filename, struct genbind_node **genbind_ast, const char *str) { - locp = locp; + int errlen; + errlen = snprintf(NULL, 0, "%s:%d:%s", + locp->filename, locp->first_line, str); + errtxt = malloc(errlen + 1); + snprintf(errtxt, errlen + 1, "%s:%d:%s", + locp->filename, locp->first_line, str); + genbind_ast = genbind_ast; - errtxt = strdup(str); + filename = filename; } static struct genbind_node * @@ -91,14 +159,9 @@ add_method(struct genbind_node **genbind_ast, return res_node; } -%} +} -%locations - /* bison prior to 2.4 cannot cope with %define api.pure so we use the - * deprecated directive - */ -%pure-parser -%error-verbose +%parse-param { char *filename } %parse-param { struct genbind_node **genbind_ast } %union @@ -188,7 +251,7 @@ Statements: | error ';' { - fprintf(stderr, "%d: %s\n", yylloc.first_line, errtxt); + fprintf(stderr, "%s\n", errtxt); free(errtxt); YYABORT ; } -- cgit v1.2.3