added location tracking to parser

This commit is contained in:
Pedro 2014-12-15 14:43:42 +01:00
parent bda8db57e4
commit 98c84abcba
6 changed files with 71 additions and 21 deletions

View File

@ -57,6 +57,8 @@ public:
bool isValid;
const char* parser_msg;
int error_line;
int error_col;
};

View File

@ -19,13 +19,15 @@
using namespace hsql;
int yyerror(SQLStatementList** result, yyscan_t scanner, const char *msg) {
int yyerror(YYLTYPE* llocp, SQLStatementList** result, yyscan_t scanner, const char *msg) {
SQLStatementList* list = new SQLStatementList();
list->isValid = false;
list->parser_msg = strdup(msg);
list->error_line = llocp->first_line;
list->error_col = llocp->first_column;
*result = list;
return 0;
}
@ -47,6 +49,8 @@ int yyerror(SQLStatementList** result, yyscan_t scanner, const char *msg) {
%define api.token.prefix {SQL_}
%define parse.error verbose
%locations
// Specify code that is included in the generated .h and .c files
%code requires {
@ -57,6 +61,21 @@ typedef void* yyscan_t;
#endif
#define YYSTYPE HSQL_STYPE
#define YYLTYPE HSQL_LTYPE
#define YY_USER_ACTION \
yylloc->first_line = yylloc->last_line; \
yylloc->first_column = yylloc->last_column; \
for(int i = 0; yytext[i] != '\0'; i++) { \
if(yytext[i] == '\n') { \
yylloc->last_line++; \
yylloc->last_column = 0; \
} \
else { \
yylloc->last_column++; \
} \
}
}
@ -114,26 +133,27 @@ typedef void* yyscan_t;
%token <uval> NOTEQUALS LESSEQ GREATEREQ
/* SQL Keywords */
%token PARAMETERS INTERSECT TEMPORARY TIMESTAMP DISTINCT
%token NVARCHAR RESTRICT TRUNCATE ANALYZE BETWEEN CASCADE
%token COLUMNS CONTROL DEFAULT EXPLAIN HISTORY INTEGER
%token NATURAL PRIMARY SCHEMAS SPATIAL VIRTUAL BEFORE COLUMN
%token CREATE DELETE DIRECT DOUBLE ESCAPE EXCEPT EXISTS
%token GLOBAL HAVING IMPORT INSERT ISNULL OFFSET RENAME
%token SCHEMA SELECT SORTED TABLES UNIQUE UNLOAD UPDATE
%token VALUES AFTER ALTER CROSS DELTA GROUP INDEX INNER
%token LIMIT LOCAL MERGE MINUS ORDER OUTER RIGHT TABLE UNION
%token USING WHERE CALL DATE DESC DROP FILE FROM FULL HASH
%token INTO JOIN LEFT LIKE LOAD NULL PART PLAN SHOW TEXT
%token TIME VIEW WITH ADD ALL AND ASC CSV FOR INT KEY NOT OFF
%token SET TBL TOP AS BY IF IN IS OF ON OR TO
%token DEALLOCATE PARAMETERS INTERSECT TEMPORARY TIMESTAMP
%token DISTINCT NVARCHAR RESTRICT TRUNCATE ANALYZE BETWEEN
%token CASCADE COLUMNS CONTROL DEFAULT EXECUTE EXPLAIN
%token HISTORY INTEGER NATURAL PREPARE PRIMARY SCHEMAS
%token SPATIAL VIRTUAL BEFORE COLUMN CREATE DELETE DIRECT
%token DOUBLE ESCAPE EXCEPT EXISTS GLOBAL HAVING IMPORT
%token INSERT ISNULL OFFSET RENAME SCHEMA SELECT SORTED
%token TABLES UNIQUE UNLOAD UPDATE VALUES AFTER ALTER CROSS
%token DELTA GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER
%token OUTER RIGHT TABLE UNION USING WHERE CALL DATE DESC
%token DROP FILE FROM FULL HASH HINT INTO JOIN LEFT LIKE
%token LOAD NULL PART PLAN SHOW TEXT TIME VIEW WITH ADD ALL
%token AND ASC CSV FOR INT KEY NOT OFF SET TBL TOP AS BY IF
%token IN IS OF ON OR TO
/*********************************
** Non-Terminal types (http://www.gnu.org/software/bison/manual/html_node/Type-Decl.html)
*********************************/
%type <stmt_list> statement_list
%type <statement> statement
%type <statement> statement preparable_statement prepare_statement
%type <select_stmt> select_statement select_with_paren select_no_paren select_clause
%type <import_stmt> import_statement
%type <create_stmt> create_statement
@ -200,6 +220,12 @@ statement_list:
;
statement:
preparable_statement
| prepare_statement
;
preparable_statement:
select_statement { $$ = $1; }
| import_statement { $$ = $1; }
| create_statement { $$ = $1; }
@ -211,6 +237,14 @@ statement:
;
/******************************
* Prepared Statement
******************************/
prepare_statement:
PREPARE IDENTIFIER ':' preparable_statement { $$ = NULL; }
;
/******************************
* Import Statement

View File

@ -39,6 +39,7 @@
%option warn
%option case-insensitive
%option prefix="hsql_"
%option bison-locations
/* %option nodefault */
@ -58,6 +59,7 @@
DEALLOCATE TOKEN(DEALLOCATE)
PARAMETERS TOKEN(PARAMETERS)
INTERSECT TOKEN(INTERSECT)
TEMPORARY TOKEN(TEMPORARY)
@ -72,10 +74,12 @@ CASCADE TOKEN(CASCADE)
COLUMNS TOKEN(COLUMNS)
CONTROL TOKEN(CONTROL)
DEFAULT TOKEN(DEFAULT)
EXECUTE TOKEN(EXECUTE)
EXPLAIN TOKEN(EXPLAIN)
HISTORY TOKEN(HISTORY)
INTEGER TOKEN(INTEGER)
NATURAL TOKEN(NATURAL)
PREPARE TOKEN(PREPARE)
PRIMARY TOKEN(PRIMARY)
SCHEMAS TOKEN(SCHEMAS)
SPATIAL TOKEN(SPATIAL)
@ -130,6 +134,7 @@ FILE TOKEN(FILE)
FROM TOKEN(FROM)
FULL TOKEN(FULL)
HASH TOKEN(HASH)
HINT TOKEN(HINT)
INTO TOKEN(INTO)
JOIN TOKEN(JOIN)
LEFT TOKEN(LEFT)
@ -172,7 +177,7 @@ TO TOKEN(TO)
">=" TOKEN(GREATEREQ)
[-+*/(),.;<>=^%] { return yytext[0]; }
[-+*/(),.;<>=^%:?] { return yytext[0]; }
[0-9]+"."[0-9]* |
@ -204,7 +209,7 @@ TO TOKEN(TO)
return SQL_STRING;
}
. { fprintf(stderr, "[SQL-Lexer-Error] Unknown Character: %c\n", yytext[0]); return 0; }
%%
@ -213,5 +218,5 @@ TO TOKEN(TO)
***************************/
int yyerror(const char *msg) {
fprintf(stderr, "[Error] SQL Lexer: %s\n",msg); return 0;
fprintf(stderr, "[SQL-Lexer-Error] %s\n",msg); return 0;
}

View File

@ -101,6 +101,11 @@ UNLOAD
DELETE
// Prepared Statements
DEALLOCATE
PREPARE
EXECUTE
///////////////////////////////
// other statements
RENAME
@ -138,6 +143,7 @@ ESCAPE
// With
WITH
HINT
PARAMETERS
ON
OFF

View File

@ -76,7 +76,7 @@ int main(int argc, char *argv[]) {
if (expect_false == stmt_list->isValid) {
printf("\033[0;31m{ failed}\033[0m\n");
printf("\t\033[0;31m%s\n\033[0m", stmt_list->parser_msg);
printf("\t\033[0;31m%s (L%d:%d)\n\033[0m", stmt_list->parser_msg, stmt_list->error_line, stmt_list->error_col);
printf("\t%s\n", sql.c_str());
num_failed++;
} else {

View File

@ -29,4 +29,7 @@ UPDATE students SET grade = 1.3 WHERE name = 'Max Mustermann';
UPDATE students SET grade = 1.3, name='Felix Fürstenberg' WHERE name = 'Max Mustermann';
UPDATE students SET grade = 1.0;
# DROP
DROP TABLE students;
DROP TABLE students;
# PREPARE
PREPARE prep_inst: INSERT INTO test VALUES (?, ?, ?); SELECT * FROM test;
EXECUTE prep_inst(1, 2, 3);