shitshow

A shitty programming language
git clone git://git.bain.cz/shitshow.git
Log | Files | Refs

commit 4cfbabbce597dbbabab0a80ee589ccef71a76e6c
parent 7f625eba293c4ec33fbd63a8dae9d585fd3bde2d
Author: bain3 <31798786+bain3@users.noreply.github.com>
Date:   Sat,  1 May 2021 00:21:36 +0200

Add parsing of print statement

Diffstat:
Mmain.cpp | 60++++++++++++++++++++++++++++++++++++++----------------------
Mparser/parser.cpp | 79++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mparser/parser.h | 10+++++++---
3 files changed, 97 insertions(+), 52 deletions(-)

diff --git a/main.cpp b/main.cpp @@ -4,7 +4,7 @@ std::string tab(const int &deep) { std::string o; - for (int i = 0; i < deep; i++) o+=" "; + for (int i = 0; i < deep; i++) o += " "; return o; } @@ -13,8 +13,14 @@ void print_expression(const std::unique_ptr<parser::elements::Expression> &expre for (const std::unique_ptr<elements::ParserElement> &e : expression->children) { switch (e->type) { case parser::CONST_DEFINE: { - auto* constant = (elements::ConstDefine*)e.get(); - std::cout << tab(deep) << "constant " << constant->value << std::endl; + auto *constant = (elements::ConstDefine *) e.get(); + std::cout << tab(deep) << "constant " << (constant->data_type == INT ? "int: " : "string: ") + << constant->value << std::endl; + break; + } + case parser::NAME: { + auto *name = (elements::Name *) e.get(); + std::cout << tab(deep) << "name " << name->name << std::endl; break; } default: @@ -28,7 +34,7 @@ void print_statement(const std::unique_ptr<parser::elements::Statement> &stateme for (std::unique_ptr<elements::ParserElement> &e : statement->children) { switch (e->type) { case parser::DECLARATION: { - auto* declaration = (elements::Declaration*)e.get(); + auto *declaration = (elements::Declaration *) e.get(); std::cout << tab(deep) << "declaring " << declaration->name << " as "; switch (declaration->data_type) { case INT: @@ -42,9 +48,15 @@ void print_statement(const std::unique_ptr<parser::elements::Statement> &stateme break; } case parser::ASSIGNMENT: { - auto* assignment = (elements::Assignment*)e.get(); + auto *assignment = (elements::Assignment *) e.get(); std::cout << tab(deep) << "assigning " << assignment->name << " to " << std::endl; - print_expression(assignment->value, deep+4); + print_expression(assignment->value, deep + 4); + break; + } + case parser::PRINT: { + auto *print = (elements::Print *) e.get(); + std::cout << tab(deep) << "printing" << std::endl; + print_expression(print->value, deep + 4); break; } default: @@ -52,29 +64,33 @@ void print_statement(const std::unique_ptr<parser::elements::Statement> &stateme } } } + void print_block(const parser::elements::Block &block, const int &deep) { + std::cout << tab(deep) << "block begin" << std::endl; for (const std::unique_ptr<parser::elements::Statement> &e : block.children) { - std::cout << tab(deep) << "statement begin" << std::endl; - print_statement(e, deep+4); - std::cout << tab(deep) << "statement end" << std::endl; + std::cout << tab(deep + 4) << "statement begin" << std::endl; + print_statement(e, deep + 8); + std::cout << tab(deep + 4) << "statement end" << std::endl; } + std::cout << tab(deep) << "block end" << std::endl; } int main() { lexer::Lexer lxr({ - {.type=lexer::TokenType::SEMICOLON, .definition=";", .handler=lexer::HandlerType::SINGLE_CHAR}, - {.type=lexer::TokenType::ASSIGNMENT, .definition="=", .handler=lexer::HandlerType::SINGLE_CHAR}, - {.type=lexer::TokenType::LEFT_PARENT, .definition="(", .handler=lexer::HandlerType::SINGLE_CHAR}, - {.type=lexer::TokenType::RIGHT_PARENT, .definition=")", .handler=lexer::HandlerType::SINGLE_CHAR}, - {.type=lexer::TokenType::LEFT_BRACKET, .definition="{", .handler=lexer::HandlerType::SINGLE_CHAR}, - {.type=lexer::TokenType::RIGHT_BRACKET, .definition="}", .handler=lexer::HandlerType::SINGLE_CHAR}, - {.type=lexer::TokenType::TYPE_INT, .definition="int", .handler=lexer::HandlerType::MULTI_CHAR}, - {.type=lexer::TokenType::NAME, .definition=R"([A-Za-z_](?:[\w]+)?)", .handler=lexer::HandlerType::REGEX}, - {.type=lexer::TokenType::NUMBER_LITERAL, .definition=R"([0-9]+)", .handler=lexer::HandlerType::REGEX}, - {.type=lexer::TokenType::STRING_LITERAL, .handler=lexer::HandlerType::STRING} - }); - std::vector<lexer::Token> out = lxr.tokenize("int i = 120;"); - for (const lexer::Token& token : out) { + {.type=lexer::TokenType::SEMICOLON, .definition=";", .handler=lexer::HandlerType::SINGLE_CHAR}, + {.type=lexer::TokenType::ASSIGNMENT, .definition="=", .handler=lexer::HandlerType::SINGLE_CHAR}, + {.type=lexer::TokenType::LEFT_PARENT, .definition="(", .handler=lexer::HandlerType::SINGLE_CHAR}, + {.type=lexer::TokenType::RIGHT_PARENT, .definition=")", .handler=lexer::HandlerType::SINGLE_CHAR}, + {.type=lexer::TokenType::LEFT_BRACKET, .definition="{", .handler=lexer::HandlerType::SINGLE_CHAR}, + {.type=lexer::TokenType::RIGHT_BRACKET, .definition="}", .handler=lexer::HandlerType::SINGLE_CHAR}, + {.type=lexer::TokenType::TYPE_INT, .definition="int", .handler=lexer::HandlerType::MULTI_CHAR}, + {.type=lexer::TokenType::PRINT, .definition="print", .handler=lexer::HandlerType::MULTI_CHAR}, + {.type=lexer::TokenType::NAME, .definition=R"([A-Za-z_](?:[\w]+)?)", .handler=lexer::HandlerType::REGEX}, + {.type=lexer::TokenType::NUMBER_LITERAL, .definition=R"([0-9]+)", .handler=lexer::HandlerType::REGEX}, + {.type=lexer::TokenType::STRING_LITERAL, .handler=lexer::HandlerType::STRING} + }); + std::vector<lexer::Token> out = lxr.tokenize("int i = 120; print \"asdfa\";"); + for (const lexer::Token &token : out) { std::cout << token.type << ": " << token.value << std::endl; } parser::elements::Block parsed = parser::parse_block(out, 0); diff --git a/parser/parser.cpp b/parser/parser.cpp @@ -2,7 +2,7 @@ #include "parser.h" #include <iostream> -void error(const std::string& msg) { +void error(const std::string &msg) { std::cerr << "Error while parsing:" << std::endl << msg << std::endl; std::exit(1); } @@ -16,12 +16,12 @@ void error(const std::string &msg, const std::string &linectx) { void error(const std::string &msg, const std::string &linectx, const int &column) { std::cerr << "Error while parsing:" << std::endl << msg << std::endl; std::cerr << " " << linectx << std::endl; - for (int i = 0; i < column+4; i++) std::cerr << " "; + for (int i = 0; i < column + 4; i++) std::cerr << " "; std::cerr << std::endl; std::exit(1); } -std::string reconstruct_code(const std::vector<lexer::Token>& tokens) { +std::string reconstruct_code(const std::vector<lexer::Token> &tokens) { std::string output; for (const auto &token : tokens) output += token.value + " "; return output; @@ -58,9 +58,9 @@ parser::elements::Block parser::parse_block(const std::vector<lexer::Token> &tok return block; } -parser::elements::Statement* parser::parse_statement(const std::vector<lexer::Token> &token_stream) { +parser::elements::Statement *parser::parse_statement(const std::vector<lexer::Token> &token_stream) { int consumed = 0; - auto* statement = new elements::Statement; + auto *statement = new elements::Statement; if (token_stream.empty()) { return statement; } @@ -68,44 +68,57 @@ parser::elements::Statement* parser::parse_statement(const std::vector<lexer::To lexer::Token token = token_stream[consumed]; switch (token.type) { case lexer::NAME: { - if (token_stream.size() < consumed+2) { + if (token_stream.size() < consumed + 2) { return statement; } - lexer::Token token2 = token_stream[consumed+1]; + lexer::Token token2 = token_stream[consumed + 1]; switch (token2.type) { case lexer::ASSIGNMENT: { - if (token_stream.size() < consumed+3) { + if (token_stream.size() < consumed + 3) { error("Nothing to assign.", reconstruct_code(token_stream)); } - auto* assignment = new elements::Assignment { + auto *assignment = new elements::Assignment{ .name = token.value, - .value = std::unique_ptr<elements::Expression>(parse_expression(token_stream, consumed+2)), + .value = std::unique_ptr<elements::Expression>( + parse_expression(token_stream, consumed + 2)), }; - statement->children.push_back(std::unique_ptr<elements::ParserElement>((elements::ParserElement*)assignment)); + statement->children.push_back( + std::unique_ptr<elements::ParserElement>((elements::ParserElement *) assignment)); break; } default: - error("Token: "+token2.value+" unexpected at this point.", reconstruct_code(token_stream)); + error("Token: " + token2.value + " unexpected at this point.", reconstruct_code(token_stream)); } break; } case lexer::TYPE_INT: { - if (token_stream.size() < consumed+3) { + if (token_stream.size() < consumed + 2) { error("What am I declaring? Missing name to declare.", reconstruct_code(token_stream)); - } else if (token_stream[consumed+1].type != lexer::TokenType::NAME) { + } else if (token_stream[consumed + 1].type != lexer::TokenType::NAME) { error("Can only declare names.", reconstruct_code(token_stream)); } - auto* declaration = new elements::Declaration { - .name = token_stream[consumed+1].value, + auto *declaration = new elements::Declaration{ + .name = token_stream[consumed + 1].value, .data_type = INT }; - statement->children.push_back(std::unique_ptr<elements::ParserElement>((elements::ParserElement*)declaration)); - if (token_stream.size() > consumed+2 && token_stream[consumed+2].type == lexer::ASSIGNMENT) { + statement->children.push_back( + std::unique_ptr<elements::ParserElement>((elements::ParserElement *) declaration)); + if (token_stream.size() > consumed + 2 && token_stream[consumed + 2].type == lexer::ASSIGNMENT) { consumed++; continue; // continue to run the main loop to get the assignment } } - case lexer::PRINT: + case lexer::PRINT: { + if (token_stream.size() < consumed + 2) { + error("What am I printing? Missing expression to print.", reconstruct_code(token_stream)); + } + std::unique_ptr<elements::Expression> expr(parse_expression(token_stream, consumed + 1)); + auto *print = new elements::Print{ + .value = std::move(expr) + }; + statement->children.push_back( + std::unique_ptr<elements::ParserElement>((elements::ParserElement *) print)); + } case lexer::LEFT_BRACKET: break; default: @@ -116,14 +129,26 @@ parser::elements::Statement* parser::parse_statement(const std::vector<lexer::To return statement; } -parser::elements::Expression* parser::parse_expression(const std::vector<lexer::Token> &token_stream, int start_at) { - auto* expression = new parser::elements::Expression; - if (token_stream[start_at].type == lexer::NUMBER_LITERAL) { - auto* number = new parser::elements::ConstDefine { - .data_type = INT, - .value = token_stream[start_at].value - }; - expression->children.push_back(std::unique_ptr<elements::ParserElement>((elements::ParserElement*)(number))); +parser::elements::Expression *parser::parse_expression(const std::vector<lexer::Token> &token_stream, int start_at) { + auto *expression = new parser::elements::Expression; + switch (token_stream[start_at].type) { + case lexer::STRING_LITERAL: + case lexer::NUMBER_LITERAL: { + auto *number = new parser::elements::ConstDefine{ + .data_type = token_stream[start_at].type == lexer::NUMBER_LITERAL ? INT : STRING, + .value = token_stream[start_at].value + }; + expression->children.push_back( + std::unique_ptr<elements::ParserElement>((elements::ParserElement *) number)); + break; + } + case lexer::NAME: { + auto *name = new parser::elements::Name{ + .name = token_stream[start_at].value + }; + expression->children.push_back(std::unique_ptr<elements::ParserElement>((elements::ParserElement *) name)); + break; + } } return expression; } diff --git a/parser/parser.h b/parser/parser.h @@ -1,6 +1,7 @@ #ifndef SHITSHOW_PARSER_H #define SHITSHOW_PARSER_H + #include <string> #include <vector> #include <memory> @@ -66,12 +67,15 @@ namespace parser { }; struct Print { ParserElementType type = PRINT; - ParserElement value; + std::unique_ptr<Expression> value; }; } + elements::Block parse_block(const std::vector<lexer::Token> &token_stream, int start_at); - elements::Statement* parse_statement(const std::vector<lexer::Token> &token_stream); - elements::Expression * parse_expression(const std::vector<lexer::Token> &token_stream, int start_at); + + elements::Statement *parse_statement(const std::vector<lexer::Token> &token_stream); + + elements::Expression *parse_expression(const std::vector<lexer::Token> &token_stream, int start_at); } #endif //SHITSHOW_PARSER_H