diff --git a/src/lex_lexer.l b/src/lex_lexer.l index 766a3e9..e47d8bc 100644 --- a/src/lex_lexer.l +++ b/src/lex_lexer.l @@ -43,13 +43,20 @@ OR TOK(OR) "<" | ">" | "<=" | -">=" TOK(COMPARISON) +">=" { + yylval->sval = strdup(yytext); + return COMPARISON; +} + [-+*/(),.;] TOK(yytext[0]) [0-9]+ | [0-9]+"."[0-9]* | -"."[0-9]* TOK(INTNUM) +"."[0-9]* { + yylval->number = atof(yytext); + return INTNUM; +} [A-Za-z][A-Za-z0-9_]* { yylval->sval = strdup(yytext); diff --git a/src/lex_parser.y b/src/lex_parser.y index ad5f392..616ac24 100644 --- a/src/lex_parser.y +++ b/src/lex_parser.y @@ -36,7 +36,7 @@ typedef void* yyscan_t; %parse-param { yyscan_t scanner } %union { - int value; + float number; char* sval; Statement* statement; @@ -49,14 +49,18 @@ typedef void* yyscan_t; } %token SELECT FROM GROUP BY WHERE NOT AND OR -%token INTNUM COMPARISON STRING -%token NAME + +%token NAME STRING COMPARISON +%token INTNUM %type statement %type select_statement -%type column_name table_name +%type table_name %type from_clause table_exp -%type expr; + +%type expr column_name scalar_exp literal +%type comparison_predicate predicate search_condition where_clause + %type table_ref_commalist %type expr_list group_clause %% @@ -80,6 +84,7 @@ select_statement: SelectStatement* s = new SelectStatement(); s->_select_list = $2; s->_from_table = $3; + s->_where_clause = $4; s->_group_by = $5; $$ = s; } @@ -92,8 +97,8 @@ from_clause: ; where_clause: - WHERE search_condition - | /* empty */ + WHERE search_condition { $$ = $2; } + | /* empty */ { $$ = NULL; } ; group_clause: @@ -126,12 +131,12 @@ predicate: ; comparison_predicate: - scalar_exp COMPARISON scalar_exp + scalar_exp COMPARISON scalar_exp { $$ = makePredicate($1, $2, $3); } ; expr: - column_name { $$ = makeColumnRef($1); } + column_name | NAME '(' expr ')' { $$ = makeFunctionRef($1, $3); } ; @@ -153,7 +158,7 @@ table_ref_commalist: column_name: - NAME + NAME { $$ = makeColumnRef($1); } ; table_name: @@ -162,8 +167,8 @@ table_name: ; literal: - STRING - | INTNUM + STRING { $$ = makeStringLiteral($1); } + | INTNUM { $$ = makeFloatLiteral($1); } ; scalar_exp: diff --git a/src/lib/Expr.cpp b/src/lib/Expr.cpp index 7321177..0dd2867 100644 --- a/src/lib/Expr.cpp +++ b/src/lib/Expr.cpp @@ -1,6 +1,6 @@ #include "Expr.h" - +#include Expr* makeColumnRef(char* name) { ALLOC_EXPR(e, eExprColumnRef); @@ -12,5 +12,26 @@ Expr* makeColumnRef(char* name) { Expr* makeFunctionRef(char* func_name, Expr* expr) { ALLOC_EXPR(e, eExprFunctionRef); e->name = func_name; + e->expr = expr; + return e; +} + +Expr* makePredicate(Expr* expr1, char* op, Expr* expr2) { + ALLOC_EXPR(e, eExprPredicate); + e->name = op; + e->expr = expr1; + e->expr2 = expr2; + return e; +} + +Expr* makeFloatLiteral(float value) { + ALLOC_EXPR(e, eExprLiteralFloat); + e->float_literal = value; + return e; +} + +Expr* makeStringLiteral(char* string) { + ALLOC_EXPR(e, eExprLiteralString); + e->name = string; return e; } \ No newline at end of file diff --git a/src/lib/Expr.h b/src/lib/Expr.h index fd08cd1..1a285ac 100644 --- a/src/lib/Expr.h +++ b/src/lib/Expr.h @@ -17,9 +17,12 @@ struct Expr { char* name; Expr* expr; + Expr* expr2; + float float_literal; }; // Zero initializes an Expr object and assigns it to a space in the heap +// http://www.ex-parrot.com/~chris/random/initialise.html #define ALLOC_EXPR(var, type) \ Expr* var; \ do { \ @@ -31,6 +34,9 @@ struct Expr { Expr* makeColumnRef(char* name); Expr* makeFunctionRef(char* func_name, Expr* expr); +Expr* makePredicate(Expr* expr1, char* op, Expr* expr2); +Expr* makeFloatLiteral(float value); +Expr* makeStringLiteral(char* string); #endif \ No newline at end of file diff --git a/src/lib/Statement.h b/src/lib/Statement.h index 8403464..3707de5 100644 --- a/src/lib/Statement.h +++ b/src/lib/Statement.h @@ -34,6 +34,7 @@ public: TableRef* _from_table; List* _select_list; List* _group_by; + Expr* _where_clause; }; diff --git a/src/sql_tests.cpp b/src/sql_tests.cpp index 5c72564..cd20a2e 100644 --- a/src/sql_tests.cpp +++ b/src/sql_tests.cpp @@ -18,20 +18,28 @@ void SelectTest1() { fflush(stdout); const char* sql = "SELECT age, name, address from table WHERE age > 12.5;"; - Statement* stmt = SQLParser::parseSQL(sql); - ASSERT(stmt != NULL); - ASSERT(stmt->_type == eSelect); + Statement* sqlStatement = SQLParser::parseSQL(sql); + ASSERT(sqlStatement != NULL); + ASSERT(sqlStatement->_type == eSelect); - SelectStatement* select = (SelectStatement*) stmt; + SelectStatement* stmt = (SelectStatement*) sqlStatement; - ASSERT(select->_select_list->size() == 3); - ASSERT_STR(select->_select_list->at(0)->name, "age"); - ASSERT_STR(select->_select_list->at(1)->name, "name"); - ASSERT_STR(select->_select_list->at(2)->name, "address"); + ASSERT(stmt->_select_list->size() == 3); + ASSERT_STR(stmt->_select_list->at(0)->name, "age"); + ASSERT_STR(stmt->_select_list->at(1)->name, "name"); + ASSERT_STR(stmt->_select_list->at(2)->name, "address"); - ASSERT(select->_from_table != NULL); - ASSERT(select->_from_table->_type == eTableName); - ASSERT_STR(select->_from_table->_table_names->at(0), "table"); + ASSERT(stmt->_from_table != NULL); + ASSERT(stmt->_from_table->_type == eTableName); + ASSERT_STR(stmt->_from_table->_table_names->at(0), "table"); + + // WHERE + ASSERT(stmt->_where_clause != NULL); + ASSERT(stmt->_where_clause->expr->type == eExprColumnRef); + ASSERT_STR(stmt->_where_clause->expr->name, "age"); + ASSERT_STR(stmt->_where_clause->name, ">"); + ASSERT(stmt->_where_clause->expr2->type == eExprLiteralFloat); + ASSERT(stmt->_where_clause->expr2->float_literal == 12.5); printf("passed!\n"); }