Skip to content

Commit 27b4008

Browse files
committed
Adding inistal example for MySQL
1 parent fb25886 commit 27b4008

8 files changed

Lines changed: 646 additions & 38 deletions

File tree

.gitignore

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@
3232
*.app
3333

3434

35+
mysql_example
3536
pgsql_example
3637
libpgsqlparser.a
37-
src/pgsql_parser/pgsql_parser.tab.c
38-
src/pgsql_parser/pgsql_parser.tab.h
39-
src/pgsql_parser/pgsql_lexer.yy.c
40-
src/pgsql_parser/pgsql_parser.output
41-
src/pgsql_parser/pgsql_parser.report
38+
src/*_parser/*_parser.tab.c
39+
src/*_parser/*_parser.tab.h
40+
src/*_parser/*_lexer.yy.c
41+
src/*_parser/*_parser.output
42+
src/*_parser/*_parser.report
43+

Makefile

Lines changed: 85 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,67 +9,119 @@ PROJECT_ROOT = .
99
INCLUDE_DIR = $(PROJECT_ROOT)/include
1010
SRC_DIR = $(PROJECT_ROOT)/src
1111

12+
# --- PostgreSQL Parser Variables ---
1213
PGSQL_PARSER_SRC_DIR = $(SRC_DIR)/pgsql_parser
1314
PGSQL_PARSER_INCLUDE_DIR = $(INCLUDE_DIR)/pgsql_parser
15+
PGSQL_TARGET_LIB_NAME = pgsqlparser
16+
PGSQL_TARGET_LIB = $(PROJECT_ROOT)/lib$(PGSQL_TARGET_LIB_NAME).a
17+
PGSQL_EXAMPLE_EXE = $(PROJECT_ROOT)/pgsql_example
1418

15-
TARGET_LIB_NAME = pgsqlparser
16-
TARGET_LIB = $(PROJECT_ROOT)/lib$(TARGET_LIB_NAME).a
17-
EXAMPLE_EXE = $(PROJECT_ROOT)/pgsql_example
19+
PGSQL_BISON_C_FILE = pgsql_parser.tab.c
20+
PGSQL_BISON_H_FILE = pgsql_parser.tab.h
21+
PGSQL_FLEX_C_FILE = pgsql_lexer.yy.c
1822

19-
PGSQL_BISON_PARSER_C_FILE = pgsql_parser.tab.c
20-
PGSQL_BISON_PARSER_H_FILE = pgsql_parser.tab.h
21-
PGSQL_FLEX_LEXER_C_FILE = pgsql_lexer.yy.c
22-
23-
PGSQL_BISON_PARSER_C = $(PGSQL_PARSER_SRC_DIR)/$(PGSQL_BISON_PARSER_C_FILE)
24-
PGSQL_BISON_PARSER_H = $(PGSQL_PARSER_SRC_DIR)/$(PGSQL_BISON_PARSER_H_FILE)
25-
PGSQL_FLEX_LEXER_C = $(PGSQL_PARSER_SRC_DIR)/$(PGSQL_FLEX_LEXER_C_FILE)
23+
PGSQL_BISON_C = $(PGSQL_PARSER_SRC_DIR)/$(PGSQL_BISON_C_FILE)
24+
PGSQL_BISON_H = $(PGSQL_PARSER_SRC_DIR)/$(PGSQL_BISON_H_FILE)
25+
PGSQL_FLEX_C = $(PGSQL_PARSER_SRC_DIR)/$(PGSQL_FLEX_C_FILE)
2626

2727
PGSQL_LIB_OBJS = \
28-
$(PGSQL_BISON_PARSER_C:.c=.o) \
29-
$(PGSQL_FLEX_LEXER_C:.c=.o) \
28+
$(PGSQL_BISON_C:.c=.o) \
29+
$(PGSQL_FLEX_C:.c=.o) \
3030
$(PGSQL_PARSER_SRC_DIR)/pgsql_parser.o
31+
PGSQL_EXAMPLE_OBJS = $(PROJECT_ROOT)/examples/main_pgsql_example.o
32+
33+
# --- MySQL Parser Variables ---
34+
MYSQL_PARSER_SRC_DIR = $(SRC_DIR)/mysql_parser
35+
MYSQL_PARSER_INCLUDE_DIR = $(INCLUDE_DIR)/mysql_parser
36+
MYSQL_TARGET_LIB_NAME = mysqlparser
37+
MYSQL_TARGET_LIB = $(PROJECT_ROOT)/lib$(MYSQL_TARGET_LIB_NAME).a
38+
MYSQL_EXAMPLE_EXE = $(PROJECT_ROOT)/mysql_example
39+
40+
MYSQL_BISON_C_FILE = mysql_parser.tab.c
41+
MYSQL_BISON_H_FILE = mysql_parser.tab.h
42+
MYSQL_FLEX_C_FILE = mysql_lexer.yy.c
43+
44+
MYSQL_BISON_C = $(MYSQL_PARSER_SRC_DIR)/$(MYSQL_BISON_C_FILE)
45+
MYSQL_BISON_H = $(MYSQL_PARSER_SRC_DIR)/$(MYSQL_BISON_H_FILE)
46+
MYSQL_FLEX_C = $(MYSQL_PARSER_SRC_DIR)/$(MYSQL_FLEX_C_FILE)
47+
48+
MYSQL_LIB_OBJS = \
49+
$(MYSQL_BISON_C:.c=.o) \
50+
$(MYSQL_FLEX_C:.c=.o) \
51+
$(MYSQL_PARSER_SRC_DIR)/mysql_parser.o
52+
MYSQL_EXAMPLE_OBJS = $(PROJECT_ROOT)/examples/main_mysql_example.o
3153

32-
EXAMPLE_OBJS = $(PROJECT_ROOT)/examples/main_pgsql_example.o
3354

34-
.PHONY: all clean examples
55+
.PHONY: all clean examples pgsql mysql
3556

36-
all: $(TARGET_LIB) examples
57+
all: pgsql mysql examples
3758

38-
examples: $(EXAMPLE_EXE)
59+
pgsql: $(PGSQL_TARGET_LIB)
60+
mysql: $(MYSQL_TARGET_LIB)
3961

40-
$(TARGET_LIB): $(PGSQL_LIB_OBJS)
62+
examples: $(PGSQL_EXAMPLE_EXE) $(MYSQL_EXAMPLE_EXE)
63+
64+
# --- PostgreSQL Rules ---
65+
$(PGSQL_TARGET_LIB): $(PGSQL_LIB_OBJS)
4166
ar rcs $@ $(PGSQL_LIB_OBJS)
4267
@echo "Created library $@"
4368

44-
$(EXAMPLE_EXE): $(EXAMPLE_OBJS) $(TARGET_LIB)
45-
$(LINKER) $(CXXFLAGS) -o $@ $(EXAMPLE_OBJS) -L$(PROJECT_ROOT) -l$(TARGET_LIB_NAME)
46-
@echo "Created example $@"
69+
$(PGSQL_EXAMPLE_EXE): $(PGSQL_EXAMPLE_OBJS) $(PGSQL_TARGET_LIB)
70+
$(LINKER) $(CXXFLAGS) -o $@ $(PGSQL_EXAMPLE_OBJS) -L$(PROJECT_ROOT) -l$(PGSQL_TARGET_LIB_NAME)
71+
@echo "Created PostgreSQL example $@"
4772

48-
$(PGSQL_BISON_PARSER_H) $(PGSQL_BISON_PARSER_C): $(PGSQL_PARSER_SRC_DIR)/pgsql_parser.y $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_ast.h $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h
73+
$(PGSQL_BISON_H) $(PGSQL_BISON_C): $(PGSQL_PARSER_SRC_DIR)/pgsql_parser.y $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_ast.h $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h
4974
cd $(PGSQL_PARSER_SRC_DIR) && bison -d -v --report=all pgsql_parser.y
5075

51-
$(PGSQL_FLEX_LEXER_C): $(PGSQL_PARSER_SRC_DIR)/pgsql_lexer.l $(PGSQL_BISON_PARSER_H)
52-
cd $(PGSQL_PARSER_SRC_DIR) && flex -o $(PGSQL_FLEX_LEXER_C_FILE) pgsql_lexer.l
76+
$(PGSQL_FLEX_C): $(PGSQL_PARSER_SRC_DIR)/pgsql_lexer.l $(PGSQL_BISON_H)
77+
cd $(PGSQL_PARSER_SRC_DIR) && flex -o $(PGSQL_FLEX_C_FILE) pgsql_lexer.l
5378

54-
# Rule to compile Bison-generated file (pgsql_parser.tab.c) AS C++
55-
$(PGSQL_BISON_PARSER_C:.c=.o): $(PGSQL_BISON_PARSER_C) $(PGSQL_BISON_PARSER_H) $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h
79+
$(PGSQL_PARSER_SRC_DIR)/pgsql_parser.tab.o: $(PGSQL_BISON_C) $(PGSQL_BISON_H) $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h
5680
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
5781

58-
# Rule to compile Flex-generated file (pgsql_lexer.yy.c) AS C++
59-
$(PGSQL_FLEX_LEXER_C:.c=.o): $(PGSQL_FLEX_LEXER_C) $(PGSQL_BISON_PARSER_H) $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h
82+
$(PGSQL_PARSER_SRC_DIR)/pgsql_lexer.yy.o: $(PGSQL_FLEX_C) $(PGSQL_BISON_H) $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h
6083
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
6184

62-
# Rule to compile pgsql_parser.cpp (C++ file)
63-
$(PGSQL_PARSER_SRC_DIR)/pgsql_parser.o: $(PGSQL_PARSER_SRC_DIR)/pgsql_parser.cpp $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_ast.h $(PGSQL_BISON_PARSER_H)
85+
$(PGSQL_PARSER_SRC_DIR)/pgsql_parser.o: $(PGSQL_PARSER_SRC_DIR)/pgsql_parser.cpp $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_ast.h $(PGSQL_BISON_H)
6486
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
6587

6688
$(PROJECT_ROOT)/examples/main_pgsql_example.o: $(PROJECT_ROOT)/examples/main_pgsql_example.cpp $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_parser.h $(PGSQL_PARSER_INCLUDE_DIR)/pgsql_ast.h
6789
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
6890

91+
# --- MySQL Rules ---
92+
$(MYSQL_TARGET_LIB): $(MYSQL_LIB_OBJS)
93+
ar rcs $@ $(MYSQL_LIB_OBJS)
94+
@echo "Created library $@"
95+
96+
$(MYSQL_EXAMPLE_EXE): $(MYSQL_EXAMPLE_OBJS) $(MYSQL_TARGET_LIB)
97+
$(LINKER) $(CXXFLAGS) -o $@ $(MYSQL_EXAMPLE_OBJS) -L$(PROJECT_ROOT) -l$(MYSQL_TARGET_LIB_NAME)
98+
@echo "Created MySQL example $@"
99+
100+
$(MYSQL_BISON_H) $(MYSQL_BISON_C): $(MYSQL_PARSER_SRC_DIR)/mysql_parser.y $(MYSQL_PARSER_INCLUDE_DIR)/mysql_ast.h $(MYSQL_PARSER_INCLUDE_DIR)/mysql_parser.h
101+
cd $(MYSQL_PARSER_SRC_DIR) && bison -d -v --report=all -o $(MYSQL_BISON_C_FILE) --defines=$(MYSQL_BISON_H_FILE) mysql_parser.y
102+
103+
$(MYSQL_FLEX_C): $(MYSQL_PARSER_SRC_DIR)/mysql_lexer.l $(MYSQL_BISON_H)
104+
cd $(MYSQL_PARSER_SRC_DIR) && flex -o $(MYSQL_FLEX_C_FILE) mysql_lexer.l
105+
106+
$(MYSQL_PARSER_SRC_DIR)/mysql_parser.tab.o: $(MYSQL_BISON_C) $(MYSQL_BISON_H) $(MYSQL_PARSER_INCLUDE_DIR)/mysql_parser.h
107+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
108+
109+
$(MYSQL_PARSER_SRC_DIR)/mysql_lexer.yy.o: $(MYSQL_FLEX_C) $(MYSQL_BISON_H) $(MYSQL_PARSER_INCLUDE_DIR)/mysql_parser.h
110+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
111+
112+
$(MYSQL_PARSER_SRC_DIR)/mysql_parser.o: $(MYSQL_PARSER_SRC_DIR)/mysql_parser.cpp $(MYSQL_PARSER_INCLUDE_DIR)/mysql_parser.h $(MYSQL_PARSER_INCLUDE_DIR)/mysql_ast.h $(MYSQL_BISON_H)
113+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
114+
115+
$(PROJECT_ROOT)/examples/main_mysql_example.o: $(PROJECT_ROOT)/examples/main_mysql_example.cpp $(MYSQL_PARSER_INCLUDE_DIR)/mysql_parser.h $(MYSQL_PARSER_INCLUDE_DIR)/mysql_ast.h
116+
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
117+
118+
69119
clean:
70-
rm -f $(TARGET_LIB) $(EXAMPLE_EXE)
71-
rm -f $(PGSQL_LIB_OBJS) $(EXAMPLE_OBJS)
72-
rm -f $(PGSQL_BISON_PARSER_C) $(PGSQL_BISON_PARSER_H) $(PGSQL_FLEX_LEXER_C)
120+
rm -f $(PGSQL_TARGET_LIB) $(PGSQL_EXAMPLE_EXE) $(MYSQL_TARGET_LIB) $(MYSQL_EXAMPLE_EXE)
121+
rm -f $(PGSQL_LIB_OBJS) $(PGSQL_EXAMPLE_OBJS) $(MYSQL_LIB_OBJS) $(MYSQL_EXAMPLE_OBJS)
122+
rm -f $(PGSQL_BISON_C) $(PGSQL_BISON_H) $(PGSQL_FLEX_C)
123+
rm -f $(MYSQL_BISON_C) $(MYSQL_BISON_H) $(MYSQL_FLEX_C)
73124
rm -f $(PGSQL_PARSER_SRC_DIR)/pgsql_parser.output $(PGSQL_PARSER_SRC_DIR)/pgsql_parser.report
74-
rm -f $(PGSQL_PARSER_SRC_DIR)/lex.backup
125+
rm -f $(MYSQL_PARSER_SRC_DIR)/mysql_parser.output $(MYSQL_PARSER_SRC_DIR)/mysql_parser.report
126+
rm -f $(PGSQL_PARSER_SRC_DIR)/lex.backup $(MYSQL_PARSER_SRC_DIR)/lex.backup
75127
@echo "Cleaned up project."

examples/main_mysql_example.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "mysql_parser/mysql_parser.h" // Changed include path and namespace
2+
#include <iostream>
3+
#include <vector>
4+
#include <string>
5+
6+
int main() {
7+
MysqlParser::Parser parser; // Changed namespace
8+
9+
std::vector<std::string> queries = {
10+
"SELECT name FROM users;",
11+
"SELECT * FROM `orders`;", // MySQL backticked identifier
12+
"INSERT INTO products VALUES ('a new gadget');",
13+
"INSERT INTO logs VALUES (\"Error message with double quotes\");", // MySQL double quotes
14+
"INSERT INTO `special-table` VALUES ('escaped value \\'single quote\\' and \\\\ backslash');", // MySQL escapes
15+
"QUIT", // MySQL often doesn't require semicolon for last statement in a batch
16+
"SELECT * FROM WHERE;",
17+
"INSERT INTO logs VALUES (no_quotes_here);"
18+
};
19+
20+
for (const auto& query : queries) {
21+
std::cout << "------------------------------------------\n";
22+
std::cout << "Parsing MySQL query: " << query << std::endl;
23+
24+
parser.clearErrors();
25+
std::unique_ptr<MysqlParser::AstNode> ast = parser.parse(query); // Changed namespace
26+
27+
if (ast) {
28+
std::cout << "Parsing successful!" << std::endl;
29+
MysqlParser::print_ast(ast.get()); // Changed namespace
30+
} else {
31+
std::cout << "Parsing failed." << std::endl;
32+
const auto& errors = parser.getErrors();
33+
if (errors.empty()) {
34+
std::cout << " (No specific error messages, check parser logic or mysql_yyerror)" << std::endl;
35+
} else {
36+
for (const auto& error : errors) {
37+
std::cout << " Error: " << error << std::endl;
38+
}
39+
}
40+
}
41+
}
42+
return 0;
43+
}

include/mysql_parser/mysql_ast.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#ifndef MYSQL_PARSER_AST_H
2+
#define MYSQL_PARSER_AST_H
3+
4+
#include <string>
5+
#include <vector>
6+
#include <iostream>
7+
#include <algorithm>
8+
9+
namespace MysqlParser { // Changed namespace
10+
11+
// NodeType enum can be identical for this stage, or diverge later
12+
enum class NodeType {
13+
NODE_UNKNOWN,
14+
NODE_COMMAND,
15+
NODE_SELECT_STATEMENT,
16+
NODE_INSERT_STATEMENT,
17+
NODE_IDENTIFIER,
18+
NODE_STRING_LITERAL,
19+
NODE_ASTERISK
20+
};
21+
22+
struct AstNode {
23+
NodeType type;
24+
std::string value;
25+
std::vector<AstNode*> children;
26+
27+
AstNode(NodeType t, const std::string& val = "") : type(t), value(val) {}
28+
AstNode(NodeType t, std::string&& val) : type(t), value(std::move(val)) {}
29+
30+
~AstNode() {
31+
for (AstNode* child : children) {
32+
delete child;
33+
}
34+
}
35+
36+
AstNode(const AstNode&) = delete;
37+
AstNode& operator=(const AstNode&) = delete;
38+
AstNode(AstNode&&) = delete;
39+
AstNode& operator=(AstNode&&) = delete;
40+
41+
void addChild(AstNode* child) {
42+
if (child) {
43+
children.push_back(child);
44+
}
45+
}
46+
};
47+
48+
inline void print_ast(const AstNode* node, int indent = 0) {
49+
if (!node) return;
50+
for (int i = 0; i < indent; ++i) std::cout << " ";
51+
52+
std::string type_str;
53+
switch(node->type) {
54+
case NodeType::NODE_UNKNOWN: type_str = "UNKNOWN"; break;
55+
case NodeType::NODE_COMMAND: type_str = "COMMAND"; break;
56+
case NodeType::NODE_SELECT_STATEMENT: type_str = "SELECT_STMT"; break;
57+
case NodeType::NODE_INSERT_STATEMENT: type_str = "INSERT_STMT"; break;
58+
case NodeType::NODE_IDENTIFIER: type_str = "IDENTIFIER"; break;
59+
case NodeType::NODE_STRING_LITERAL: type_str = "STRING_LITERAL"; break;
60+
case NodeType::NODE_ASTERISK: type_str = "ASTERISK"; break;
61+
default: type_str = "UNHANDLED_TYPE(" + std::to_string(static_cast<int>(node->type)) + ")"; break;
62+
}
63+
std::cout << "Type: " << type_str << ", Value: '" << node->value << "'" << std::endl;
64+
for (const AstNode* child : node->children) {
65+
print_ast(child, indent + 1);
66+
}
67+
}
68+
69+
} // namespace MysqlParser
70+
71+
#endif // MYSQL_PARSER_AST_H
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef MYSQL_PARSER_PARSER_H
2+
#define MYSQL_PARSER_PARSER_H
3+
4+
#include "mysql_ast.h" // Uses MysqlParser::AstNode
5+
#include <string>
6+
#include <vector>
7+
#include <memory>
8+
9+
typedef void* yyscan_t; // Should be the same opaque type for Flex
10+
11+
namespace MysqlParser { // Changed namespace
12+
13+
class Parser {
14+
public:
15+
Parser();
16+
~Parser();
17+
18+
std::unique_ptr<AstNode> parse(const std::string& sql_query);
19+
20+
const std::vector<std::string>& getErrors() const;
21+
void clearErrors();
22+
23+
// Internal methods for Bison/Flex interaction
24+
void internal_set_ast(AstNode* root);
25+
void internal_add_error(const std::string& msg);
26+
void internal_add_error_at(const std::string& msg, int line, int column);
27+
28+
29+
private:
30+
std::unique_ptr<AstNode> ast_root_;
31+
std::vector<std::string> errors_;
32+
yyscan_t scanner_state_;
33+
};
34+
35+
} // namespace MysqlParser
36+
37+
// Declaration for mysql_yyerror, which is called by Bison's mysql_yyparse.
38+
// As both generated parser and this definition will be C++, extern "C" not strictly needed here.
39+
void mysql_yyerror(yyscan_t yyscanner, MysqlParser::Parser* parser_context, const char* msg); // Changed prefix
40+
41+
#endif // MYSQL_PARSER_PARSER_H

0 commit comments

Comments
 (0)