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:
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