Repository navigation
Expand file tree
/
Copy pathparser.cpp
More file actions
108 lines (92 loc) · 3.48 KB
/
Copy pathparser.cpp
File metadata and controls
108 lines (92 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "../include/Parser.hpp"
const Token& Parser::peek() const{
return tokens[pos];
}
bool Parser::match(TokenType t){
if(tokens[pos].type == t){
pos++;
return true;
}
return false;
}
const Token& Parser::expect(TokenType t, const std::string& what){
if(tokens[pos].type != t){
throw ParseError("expected " + what + ", got '" + tokens[pos].text + "'", tokens[pos].pos);
}
return tokens[pos++];
}
std::unique_ptr<SelectStmtAST> Parser::parse(std::vector<Token> toks){
tokens = std::move(toks);
pos = 0;
return parseSelect();
}
std::unique_ptr<SelectStmtAST> Parser::parseSelect(){
expect(TokenType::KW_SELECT, "SELECT");
std::vector<std::unique_ptr<ColumnExprAST>> columns;
bool selectAll = match(TokenType::STAR);
if(!selectAll)
columns = parseColumnList();
auto tables = parseFromClause();
std::unique_ptr<ExprAST> where;
if(match(TokenType::KW_WHERE))
where = parseWhereClause();
std::vector<std::unique_ptr<ColumnExprAST>> orderBy;
if(match(TokenType::KW_ORDER)){
expect(TokenType::KW_BY, "BY after ORDER");
orderBy.push_back(parseColumnRef());
if(peek().type == TokenType::COMMA)
throw ParseError("ORDER BY allows at most one attribute", peek().pos);
}
expect(TokenType::END, "end of query");
return std::make_unique<SelectStmtAST>(std::move(columns), std::move(tables), std::move(where), std::move(orderBy), selectAll);
}
std::vector<std::unique_ptr<ColumnExprAST>> Parser::parseColumnList() {
std::vector<std::unique_ptr<ColumnExprAST>> cols;
do {
cols.push_back(parseColumnRef());
} while (match(TokenType::COMMA));
return cols;
}
std::unique_ptr<ColumnExprAST> Parser::parseColumnRef() {
std::string first = expect(TokenType::IDENTIFIER, "column name").text;
if (match(TokenType::DOT)) {
std::string col = expect(TokenType::IDENTIFIER, "name after '.'").text;
return std::make_unique<ColumnExprAST>(first, col);
}
return std::make_unique<ColumnExprAST>("", first);
}
std::vector<std::string> Parser::parseFromClause() {
expect(TokenType::KW_FROM, "FROM");
std::vector<std::string> tables;
do {
if(tables.size() == 4)
throw ParseError("at most 4 tables allowed in FROM", peek().pos);
tables.push_back(expect(TokenType::IDENTIFIER, "table name").text);
} while (match(TokenType::COMMA));
return tables;
}
std::unique_ptr<ExprAST> Parser::parseWhereClause() {
auto lhs = parseCondition();
size_t conditions = 1;
while (match(TokenType::KW_AND)) {
if(conditions == 6)
throw ParseError("at most 6 conditions allowed in WHERE", peek().pos);
auto rhs = parseCondition();
lhs = std::make_unique<BinaryExprAST>("AND", std::move(lhs), std::move(rhs));
conditions++;
}
return lhs;
}
std::unique_ptr<ExprAST> Parser::parseCondition() {
auto lhs = parseColumnRef();
std::string op = expect(TokenType::COMPARATOR, "comparator").text;
auto rhs = parseValue();
return std::make_unique<BinaryExprAST>(op, std::move(lhs), std::move(rhs));
}
std::unique_ptr<ExprAST> Parser::parseValue() {
if (peek().type == TokenType::NUMBER)
return std::make_unique<NumberExprAST>(std::stod(expect(TokenType::NUMBER, "number").text));
if (peek().type == TokenType::STRING)
return std::make_unique<StringExprAST>(expect(TokenType::STRING, "string").text);
return parseColumnRef();
}