vkdb
A time series database engine in C++.
Loading...
Searching...
No Matches
parser.cpp
1#include <vkdb/parser.h>
2#include <vkdb/token.h>
3
4namespace vkdb {
6 const std::vector<Token>& tokens,
7 error_callback callback
8) noexcept
9 : tokens_{tokens}, callback_{callback}, position_{0} {}
10
11std::optional<Expr> Parser::parse() noexcept {
12 try {
13 return parse_expression();
14 } catch (const ParseError&) {
15 return std::nullopt;
16 }
17}
18
19ParseError Parser::error(Token token, const std::string& message) {
20 callback_(token, message);
21 return ParseError{};
22}
23
24void Parser::synchronise() {
25 advance();
26 while (tokens_remaining()) {
27 if (peek_back().type() == TokenType::SEMICOLON) {
28 return;
29 }
30 if (QUERY_BASE_WORDS.contains(peek().type())) {
31 return;
32 }
33 advance();
34 }
35}
36
37bool Parser::tokens_remaining() const noexcept {
38 return position_ < tokens_.size();
39}
40
41Token Parser::peek_back() const {
42 return tokens_[position_ - 1];
43}
44
45Token Parser::peek() const {
46 return tokens_[position_];
47}
48
49Token Parser::advance() noexcept {
50 if (tokens_remaining()) {
51 ++position_;
52 }
53 return peek_back();
54}
55
56bool Parser::check(TokenType type) const noexcept {
57 if (!tokens_remaining()) {
58 return false;
59 }
60 return peek().type() == type;
61}
62
63template <AllSameNoCVRefQuals<TokenType>... TokenTypes>
64bool Parser::match(TokenTypes... types) noexcept {
65 for (const auto& type : {types...}) {
66 if (check(type)) {
67 advance();
68 return true;
69 }
70 }
71 return false;
72}
73
74Token Parser::consume(TokenType type, const std::string& message) {
75 if (check(type)) {
76 return advance();
77 }
78 throw error(peek(), message);
79}
80
81Expr Parser::parse_expression() {
82 Expr expr{};
83 do {
84 expr.push_back(parse_query());
85 consume(TokenType::SEMICOLON, "Expected semicolon.");
86 } while (tokens_remaining() && !check(TokenType::END_OF_FILE));
87 return expr;
88}
89
90Query Parser::parse_query() {
91 switch (peek().type()) {
92 case TokenType::SELECT:
93 return parse_select_query();
94 case TokenType::PUT:
95 return parse_put_query();
96 case TokenType::DELETE:
97 return parse_delete_query();
98 case TokenType::CREATE:
99 return parse_create_query();
100 case TokenType::DROP:
101 return parse_drop_query();
102 case TokenType::ADD:
103 return parse_add_query();
104 case TokenType::REMOVE:
105 return parse_remove_query();
106 case TokenType::TABLES:
107 return parse_tables_query();
108 default:
109 throw error(peek(), "Expected query base word.");
110 }
111}
112
113SelectQuery Parser::parse_select_query() {
114 consume(TokenType::SELECT, "Expected SELECT.");
115 auto select_type{parse_select_type()};
116 auto metric{parse_metric()};
117 consume(TokenType::FROM, "Expected FROM.");
118 auto table_name{parse_table_name()};
119 auto select_clause{parse_select_clause()};
120 return {
121 select_type,
122 metric,
123 table_name,
124 select_clause
125 };
126}
127
128PutQuery Parser::parse_put_query() {
129 consume(TokenType::PUT, "Expected PUT");
130 auto metric{parse_metric()};
131 auto timestamp{parse_timestamp()};
132 auto value{parse_value()};
133 consume(TokenType::INTO, "Expected INTO.");
134 auto table_name{parse_table_name()};
135 TagListExpr tag_list;
136 if (match(TokenType::TAGS)) {
137 tag_list = parse_tag_list();
138 }
139 return {
140 metric,
141 timestamp,
142 value,
143 table_name,
144 tag_list
145 };
146}
147
148DeleteQuery Parser::parse_delete_query() {
149 consume(TokenType::DELETE, "Expected DELETE.");
150 auto metric{parse_metric()};
151 auto timestamp{parse_timestamp()};
152 consume(TokenType::FROM, "Expected FROM.");
153 auto table_name{parse_table_name()};
154 TagListExpr tag_list;
155 if (match(TokenType::TAGS)) {
156 tag_list = parse_tag_list();
157 }
158 return {
159 metric,
160 timestamp,
161 table_name,
162 tag_list
163 };
164}
165
166CreateQuery Parser::parse_create_query() {
167 consume(TokenType::CREATE, "Expected CREATE.");
168 consume(TokenType::TABLE, "Expected TABLE.");
169 auto table_name{parse_table_name()};
170 TagColumnsExpr tag_columns;
171 if (match(TokenType::TAGS)) {
172 tag_columns = parse_tag_columns();
173 }
174 return {
175 table_name,
176 tag_columns
177 };
178}
179
180DropQuery Parser::parse_drop_query() {
181 consume(TokenType::DROP, "Expected DROP.");
182 consume(TokenType::TABLE, "Expected TABLE.");
183 auto table_name{parse_table_name()};
184 return {table_name};
185}
186
187AddQuery Parser::parse_add_query() {
188 consume(TokenType::ADD, "Expected ADD.");
189 consume(TokenType::TAGS, "Expected TAGS.");
190 auto tag_columns{parse_tag_columns()};
191 consume(TokenType::TO, "Expected TO.");
192 auto table_name{parse_table_name()};
193 return {
194 tag_columns,
195 table_name
196 };
197}
198
199RemoveQuery Parser::parse_remove_query() {
200 consume(TokenType::REMOVE, "Expected REMOVE.");
201 consume(TokenType::TAGS, "Expected TAGS.");
202 auto tag_columns{parse_tag_columns()};
203 consume(TokenType::FROM, "Expected FROM.");
204 auto table_name{parse_table_name()};
205 return {
206 tag_columns,
207 table_name
208 };
209}
210
211TablesQuery Parser::parse_tables_query() {
212 auto tables{consume(TokenType::TABLES, "Expected TABLES.")};
213 return {tables};
214}
215
216SelectType Parser::parse_select_type() {
217 auto select_type{[this]() -> SelectType {
218 switch (peek().type()) {
219 case TokenType::DATA:
220 advance();
221 return SelectTypeDataExpr{peek()};
222 case TokenType::COUNT:
223 advance();
224 return SelectTypeCountExpr{peek()};
225 case TokenType::AVG:
226 advance();
227 return SelectTypeAvgExpr{peek()};
228 case TokenType::SUM:
229 advance();
230 return SelectTypeSumExpr{peek()};
231 case TokenType::MIN:
232 advance();
233 return SelectTypeMinExpr{peek()};
234 case TokenType::MAX:
235 advance();
236 return SelectTypeMaxExpr{peek()};
237 default:
238 throw error(peek(), "Expected select type.");
239 }
240 }()};
241 return select_type;
242}
243
244SelectClause Parser::parse_select_clause() {
245 switch (peek().type()) {
246 case TokenType::ALL:
247 return parse_all_clause();
248 case TokenType::BETWEEN:
249 return parse_between_clause();
250 case TokenType::AT:
251 return parse_at_clause();
252 default:
253 throw error(peek(), "Expected select clause.");
254 }
255}
256
257AllClause Parser::parse_all_clause() {
258 consume(TokenType::ALL, "Expected ALL.");
259 WhereClause where_clause;
260 if (check(TokenType::WHERE)) {
261 where_clause = parse_where_clause();
262 }
263 return {where_clause};
264}
265
266BetweenClause Parser::parse_between_clause() {
267 consume(TokenType::BETWEEN, "Expected BETWEEN.");
268 auto start_timestamp{parse_timestamp()};
269 consume(TokenType::AND, "Expected AND.");
270 auto end_timestamp{parse_timestamp()};
271 WhereClause where_clause;
272 if (check(TokenType::WHERE)) {
273 where_clause = parse_where_clause();
274 }
275 return {
276 start_timestamp,
277 end_timestamp,
278 where_clause
279 };
280}
281
282AtClause Parser::parse_at_clause() {
283 consume(TokenType::AT, "Expected AT.");
284 auto timestamp{parse_timestamp()};
285 WhereClause where_clause;
286 if (check(TokenType::WHERE)) {
287 where_clause = parse_where_clause();
288 }
289 return {
290 timestamp,
291 where_clause
292 };
293}
294
295WhereClause Parser::parse_where_clause() {
296 consume(TokenType::WHERE, "Expected WHERE.");
297 auto tag_list{parse_tag_list()};
298 return {tag_list};
299}
300
301TagListExpr Parser::parse_tag_list() {
302 std::vector<TagExpr> tags;
303 do {
304 tags.push_back(parse_tag());
305 } while (match(TokenType::COMMA));
306 return {tags};
307}
308
309TagExpr Parser::parse_tag() {
310 auto tag_key{parse_tag_key()};
311 consume(TokenType::EQUAL, "Expected '='.");
312 auto tag_value{parse_tag_value()};
313 return {
314 tag_key,
315 tag_value
316 };
317}
318
319TagColumnsExpr Parser::parse_tag_columns() {
320 std::vector<TagKeyExpr> keys;
321 do {
322 keys.push_back(parse_tag_key());
323 } while (match(TokenType::COMMA));
324 return {keys};
325}
326
327TagKeyExpr Parser::parse_tag_key() {
328 auto tag_key{consume(TokenType::IDENTIFIER, "Expected tag key.")};
329 return {tag_key};
330}
331
332TagValueExpr Parser::parse_tag_value() {
333 auto tag_value{consume(TokenType::IDENTIFIER, "Expected tag value.")};
334 return {tag_value};
335}
336
337MetricExpr Parser::parse_metric() {
338 auto metric{consume(TokenType::IDENTIFIER, "Expected metric.")};
339 return {metric};
340}
341
342TableNameExpr Parser::parse_table_name() {
343 auto table_name{consume(TokenType::IDENTIFIER, "Expected table name.")};
344 return {table_name};
345}
346
347TimestampExpr Parser::parse_timestamp() {
348 auto timestamp{consume(TokenType::NUMBER, "Expected timestamp.")};
349 return {timestamp};
350}
351
352ValueExpr Parser::parse_value() {
353 auto value{consume(TokenType::NUMBER, "Expected value.")};
354 return {value};
355}
356} // namespace vkdb
Exception class for parse errors.
Definition parser.h:17
Parser()=delete
Deleted default constructor.
std::optional< Expr > parse() noexcept
Parses the tokens into an expression.
Definition parser.cpp:11
Represents a token.
Definition token.h:81