#include "parser.h" #include "exception.h" namespace usql { // TOOD handle premature eof Parser::Parser() { lexer = Lexer{}; } std::unique_ptr Parser::parse(const std::string &code) { lexer.parse(code); // lexer.debugTokens(); if (lexer.tokenType() == TokenType::keyword_create && lexer.nextTokenType() == TokenType::keyword_table) { return parse_create_table(); } if (lexer.tokenType() == TokenType::keyword_insert) { return parse_insert_into_table(); } if (lexer.tokenType() == TokenType::keyword_select) { return parse_select_from_table(); } if (lexer.tokenType() == TokenType::keyword_delete) { return parse_delete_from_table(); } if (lexer.tokenType() == TokenType::keyword_update) { return parse_update_table(); } if (lexer.tokenType() == TokenType::keyword_load) { return parse_load_table(); } std::cout << "ERROR, token:" << lexer.currentToken().token_string << std::endl; return std::make_unique(NodeType::error); } std::unique_ptr Parser::parse_create_table() { std::vector cols_def{}; lexer.skipToken(TokenType::keyword_create); lexer.skipToken(TokenType::keyword_table); if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } std::string table_name = lexer.consumeCurrentToken().token_string; lexer.skipToken(TokenType::open_paren); int column_order = 0; do { std::string column_name; ColumnType column_type; int column_len{1}; bool column_nullable{true}; // column name if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } column_name = lexer.consumeCurrentToken().token_string; // column type and optionally len if (lexer.tokenType() == TokenType::keyword_int) { column_type = ColumnType::integer_type; lexer.nextToken(); } else if (lexer.tokenType() == TokenType::keyword_float) { column_type = ColumnType::float_type; lexer.nextToken(); } else if (lexer.tokenType() == TokenType::keyword_varchar) { column_type = ColumnType::varchar_type; lexer.nextToken(); lexer.skipToken(TokenType::open_paren); if (lexer.tokenType() == TokenType::int_number) { column_len = std::stoi(lexer.consumeCurrentToken().token_string); } else { /* TODO handle error */ } lexer.skipToken(TokenType::close_paren); } else { /* TODO handle error */ } if (lexer.tokenType() == TokenType::keyword_not) { lexer.nextToken(); lexer.skipToken(TokenType::keyword_null); column_nullable = false; } else if (lexer.tokenType() == TokenType::keyword_null) { lexer.nextToken(); } cols_def.push_back( ColDefNode(column_name, column_type, column_order++, column_len, column_nullable)); lexer.skipTokenOptional(TokenType::comma); // TODO in future constraints } while (lexer.tokenType() != TokenType::close_paren); return std::make_unique(table_name, cols_def); } std::unique_ptr Parser::parse_insert_into_table() { std::vector exec_code{}; std::vector cols_names{}; std::vector cols_values{}; lexer.skipToken(TokenType::keyword_insert); lexer.skipToken(TokenType::keyword_into); // table name if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } std::string table_name = lexer.consumeCurrentToken().token_string; // column names lexer.skipToken(TokenType::open_paren); do { if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } cols_names.push_back(lexer.consumeCurrentToken().token_string); lexer.skipTokenOptional(TokenType::comma); } while (lexer.tokenType() != TokenType::close_paren); lexer.skipToken(TokenType::close_paren); lexer.skipToken(TokenType::keyword_values); // column values lexer.skipToken(TokenType::open_paren); do { cols_values.push_back(lexer.consumeCurrentToken().token_string); lexer.skipTokenOptional(TokenType::comma); } while (lexer.tokenType() != TokenType::close_paren); lexer.skipToken(TokenType::close_paren); return std::make_unique(table_name, cols_names, cols_values); } std::unique_ptr Parser::parse_select_from_table() { std::vector cols_names{}; lexer.skipToken(TokenType::keyword_select); while (lexer.tokenType() != TokenType::keyword_from) { cols_names.push_back(lexer.consumeCurrentToken().token_string); lexer.skipTokenOptional(TokenType::comma); } lexer.skipToken(TokenType::keyword_from); std::string table_name = lexer.consumeCurrentToken().token_string; std::unique_ptr where_node = parse_where_clause(); // if (lexer.tokenType() == TokenType::keyword_order_by) {} // if (lexer.tokenType() == TokenType::keyword_offset) {} // if (lexer.tokenType() == TokenType::keyword_limit) {} return std::make_unique(table_name, cols_names, std::move(where_node)); } std::unique_ptr Parser::parse_delete_from_table() { lexer.skipToken(TokenType::keyword_delete); lexer.skipToken(TokenType::keyword_from); std::string table_name = lexer.consumeCurrentToken().token_string; std::unique_ptr where_node = parse_where_clause(); return std::make_unique(table_name, std::move(where_node)); } std::unique_ptr Parser::parse_update_table() { lexer.skipToken(TokenType::keyword_update); lexer.skipTokenOptional(TokenType::keyword_table); std::string table_name = lexer.consumeCurrentToken().token_string; lexer.skipToken(TokenType::keyword_set); std::vector cols_names; std::vector> values; do { cols_names.push_back(lexer.consumeCurrentToken().token_string); lexer.skipToken(TokenType::equal); std::unique_ptr left = Parser::parse_operand_node(); if (Lexer::isArithmeticalOperator(lexer.tokenType())) { ArithmeticalOperatorType op = parse_arithmetical_operator(); std::unique_ptr right = Parser::parse_operand_node(); values.push_back(std::make_unique(op, std::move(left), std::move(right))); } else { std::unique_ptr right = std::make_unique(0); values.push_back( std::make_unique(ArithmeticalOperatorType::copy_value, std::move(left), std::move(right))); } lexer.skipTokenOptional(TokenType::comma); } while (lexer.tokenType() != TokenType::keyword_where && lexer.tokenType() != TokenType::eof); std::unique_ptr where_node = parse_where_clause(); return std::make_unique(table_name, cols_names, std::move(values), std::move(where_node)); } std::unique_ptr Parser::parse_load_table() { lexer.skipToken(TokenType::keyword_load); lexer.skipTokenOptional(TokenType::keyword_into); std::string table_name = lexer.consumeCurrentToken().token_string; lexer.skipTokenOptional(TokenType::keyword_from); std::string file_name = lexer.consumeCurrentToken().token_string; return std::make_unique(table_name, file_name); } std::unique_ptr Parser::parse_where_clause() { // TODO add support for multiple filters // TODO add support for parenthesis if (lexer.tokenType() != TokenType::keyword_where) { return std::make_unique(); } std::unique_ptr node; lexer.skipToken(TokenType::keyword_where); do { node = parse_relational_expression(); if (Lexer::isLogicalOperator(lexer.tokenType())) { auto operation = parse_logical_operator(); std::unique_ptr node2 = parse_relational_expression(); node = std::make_unique(operation, std::move(node), std::move(node2)); } } while (lexer.tokenType() != TokenType::eof); // until whole where clause parsed return node; } std::unique_ptr Parser::parse_relational_expression() { auto left = parse_operand_node(); auto operation = parse_relational_operator(); auto right = parse_operand_node(); return std::make_unique(operation, std::move(left), std::move(right)); } std::unique_ptr Parser::parse_operand_node() { // while not end or order or limit auto token_type = lexer.tokenType(); std::string tokenString = lexer.consumeCurrentToken().token_string; switch (token_type) { case TokenType::int_number: return std::make_unique(std::stoi(tokenString)); case TokenType::double_number: return std::make_unique(std::stod(tokenString)); case TokenType::string_literal: return std::make_unique(tokenString); case TokenType::identifier: return std::make_unique(tokenString); default:; throw Exception("Unknown operand node"); } } RelationalOperatorType Parser::parse_relational_operator() { auto op = lexer.consumeCurrentToken(); switch (op.type) { case TokenType::equal: return RelationalOperatorType::equal; case TokenType::not_equal: return RelationalOperatorType::not_equal; case TokenType::greater: return RelationalOperatorType::greater; case TokenType::greater_equal: return RelationalOperatorType::greater_equal; case TokenType::lesser: return RelationalOperatorType::lesser; case TokenType::lesser_equal: return RelationalOperatorType::lesser_equal; default: throw Exception("Unknown relational operator"); } } LogicalOperatorType Parser::parse_logical_operator() { auto op = lexer.consumeCurrentToken(); switch (op.type) { case TokenType::logical_and: return LogicalOperatorType::and_operator; case TokenType::logical_or: return LogicalOperatorType::or_operator; default: throw Exception("Unknown logical operator"); } } ArithmeticalOperatorType Parser::parse_arithmetical_operator() { auto op = lexer.consumeCurrentToken(); switch (op.type) { case TokenType::plus: return ArithmeticalOperatorType::plus_operator; case TokenType::minus: return ArithmeticalOperatorType::minus_operator; case TokenType::multiply: return ArithmeticalOperatorType::multiply_operator; case TokenType::divide: return ArithmeticalOperatorType::divide_operator; default: throw Exception("Unknown arithmetical operator"); } } }