commit 7f625eba293c4ec33fbd63a8dae9d585fd3bde2d
parent 3ed7b5866ce740ea5f3a1eb538071fb555442f3e
Author: bain3 <31798786+bain3@users.noreply.github.com>
Date: Fri, 30 Apr 2021 23:50:48 +0200
Switch to unique pointers
Diffstat:
4 files changed, 73 insertions(+), 46 deletions(-)
diff --git a/lexer/handlers.cpp b/lexer/handlers.cpp
@@ -12,7 +12,7 @@ int lexer::handlers::single_char(const lexer::GrammarRule &rule, lexer::Token &t
int lexer::handlers::multi_char(const GrammarRule &rule, Token &token, const std::string &input) {
if (input.length() >= rule.definition.length()) {
- std::string sub = input.substr(rule.definition.length());
+ std::string sub = input.substr(0, rule.definition.length());
if (sub == rule.definition) {
token.type = rule.type;
token.value = sub;
diff --git a/main.cpp b/main.cpp
@@ -8,28 +8,43 @@ std::string tab(const int &deep) {
return o;
}
-void print_expression(parser::elements::Expression* expression, int deep) {
+void print_expression(const std::unique_ptr<parser::elements::Expression> &expression, int deep) {
using namespace parser;
- std::cout << tab(deep);
- for (parser::elements::ParserElement* e : expression->children) {
- std::cout << e->type << " ";
+ 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;
+ break;
+ }
+ default:
+ std::cout << tab(deep) << "element of type " << e->type << std::endl;
+ }
}
- std::cout << std::endl;
}
-void print_statement(parser::elements::Statement* statement, int deep) {
+void print_statement(const std::unique_ptr<parser::elements::Statement> &statement, int deep) {
using namespace parser;
- for (parser::elements::ParserElement* e : statement->children) {
+ for (std::unique_ptr<elements::ParserElement> &e : statement->children) {
switch (e->type) {
case parser::DECLARATION: {
- auto* declaration = (elements::Declaration*)e;
- std::cout << tab(deep) << "declaring " << declaration->name << " as " << declaration->data_type << std::endl;
+ 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;
+ 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;
}
default:
@@ -38,7 +53,7 @@ void print_statement(parser::elements::Statement* statement, int deep) {
}
}
void print_block(const parser::elements::Block &block, const int &deep) {
- for (parser::elements::Statement* e : block.children) {
+ 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;
@@ -53,11 +68,12 @@ int main() {
{.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](?:.[0-9])?)", .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 = 0; print i;");
+ std::vector<lexer::Token> out = lxr.tokenize("int i = 120;");
for (const lexer::Token& token : out) {
std::cout << token.type << ": " << token.value << std::endl;
}
diff --git a/parser/parser.cpp b/parser/parser.cpp
@@ -36,8 +36,7 @@ parser::elements::Block parser::parse_block(const std::vector<lexer::Token> &tok
lexer::Token token = token_stream[consumed];
switch (token.type) {
case lexer::SEMICOLON: {
- elements::Statement st = parse_statement(statement_tokens);
- block.children.push_back(&st);
+ block.children.push_back(std::unique_ptr<elements::Statement>(parse_statement(statement_tokens)));
statement_tokens.clear();
break;
}
@@ -47,8 +46,7 @@ parser::elements::Block parser::parse_block(const std::vector<lexer::Token> &tok
break;
case lexer::RIGHT_BRACKET:
if (!brackets) {
- elements::Statement st = parse_statement(statement_tokens);
- block.children.push_back(&st);
+ block.children.push_back(std::unique_ptr<elements::Statement>(parse_statement(statement_tokens)));
statement_tokens.clear();
}
break;
@@ -60,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;
- elements::Statement statement;
+ auto* statement = new elements::Statement;
if (token_stream.empty()) {
return statement;
}
@@ -79,12 +77,11 @@ parser::elements::Statement parser::parse_statement(const std::vector<lexer::Tok
if (token_stream.size() < consumed+3) {
error("Nothing to assign.", reconstruct_code(token_stream));
}
- elements::Expression exp = parse_expression(token_stream, consumed+2);
- elements::Assignment assignment {
+ auto* assignment = new elements::Assignment {
.name = token.value,
- .value = exp,
+ .value = std::unique_ptr<elements::Expression>(parse_expression(token_stream, consumed+2)),
};
- statement.children.push_back(&assignment);
+ statement->children.push_back(std::unique_ptr<elements::ParserElement>((elements::ParserElement*)assignment));
break;
}
default:
@@ -98,13 +95,15 @@ parser::elements::Statement parser::parse_statement(const std::vector<lexer::Tok
} else if (token_stream[consumed+1].type != lexer::TokenType::NAME) {
error("Can only declare names.", reconstruct_code(token_stream));
}
- elements::Declaration declaration {
+ auto* declaration = new elements::Declaration {
.name = token_stream[consumed+1].value,
.data_type = INT
};
- statement.children.push_back(&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::LEFT_BRACKET:
@@ -117,8 +116,15 @@ parser::elements::Statement parser::parse_statement(const std::vector<lexer::Tok
return statement;
}
-parser::elements::Expression parser::parse_expression(const std::vector<lexer::Token> &token_stream, int start_at) {
-
- return parser::elements::Expression();
+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)));
+ }
+ return expression;
}
diff --git a/parser/parser.h b/parser/parser.h
@@ -3,10 +3,12 @@
#define SHITSHOW_PARSER_H
#include <string>
#include <vector>
+#include <memory>
#include "../lexer/lexer.h"
namespace parser {
enum ParserElementType {
+ NONE,
BLOCK,
EXPRESSION,
STATEMENT,
@@ -22,51 +24,54 @@ namespace parser {
STRING
};
namespace elements {
- struct ParserElement { ParserElementType type; };
- struct Expression : ParserElement {
+ struct ParserElement {
+ ParserElementType type = NONE;
+ };
+ struct Expression {
ParserElementType type = EXPRESSION;
// TODO: memory leaks?
- std::vector<ParserElement*> children;
+ std::vector<std::unique_ptr<ParserElement>> children;
};
- struct Statement : Expression {
+ struct Statement {
ParserElementType type = STATEMENT;
+ std::vector<std::unique_ptr<ParserElement>> children;
};
- struct Block : ParserElement {
+ struct Block {
ParserElementType type = BLOCK;
// TODO: memory leaks?
- std::vector<Statement*> children;
+ std::vector<std::unique_ptr<Statement>> children;
};
- struct Declaration : ParserElement {
+ struct Declaration {
ParserElementType type = DECLARATION;
std::string name;
DataType data_type;
};
- struct Assignment : ParserElement {
+ struct Assignment {
ParserElementType type = ASSIGNMENT;
std::string name;
- Expression value;
+ std::unique_ptr<Expression> value;
};
- struct ConstDefine : ParserElement {
+ struct ConstDefine {
ParserElementType type = CONST_DEFINE;
DataType data_type;
std::string value;
};
- struct Call : ParserElement {
+ struct Call {
ParserElementType type = CALL;
std::string name;
};
- struct Name : ParserElement {
+ struct Name {
ParserElementType type = NAME;
std::string name;
};
- struct Print : ParserElement {
+ struct Print {
ParserElementType type = PRINT;
ParserElement 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