shitshow

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

commit cad7e07fadfb554b4d3f273fc2792f938d4b7d1d
parent 4b8d1cecbde28562f062eb67b594bdbb723c58c7
Author: bain3 <31798786+bain3@users.noreply.github.com>
Date:   Sun,  9 May 2021 14:31:40 +0200

Finish parser, add while loop and support for parentheses

Diffstat:
Mlexer/lexer.h | 2+-
Mmain.cpp | 156++++----------------------------------------------------------------------------
Mparser/parser.cpp | 104+++++++++++++++++++++++++++++++++++++------------------------------------------
Mparser/parser_elements.h | 7++++++-
Aparser/print_stuff.h | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 237 insertions(+), 207 deletions(-)

diff --git a/lexer/lexer.h b/lexer/lexer.h @@ -18,7 +18,7 @@ namespace lexer { RIGHT_PARENT, LEFT_BRACKET, RIGHT_BRACKET, - IF, EQ, ARITHMETIC + IF, EQ, ARITHMETIC, WHILE }; enum HandlerType { SINGLE_CHAR, diff --git a/main.cpp b/main.cpp @@ -1,152 +1,7 @@ #include <iostream> #include "lexer/lexer.h" #include "parser/parser.h" - -void print_block(parser::elements::Block *block, const int &deep); - -std::string tab(const int &deep) { - std::string o; - for (int i = 0; i < deep; i++) o += " "; - return o; -} - -void print_name_or_const(parser::elements::ParserElement *el, int deep) { - if (el->type == parser::ParserElementType::CONST_DEFINE) { - auto *constant = (parser::elements::ConstDefine *) el; - std::cout << tab(deep) << "constant " - << (constant->data_type == parser::DataType::INT ? "int: " : "string: ") - << constant->value << std::endl; - } else if (el->type == parser::ParserElementType::NAME) { - auto *name = (parser::elements::Name *) el; - std::cout << tab(deep) << "name " << name->name << std::endl; - } else { - std::cout << tab(deep) << "not name or const!" << std::endl; - } -} - -void print_operation(parser::elements::Arithmetic *arithmetic, int deep) { - std::cout << tab(deep); - switch (arithmetic->specific_type) { - case parser::ADD: - std::cout << "addition"; - break; - case parser::SUBTRACT: - std::cout << "subtraction"; - break; - case parser::DIVIDE: - std::cout << "division"; - break; - case parser::MULTIPLY: - std::cout << "multiplication"; - break; - } - std::cout << std::endl; - switch (arithmetic->left->type) { - case parser::CONST_DEFINE: - case parser::NAME: - print_name_or_const(arithmetic->left.get(), deep + 4); - break; - case parser::ARITHMETIC: - print_operation((parser::elements::Arithmetic *) arithmetic->left.get(), deep + 4); - break; - default: - std::cout << tab(deep + 4) << "element of type " << arithmetic->left->type << std::endl; - } - switch (arithmetic->right->type) { - case parser::CONST_DEFINE: - case parser::NAME: - print_name_or_const(arithmetic->right.get(), deep + 4); - break; - case parser::ARITHMETIC: - print_operation((parser::elements::Arithmetic *) arithmetic->right.get(), deep + 4); - break; - default: - std::cout << tab(deep + 4) << "element of type " << arithmetic->right->type << std::endl; - } -} - -void print_expression(const std::unique_ptr<parser::elements::Expression> &expression, int deep) { - using namespace parser; - for (const std::unique_ptr<elements::ParserElement> &e : expression->children) { - switch (e->type) { - case parser::COMPARE: { - auto *compare = (elements::Compare *) e.get(); - std::cout << tab(deep) << "compare of type " << compare->specific_type << std::endl; - break; - } - case parser::NAME: - case parser::CONST_DEFINE: { - print_name_or_const(e.get(), deep); - break; - } - case parser::ARITHMETIC: { - auto *arithmetic = (elements::Arithmetic *) e.get(); - print_operation(arithmetic, deep); - break; - } - default: - std::cout << tab(deep) << "element of type " << e->type << std::endl; - } - } -} - -void print_statement(const std::unique_ptr<parser::elements::Statement> &statement, int deep) { - using namespace parser; - for (std::unique_ptr<elements::ParserElement> &e : statement->children) { - switch (e->type) { - case parser::BLOCK: { - auto *block = (elements::Block *) e.get(); - print_block(block, deep); - break; - } - case parser::DECLARATION: { - auto *declaration = (elements::Declaration *) e.get(); - std::cout << tab(deep) << "declaring " << declaration->name << " as "; - switch (declaration->data_type) { - case INT: - std::cout << "int"; - break; - case STRING: - std::cout << "string"; - break; - } - std::cout << std::endl; - break; - } - case parser::ASSIGNMENT: { - auto *assignment = (elements::Assignment *) e.get(); - std::cout << tab(deep) << "assigning " << assignment->name << " to " << std::endl; - 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; - } - case parser::IF: { - auto *if_ = (elements::If *) e.get(); - std::cout << tab(deep) << "if condition" << std::endl; - print_expression(if_->expression, deep + 4); - std::cout << tab(deep) << "end condition" << std::endl; - break; - } - default: - std::cout << tab(deep) << "doing " << e->type << std::endl; - } - } -} - -void print_block(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 + 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; -} +#include "parser/print_stuff.h" int main() { lexer::Lexer lxr({ @@ -165,10 +20,11 @@ int main() { lxr.reserved = { {lexer::TokenType::TYPE, {"int", "char"}}, {lexer::TokenType::PRINT, {"print"}}, - {lexer::TokenType::IF, {"if"}} + {lexer::TokenType::IF, {"if"}}, + {lexer::TokenType::WHILE, {"while"}} }; std::vector<lexer::Token> out = lxr.tokenize( - "int integer = 120 + 2 - 1/2; print asdfa; if (integer == 2) {print \"hii\";}"); + "int integer = 120 + 2 - 1/2; print asdfa; if (integer == 2) {while (1) print \"hii\";}"); lxr.convert_reserved(out); for (const lexer::Token &token : out) { std::cout << token.value << " "; @@ -176,7 +32,7 @@ int main() { std::cout << std::endl; int offset = 0; for (const lexer::Token &token : out) { - std::cout << tab(offset) << token.type; + std::cout << parser_print::tab(offset) << token.type; int num = token.type; int digits = num == 0; while (num > 0) { @@ -187,5 +43,5 @@ int main() { } std::cout << std::endl << std::endl; parser::elements::Block *parsed = parser::parse_block(out, 0); - print_block(parsed, 0); + parser_print::print_block(parsed, 0); } diff --git a/parser/parser.cpp b/parser/parser.cpp @@ -142,6 +142,7 @@ parser::elements::Statement *parser::parse_statement(const std::vector<lexer::To }; break; } + case lexer::WHILE: case lexer::IF: { if (stream_size < consumed + 2 || token_stream[consumed + 1].type != lexer::LEFT_PARENT) { error("STMT3: Expected (, found: " + token.value, reconstruct_code(token_stream)); @@ -151,7 +152,11 @@ parser::elements::Statement *parser::parse_statement(const std::vector<lexer::To error("STMT2: Could not find matching ) for (", reconstruct_code(token_stream)); } std::unique_ptr<elements::Expression> expr(parse_expression(token_stream, consumed + 2, closing_pos)); - parser_element = (elements::ParserElement *) new elements::If{.expression = std::move(expr)}; + if (token.type == lexer::IF) { + parser_element = (elements::ParserElement *) new elements::If{.expression = std::move(expr)}; + } else { + parser_element = (elements::ParserElement *) new elements::While{.expression = std::move(expr)}; + } consumed = closing_pos + 1; stop = false; // we want the block that is following (or command) break; @@ -173,6 +178,38 @@ parser::elements::Statement *parser::parse_statement(const std::vector<lexer::To return statement; } +void +resolve_arithmetic(parser::elements::Expression *expression, parser::ArithmeticTypes t1, parser::ArithmeticTypes t2, + const std::vector<lexer::Token> &token_stream) { + for (bool stop = false; !stop;) { + stop = true; + auto end = expression->children.end(); + auto begin = expression->children.begin(); + for (auto i = expression->children.begin(); + i != expression->children.end(); i++) { // NOLINT(cppcoreguidelines-narrowing-conversions) + if ((*i)->type == parser::ARITHMETIC) { + auto *c = (parser::elements::Arithmetic *) i->get(); + if (c->left != nullptr || c->right != nullptr || + (c->specific_type != t1 && c->specific_type != t2)) + continue; + if (std::distance(begin, i) <= 0 || std::distance(end, i) <= 0) {// || std::distance(end, i) >= 0) { + std::cout << std::distance(end, i) << std::endl; + error("ROP1: Missing operands!", reconstruct_code(token_stream)); + } + c->left = std::move(*(--i)); + auto first = i; + i++; + i++; + c->right = std::move(*i); + expression->children.erase(i); + expression->children.erase(first); + stop = false; + break; + } + } + } +} + parser::elements::Expression * parser::parse_expression(const std::vector<lexer::Token> &token_stream, int start_at, int end_at) { auto *expression = new parser::elements::Expression; @@ -207,6 +244,15 @@ parser::parse_expression(const std::vector<lexer::Token> &token_stream, int star el = (elements::ParserElement *) new parser::elements::Arithmetic{.specific_type=t}; break; } + case lexer::LEFT_PARENT: { + int match = find_matching(token_stream, i+1, lexer::LEFT_PARENT); + if (match == -1) { + error("EXP4: Cannot find matching parenthesis.", reconstruct_code(token_stream)); + } + el = (elements::ParserElement*) parse_expression(token_stream, i+1, match); + i = match; + break; + } default: el = new parser::elements::ParserElement{}; error("EXP1: Token " + token.value + " unexpected at this point", reconstruct_code(token_stream)); @@ -216,62 +262,10 @@ parser::parse_expression(const std::vector<lexer::Token> &token_stream, int star } // resolve multiplication and division - for (bool stop = false; !stop;) { - stop = true; - auto end = expression->children.end(); - auto begin = expression->children.begin(); - for (auto i = expression->children.begin(); - i != expression->children.end(); i++) { // NOLINT(cppcoreguidelines-narrowing-conversions) - if ((*i)->type == ARITHMETIC) { - auto *c = (elements::Arithmetic *) i->get(); - if (c->left != nullptr || c->right != nullptr || - (c->specific_type != MULTIPLY && c->specific_type != DIVIDE)) - continue; - if (std::distance(begin, i) <= 0 || std::distance(end, i) <= 0) {// || std::distance(end, i) >= 0) { - std::cout << std::distance(end, i) << std::endl; - error("ROP1: Missing operands!", reconstruct_code(token_stream)); - } - c->left = std::move(*(--i)); - auto first = i; - i++; - i++; - c->right = std::move(*i); - expression->children.erase(i); - expression->children.erase(first); - stop = false; - break; - } - } - } + resolve_arithmetic(expression, MULTIPLY, DIVIDE, token_stream); // resolve addition and subtraction - for (bool stop = false; !stop;) { - stop = true; - auto end = expression->children.end(); - auto begin = expression->children.begin(); - for (auto i = expression->children.begin(); - i != expression->children.end(); i++) { // NOLINT(cppcoreguidelines-narrowing-conversions) - if ((*i)->type == ARITHMETIC) { - auto *c = (elements::Arithmetic *) i->get(); - if (c->left != nullptr || c->right != nullptr || - (c->specific_type != ADD && c->specific_type != SUBTRACT)) - continue; - if (std::distance(begin, i) <= 0 || std::distance(end, i) <= 0) {// || std::distance(end, i) >= 0) { - std::cout << std::distance(end, i) << std::endl; - error("ROP1: Missing operands!", reconstruct_code(token_stream)); - } - c->left = std::move(*(--i)); - auto first = i; - i++; - i++; - c->right = std::move(*i); - expression->children.erase(i); - expression->children.erase(first); - stop = false; - break; - } - } - } + resolve_arithmetic(expression, ADD, SUBTRACT, token_stream); // resolve comparisons for (bool stop = false; !stop;) { diff --git a/parser/parser_elements.h b/parser/parser_elements.h @@ -19,7 +19,8 @@ namespace parser { CALL, COMPARE, IF, - ARITHMETIC + ARITHMETIC, + WHILE }; enum DataType { INT, @@ -90,6 +91,10 @@ namespace parser { ParserElementType type = IF; std::unique_ptr<Expression> expression; }; + struct While { + ParserElementType type = WHILE; + std::unique_ptr<Expression> expression; + }; } } #endif //SHITSHOW_PARSER_ELEMENTS_H diff --git a/parser/print_stuff.h b/parser/print_stuff.h @@ -0,0 +1,175 @@ +// +// Created by bain on 08.05.21. +// + +#ifndef SHITSHOW_PRINT_STUFF_H +#define SHITSHOW_PRINT_STUFF_H +#include "parser.h" + +namespace parser_print { + void print_block(parser::elements::Block *block, const int &deep); + void print_expression(parser::elements::Expression *expression, int deep); + + std::string tab(const int &deep) { + std::string o; + for (int i = 0; i < deep; i++) o += " "; + return o; + } + + void print_name_or_const(parser::elements::ParserElement *el, int deep) { + if (el->type == parser::ParserElementType::CONST_DEFINE) { + auto *constant = (parser::elements::ConstDefine *) el; + std::cout << tab(deep) << "constant " + << (constant->data_type == parser::DataType::INT ? "int: " : "string: ") + << constant->value << std::endl; + } else if (el->type == parser::ParserElementType::NAME) { + auto *name = (parser::elements::Name *) el; + std::cout << tab(deep) << "name " << name->name << std::endl; + } else { + std::cout << tab(deep) << "not name or const!" << std::endl; + } + } + + void print_operation(parser::elements::Arithmetic *arithmetic, int deep) { + std::cout << tab(deep); + switch (arithmetic->specific_type) { + case parser::ADD: + std::cout << "addition"; + break; + case parser::SUBTRACT: + std::cout << "subtraction"; + break; + case parser::DIVIDE: + std::cout << "division"; + break; + case parser::MULTIPLY: + std::cout << "multiplication"; + break; + } + std::cout << std::endl; + switch (arithmetic->left->type) { + case parser::CONST_DEFINE: + case parser::NAME: + print_name_or_const(arithmetic->left.get(), deep + 4); + break; + case parser::ARITHMETIC: + print_operation((parser::elements::Arithmetic *) arithmetic->left.get(), deep + 4); + break; + case parser::EXPRESSION: + print_expression((parser::elements::Expression *) arithmetic->left.get(), deep+4); + break; + default: + std::cout << tab(deep + 4) << "element of type " << arithmetic->left->type << std::endl; + } + switch (arithmetic->right->type) { + case parser::CONST_DEFINE: + case parser::NAME: + print_name_or_const(arithmetic->right.get(), deep + 4); + break; + case parser::ARITHMETIC: + print_operation((parser::elements::Arithmetic *) arithmetic->right.get(), deep + 4); + break; + case parser::EXPRESSION: + print_expression((parser::elements::Expression *) arithmetic->left.get(), deep+4); + break; + default: + std::cout << tab(deep + 4) << "element of type " << arithmetic->right->type << std::endl; + } + } + + void print_expression(parser::elements::Expression *expression, int deep) { + using namespace parser; + for (const std::unique_ptr<elements::ParserElement> &e : expression->children) { + switch (e->type) { + case parser::COMPARE: { + auto *compare = (elements::Compare *) e.get(); + std::cout << tab(deep) << "compare of type " << compare->specific_type << std::endl; + break; + } + case parser::NAME: + case parser::CONST_DEFINE: { + print_name_or_const(e.get(), deep); + break; + } + case parser::ARITHMETIC: { + auto *arithmetic = (elements::Arithmetic *) e.get(); + print_operation(arithmetic, deep); + break; + } + case parser::EXPRESSION: { + auto *expr = (elements::Expression *) e.get(); + print_expression(expr, deep+4); + break; + } + default: + std::cout << tab(deep) << "element of type " << e->type << std::endl; + } + } + } + + void print_statement(const std::unique_ptr<parser::elements::Statement> &statement, int deep) { + using namespace parser; + for (std::unique_ptr<elements::ParserElement> &e : statement->children) { + switch (e->type) { + case parser::BLOCK: { + auto *block = (elements::Block *) e.get(); + print_block(block, deep); + break; + } + case parser::DECLARATION: { + auto *declaration = (elements::Declaration *) e.get(); + std::cout << tab(deep) << "declaring " << declaration->name << " as "; + switch (declaration->data_type) { + case INT: + std::cout << "int"; + break; + case STRING: + std::cout << "string"; + break; + } + std::cout << std::endl; + break; + } + case parser::ASSIGNMENT: { + auto *assignment = (elements::Assignment *) e.get(); + std::cout << tab(deep) << "assigning " << assignment->name << " to " << std::endl; + print_expression(assignment->value.get(), deep + 4); + break; + } + case parser::PRINT: { + auto *print = (elements::Print *) e.get(); + std::cout << tab(deep) << "printing" << std::endl; + print_expression(print->value.get(), deep + 4); + break; + } + case parser::IF: { + auto *if_ = (elements::If *) e.get(); + std::cout << tab(deep) << "if condition" << std::endl; + print_expression(if_->expression.get(), deep + 4); + std::cout << tab(deep) << "end condition" << std::endl; + break; + } + case parser::WHILE: { + auto *while_ = (elements::While *) e.get(); + std::cout << tab(deep) << "while condition" << std::endl; + print_expression(while_->expression.get(), deep + 4); + std::cout << tab(deep) << "end condition" << std::endl; + break; + } + default: + std::cout << tab(deep) << "doing " << e->type << std::endl; + } + } + } + + void print_block(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 + 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; + } +} +#endif //SHITSHOW_PRINT_STUFF_H