diff --git a/src/lemon/Makefile b/src/lemon/Makefile new file mode 100644 index 0000000..7fe7234 --- /dev/null +++ b/src/lemon/Makefile @@ -0,0 +1,11 @@ + +all: lemon_parser.c flex_lexer.c + +lemon_parser.c: lemon_parser.y + lemon lemon_parser.y + +flex_lexer.c: flex_lexer.l + flex --outfile=flex_lexer.c --header-file=flex_lexer.h flex_lexer.l + +clean: + rm -f lemon_parser.c flex_lexer.c lemon_parser.h flex_lexer.h lemon_parser.out \ No newline at end of file diff --git a/src/lemon/SQLParser.cpp b/src/lemon/SQLParser.cpp new file mode 100644 index 0000000..9aafd01 --- /dev/null +++ b/src/lemon/SQLParser.cpp @@ -0,0 +1,37 @@ +#include "SQLParser.h" +#include "lemon_parser.h" +#include "flex_lexer.h" +#include + + + +void *ParseAlloc(void *(*mallocProc)(size_t)); +void ParseFree(void *p, void (*freeProc)(void*)); +void Parse(void *yyp, int yymajor, const char* text, Statement**); + + +SQLParser::SQLParser() { + fprintf(stderr, "SQLParser only has static methods atm! Do not initialize!\n"); +} + + +Statement* SQLParser::parseSQL(const char *text) { + yyscan_t scanner; + yylex_init(&scanner); + + // Scan the provided string + YY_BUFFER_STATE state = yy_scan_string(text, scanner); + + void* lemonParser = ParseAlloc(malloc); + int tokenCode; + Statement* result; + do { + tokenCode = yylex(scanner); + Parse(lemonParser, tokenCode, yyget_text(scanner), &result); + // printf("Token %d\n", tokenCode); + } while (tokenCode > 0); + + yy_delete_buffer(state, scanner); + yylex_destroy(scanner); + return result; +} \ No newline at end of file diff --git a/src/lemon/SQLParser.h b/src/lemon/SQLParser.h new file mode 100644 index 0000000..779a644 --- /dev/null +++ b/src/lemon/SQLParser.h @@ -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 \ No newline at end of file diff --git a/src/lemon/flex_lexer.l b/src/lemon/flex_lexer.l new file mode 100644 index 0000000..a498aed --- /dev/null +++ b/src/lemon/flex_lexer.l @@ -0,0 +1,52 @@ +%{ +/** + * flex_lexer.l file + */ + +#include "lemon_parser.h" +#include + +#define TOK(name) { return name; } +%} + + +%option reentrant +%option noyywrap + +%% + +[ \t\n]+ ; /* skip whitespace */ + +SELECT TOK(SELECT) +FROM TOK(FROM) +GROUP TOK(GROUP) +BY TOK(BY) +WHERE TOK(WHERE) +NOT TOK(NOT) +AND TOK(AND) +OR TOK(OR) + +"=" | +"<>" | +"<" | +">" | +"<=" | +">=" TOK(COMPARISON) + + +[-+*/(),.;] TOK(yytext[0]) + +[0-9]+ | +[0-9]+"."[0-9]* | +"."[0-9]* TOK(INTNUM) + +[A-Za-z][A-Za-z0-9_]* TOK(NAME) + + +'[^'\n]*' TOK(STRING) + +%% + +int yyerror(const char *msg) { + fprintf(stderr,"Error:%s\n",msg); return 0; +} \ No newline at end of file diff --git a/src/lemon/lemon_parser.y b/src/lemon/lemon_parser.y new file mode 100644 index 0000000..50c7749 --- /dev/null +++ b/src/lemon/lemon_parser.y @@ -0,0 +1,24 @@ +%include { + #include + #include + #include "lib/Statement.h" +} +%syntax_error { printf("Lemon syntax error\n"); } + +%extra_argument { Statement** result } +%token_type {const char*} +%type expr {Statement*} + +%left PLUS MINUS . + + +start ::= prog. + +prog ::= prog print NL . +prog ::= prog print . +prog ::= . + +print ::= expr(a) . { *result = a; } + +expr(a) ::= NUMBER . { a = new Statement(eSelect); } +expr(a) ::= expr(b) PLUS expr . { a = b; } \ No newline at end of file diff --git a/src/lemon/token_def.h b/src/lemon/token_def.h new file mode 100644 index 0000000..e69de29