summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-09-27 23:06:47 (GMT)
committer Vincent Sanders <vince@kyllikki.org>2015-09-27 23:06:47 (GMT)
commit767e69459ca7b4c13fe93875177040ab3eec8b56 (patch)
tree349e255c7c370594edfda939dc19cf6fe7247270
parent017eb2ef4da167466c05ad83eb0714129a2e46ff (diff)
downloadnsgenbind-767e69459ca7b4c13fe93875177040ab3eec8b56.tar.gz
nsgenbind-767e69459ca7b4c13fe93875177040ab3eec8b56.tar.bz2
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.
-rw-r--r--src/nsgenbind-ast.c18
-rw-r--r--src/nsgenbind-lexer.l55
-rw-r--r--src/nsgenbind-parser.y87
3 files changed, 126 insertions, 34 deletions
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 <vince@netsurf-browser.org>
+ */
+
+ /* 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 ;
}