commit of current state

This commit is contained in:
Pedro 2014-10-08 16:30:22 -07:00
parent b5e65a7821
commit 6ea2c0e318
15 changed files with 545 additions and 0 deletions

5
src/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
lex_lexer.c
lex_lexer.h
lex_parser.c
lex_parser.h
*.o

33
src/Makefile Normal file
View File

@ -0,0 +1,33 @@
# Makefile
LIB_FILES = lex_lexer.c lex_parser.c lib/Statement.cpp lib/SQLParser.cpp
TESTS_MAIN = sql_tests.cpp
TESTS_BIN = bin/tests
PARSER_MAIN = sql_parser.cpp
PARSER_BIN = bin/parser
CC = g++
CFLAGS = -g -O3 -Ilib/ -I./
tests: $(LIB_FILES) $(TESTS_MAIN)
$(CC) $(CFLAGS) $(LIB_FILES) $(TESTS_MAIN) -o $(TESTS_BIN)
parser: $(LIB_FILES) $(PARSER_MAIN)
$(CC) $(CFLAGS) $(LIB_FILES) $(PARSER_MAIN) -o $(PARSER_BIN)
lex_lexer.c: lex_lexer.l
flex lex_lexer.l
lex_parser.c: lex_parser.y lex_lexer.c
bison lex_parser.y
clean:
rm -f *.o *~ lex_lexer.c lex_lexer.h lex_parser.c lex_parser.h $(PARSER_BIN) $(TESTS_BIN)

2
src/bin/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

5
src/build_and_run.sh Normal file
View File

@ -0,0 +1,5 @@
make clean
make tests
./bin/tests

51
src/lex_lexer.l Normal file
View File

@ -0,0 +1,51 @@
%{
/*
* lexer.l file
* To generate the lexical analyzer run: "flex lexer.l"
*/
#include "Statement.h"
#include "List.h"
#include "lex_parser.h"
#include <stdio.h>
#include <iostream>
using namespace std;
#define TOK(name) { return name; }
%}
%option outfile="lex_lexer.c" header-file="lex_lexer.h"
%option warn nodefault
%option reentrant noyywrap never-interactive nounistd
%option bison-bridge
%option case-insensitive
%%
[ \t\n]+ ;
SELECT TOK(SELECT)
FROM TOK(FROM)
GROUP TOK(GROUP)
BY TOK(BY)
[-+*/(),.;] TOK(yytext[0])
[0-9]+ |
[0-9]+"."[0-9]* |
"."[0-9]* TOK(INTNUM)
[A-Za-z][A-Za-z0-9_]* {
yylval->sval = strdup(yytext);
return STRING;
}
%%
int yyerror(const char *msg) {
fprintf(stderr,"Error:%s\n",msg); return 0;
}

120
src/lex_parser.y Normal file
View File

@ -0,0 +1,120 @@
%{
/*
* parser.y file
* To generate the parser run: "bison parser.y"
*/
#include "Statement.h"
#include "List.h"
#include "lex_parser.h"
#include "lex_lexer.h"
#include <iostream>
int yyerror(Statement **expression, yyscan_t scanner, const char *msg) {
// Add error handling routine as needed
}
%}
%code requires {
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
}
%output "lex_parser.c"
%defines "lex_parser.h"
%define api.pure
%lex-param { yyscan_t scanner }
%parse-param { Statement **statement }
%parse-param { yyscan_t scanner }
%union {
int value;
char* sval;
Statement* statement;
SelectStatement* select_statement;
TableRef* table;
Expression* expr;
List<char*>* slist;
List<Expression*>* explist;
}
%token SELECT FROM GROUP BY INTNUM
%token <sval> STRING
%type <statement> statement
%type <select_statement> select_statement
%type <table> from_clause
%type <slist> string_list
%type <explist> expr_list group_clause
%type <expr> expr;
%%
input:
statement opt_semicolon { *statement = $1; };
opt_semicolon:
';' | ;
statement:
select_statement { $$ = $1; }
| { $$ = NULL; };
select_statement:
SELECT expr_list from_clause group_clause
{
SelectStatement* s = new SelectStatement();
s->_select_list = $2;
s->_from_table = $3;
s->_group_by = $4;
$$ = s;
};
expr_list:
expr { $$ = new List<Expression*>($1); }
| expr_list ',' expr { $1->push_back($3); $$ = $1; };
expr:
STRING { $$ = new Expression($1); }
| STRING '(' STRING ')' { $$ = new Expression($3, $1); };
from_clause:
FROM string_list
{
TableRef* t = new TableRef(eTableName);
t->_table_names = $2;
$$ = t;
}
| FROM '(' select_statement ')'
{
TableRef* t = new TableRef(eTableSelect);
t->_stmt = $3;
$$ = t;
};
group_clause:
GROUP BY expr_list { $$ = $3; }
| { $$ = NULL; };
string_list:
STRING { $$ = new List<char*>($1); }
| string_list ',' STRING { $1->push_back($3); $$ = $1; }
%%

0
src/lib/Expression.cpp Normal file
View File

16
src/lib/Expression.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __EXPRESSION_H__
#define __EXPRESSION_H__
class Expression {
public:
Expression(char* name) : name(name) {};
Expression(char* name, char* func_name) : name(name), func_name(func_name) {};
char* name;
char* func_name;
};
#endif

26
src/lib/List.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef __LIST_H__
#define __LIST_H__
#include <vector>
#include <cstdlib>
template <typename _T>
class List {
public:
std::vector<_T> _vector;
List() {}
List(_T first_value) {
_vector.push_back(first_value);
}
inline size_t size() { return _vector.size(); };
inline _T at(int i) { return _vector[i]; }
inline _T &operator[](int i) { return _vector[i]; }
inline void push_back(_T value) { _vector.push_back(value); }
};
#endif

37
src/lib/SQLParser.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "SQLParser.h"
#include "lex_parser.h"
#include "lex_lexer.h"
#include <stdio.h>
int yyparse(Statement **expression, yyscan_t scanner);
SQLParser::SQLParser() {
fprintf(stderr, "SQLParser only has static methods atm! Do not initialize!\n");
}
Statement* SQLParser::parseSQL(const char *text) {
Statement* stmt;
yyscan_t scanner;
YY_BUFFER_STATE state;
if (yylex_init(&scanner)) {
// couldn't initialize
fprintf(stderr, "Error when initializing!\n");
return NULL;
}
state = yy_scan_string(text, scanner);
if (yyparse(&stmt, scanner)) {
// error parsing
fprintf(stderr, "Error when parsing!\n");
return NULL;
}
yy_delete_buffer(state, scanner);
yylex_destroy(scanner);
return stmt;
}

16
src/lib/SQLParser.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __SQLPARSER_H_
#define __SQLPARSER_H_
#include "Statement.h"
class SQLParser {
public:
static Statement* parseSQL(const char* sql);
private:
SQLParser();
};
#endif

15
src/lib/Statement.cpp Normal file
View File

@ -0,0 +1,15 @@
/*
* Statement.c
* Implementation of functions used to build the syntax tree.
*/
#include "Statement.h"
#include <stdlib.h>
Statement::Statement(EStatementType type) : _type(type) {};
SelectStatement::SelectStatement() : Statement(eSelect) {};
TableRef::TableRef(ETableRefType type) : _type(type) {};

60
src/lib/Statement.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Statement.h
* Definition of the structure used to build the syntax tree.
*/
#ifndef __STATEMENT_H__
#define __STATEMENT_H__
#include "Expression.h"
#include "List.h"
class TableRef;
typedef enum {
eSelect,
eDelete,
eInsert,
eCreate
} EStatementType;
class Statement {
public:
Statement(EStatementType type);
EStatementType _type;
};
class SelectStatement : public Statement {
public:
SelectStatement();
TableRef* _from_table;
List<Expression*>* _select_list;
List<Expression*>* _group_by;
};
/**
* TableRef
* Holds reference to tables. Can be either table names or a select statement.
*/
typedef enum {
eTableName,
eTableSelect
} ETableRefType;
class TableRef {
public:
TableRef(ETableRefType type);
ETableRefType _type;
SelectStatement* _stmt;
List<char*>* _table_names;
};
#endif // __STATEMENT_H__

52
src/sql_parser.cpp Normal file
View File

@ -0,0 +1,52 @@
/*
* sql_parser.cpp
*/
#include "sql_interface.h"
#include <stdio.h>
void evaluate_statement(Statement* stmt);
int main(int argc, char *argv[]) {
if (argc <= 1) {
fprintf(stderr, "No SQL-Statement given!\n");
return -1;
}
Statement *stmt = NULL;
for (int n = 1; n < argc; ++n) {
char* sql = argv[n];
printf("\nEvaluating Statement \"%s\"\n", sql);
Statement* stmt = parse_sql(sql);
evaluate_statement(stmt);
}
return 0;
}
void evaluate_select_statement(SelectStatement* stmt) {
// printf("Selecting %s from %s\n", stmt->_targets->toString(), stmt->_from_clause);
}
void evaluate_statement(Statement* stmt) {
printf("Statement at %p\n", stmt);
if (stmt == NULL) return;
switch (stmt->_type) {
case eSelect:
evaluate_select_statement((SelectStatement*) stmt);
break;
case eInsert:
printf("Insert Statment found!\n");
break;
default:
break;
}
}

107
src/sql_tests.cpp Normal file
View File

@ -0,0 +1,107 @@
/*
* sql_tests.cpp
*/
#include "lib/SQLParser.h"
#include <stdio.h>
#include <string>
#include <cassert>
#define STREQUALS(str1, str2) std::string(str1).compare(std::string(str2)) == 0
#define ASSERT(cond) if (!(cond)) { fprintf(stderr, "failed! Assertion (" #cond ")\n"); return; }
#define ASSERT_STR(STR1, STR2) ASSERT(STREQUALS(STR1, STR2));
void SelectTest1() {
printf("Test: SelectTest1... ");
fflush(stdout);
const char* sql = "SELECT age, name, address from table;";
Statement* stmt = SQLParser::parseSQL(sql);
ASSERT(stmt != NULL);
ASSERT(stmt->_type == eSelect);
SelectStatement* select = (SelectStatement*) stmt;
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(select->_from_table != NULL);
ASSERT(select->_from_table->_type == eTableName);
ASSERT_STR(select->_from_table->_table_names->at(0), "table");
printf("passed!\n");
}
void SelectTest2() {
printf("Test: SelectTest2... ");
fflush(stdout);
const char* sql = "SELECT age, name, address FROM (SELECT age FROM table, table2);";
Statement* stmt = SQLParser::parseSQL(sql);
ASSERT(stmt != NULL);
ASSERT(stmt->_type == eSelect);
SelectStatement* select = (SelectStatement*) stmt;
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(select->_from_table != NULL);
ASSERT(select->_from_table->_type == eTableSelect);
ASSERT(select->_from_table->_stmt != NULL);
ASSERT(select->_from_table->_stmt->_select_list->size() == 1);
ASSERT_STR(select->_from_table->_stmt->_from_table->_table_names->at(0), "table");
ASSERT_STR(select->_from_table->_stmt->_from_table->_table_names->at(1), "table2");
printf("passed!\n");
}
void SelectTest3() {
printf("Test: SelectTest3... ");
fflush(stdout);
const char* sql = "SELECT name, AVG(age) FROM table GROUP BY name";
Statement* stmt = SQLParser::parseSQL(sql);
ASSERT(stmt != NULL);
ASSERT(stmt->_type == eSelect);
SelectStatement* select = (SelectStatement*) stmt;
ASSERT(select->_select_list->size() == 2);
ASSERT(select->_select_list->at(0)->func_name == NULL);
ASSERT_STR("name", select->_select_list->at(0)->name);
ASSERT(select->_select_list->at(1)->func_name != NULL);
ASSERT_STR("age", select->_select_list->at(1)->name);
ASSERT_STR("AVG", select->_select_list->at(1)->func_name);
ASSERT(select->_group_by != NULL);
ASSERT(select->_group_by->size() == 1);
ASSERT_STR("name", select->_group_by->at(0)->name);
printf("passed!\n");
}
int main(int argc, char *argv[]) {
printf("\n######################################\n");
printf("## Running all tests...\n\n");
SelectTest1();
SelectTest2();
SelectTest3();
printf("\n## Finished running all tests...\n");
printf("######################################\n");
return 0;
}