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; bool isValid;
const char* parser_msg; const char* parser_msg;
int error_line;
int error_col;
}; };

View File

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

View File

@ -39,6 +39,7 @@
%option warn %option warn
%option case-insensitive %option case-insensitive
%option prefix="hsql_" %option prefix="hsql_"
%option bison-locations
/* %option nodefault */ /* %option nodefault */
@ -58,6 +59,7 @@
DEALLOCATE TOKEN(DEALLOCATE)
PARAMETERS TOKEN(PARAMETERS) PARAMETERS TOKEN(PARAMETERS)
INTERSECT TOKEN(INTERSECT) INTERSECT TOKEN(INTERSECT)
TEMPORARY TOKEN(TEMPORARY) TEMPORARY TOKEN(TEMPORARY)
@ -72,10 +74,12 @@ CASCADE TOKEN(CASCADE)
COLUMNS TOKEN(COLUMNS) COLUMNS TOKEN(COLUMNS)
CONTROL TOKEN(CONTROL) CONTROL TOKEN(CONTROL)
DEFAULT TOKEN(DEFAULT) DEFAULT TOKEN(DEFAULT)
EXECUTE TOKEN(EXECUTE)
EXPLAIN TOKEN(EXPLAIN) EXPLAIN TOKEN(EXPLAIN)
HISTORY TOKEN(HISTORY) HISTORY TOKEN(HISTORY)
INTEGER TOKEN(INTEGER) INTEGER TOKEN(INTEGER)
NATURAL TOKEN(NATURAL) NATURAL TOKEN(NATURAL)
PREPARE TOKEN(PREPARE)
PRIMARY TOKEN(PRIMARY) PRIMARY TOKEN(PRIMARY)
SCHEMAS TOKEN(SCHEMAS) SCHEMAS TOKEN(SCHEMAS)
SPATIAL TOKEN(SPATIAL) SPATIAL TOKEN(SPATIAL)
@ -130,6 +134,7 @@ FILE TOKEN(FILE)
FROM TOKEN(FROM) FROM TOKEN(FROM)
FULL TOKEN(FULL) FULL TOKEN(FULL)
HASH TOKEN(HASH) HASH TOKEN(HASH)
HINT TOKEN(HINT)
INTO TOKEN(INTO) INTO TOKEN(INTO)
JOIN TOKEN(JOIN) JOIN TOKEN(JOIN)
LEFT TOKEN(LEFT) LEFT TOKEN(LEFT)
@ -172,7 +177,7 @@ TO TOKEN(TO)
">=" TOKEN(GREATEREQ) ">=" TOKEN(GREATEREQ)
[-+*/(),.;<>=^%] { return yytext[0]; } [-+*/(),.;<>=^%:?] { return yytext[0]; }
[0-9]+"."[0-9]* | [0-9]+"."[0-9]* |
@ -204,7 +209,7 @@ TO TOKEN(TO)
return SQL_STRING; 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) { 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 DELETE
// Prepared Statements
DEALLOCATE
PREPARE
EXECUTE
/////////////////////////////// ///////////////////////////////
// other statements // other statements
RENAME RENAME
@ -138,6 +143,7 @@ ESCAPE
// With // With
WITH WITH
HINT
PARAMETERS PARAMETERS
ON ON
OFF OFF

View File

@ -76,7 +76,7 @@ int main(int argc, char *argv[]) {
if (expect_false == stmt_list->isValid) { if (expect_false == stmt_list->isValid) {
printf("\033[0;31m{ failed}\033[0m\n"); 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()); printf("\t%s\n", sql.c_str());
num_failed++; num_failed++;
} else { } 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.3, name='Felix Fürstenberg' WHERE name = 'Max Mustermann';
UPDATE students SET grade = 1.0; UPDATE students SET grade = 1.0;
# DROP # DROP
DROP TABLE students; DROP TABLE students;
# PREPARE
PREPARE prep_inst: INSERT INTO test VALUES (?, ?, ?); SELECT * FROM test;
EXECUTE prep_inst(1, 2, 3);