diff --git a/src/Expression.cpp b/src/Expression.cpp index e8c35f3..7d14064 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -1,14 +1,95 @@ #include "Expression.h" -ExpressionInvalid Expression::Invalid = ExpressionInvalid(); +std::shared_ptr Expression::Invalid = std::make_shared(Expression::Kind::INVALID, Token::Invalid, nullptr, nullptr); -std::string ExpressionInvalid::toString() { - return "Invalid"; +Expression::Expression(Kind kind, Token token, shared_ptr left, shared_ptr right) { + switch (kind) { + case LITERAL: + setupLiteral(token); + break; + case BINARY: + setupBinary(token, left, right); + break; + case INVALID: + break; + } } -/*ExpressionInteger::ExpressionInteger(Token token) { +void Expression::setupLiteral(Token token) { + bool isKindValid = token.isOneOf({Token::Kind::INTEGER}); + if (!isKindValid) + return; + + kind = LITERAL; + integer = stoi(token.getLexme()); } -std::string ExpressionInteger::toString() { - return "INTEGER"; -}*/ \ No newline at end of file +void Expression::setupBinary(Token token, shared_ptr left, shared_ptr right) { + bool isKindValid = token.isOneOf({Token::Kind::PLUS, Token::Kind::MINUS, Token::Kind::STAR, Token::Kind::SLASH, Token::Kind::PERCENT}); + bool isLeftValid = left != nullptr && left->getKind() != Kind::INVALID; + bool isRightValid = right != nullptr && right->getKind() != Kind::INVALID; + + if (!isKindValid || !isLeftValid || !isRightValid) + return; + + kind = BINARY; + + switch (token.getKind()) { + case Token::Kind::PLUS: + operation = ADD; + break; + case Token::Kind::MINUS: + operation = SUB; + break; + case Token::Kind::STAR: + operation = MUL; + break; + case Token::Kind::SLASH: + operation = DIV; + break; + case Token::Kind::PERCENT: + operation = MOD; + break; + case Token::Kind::INVALID: + break; + } + + this->left = left; + this->right = right; +} + +Expression::Kind Expression::getKind() { + return kind; +} + +bool Expression::operator==(Expression const& other) { + return kind == other.kind; +} + +bool Expression::operator!=(Expression const& other) { + return kind != other.kind; +} + +std::string Expression::toString() { + switch (kind) { + case LITERAL: + return to_string(integer); + case BINARY: + switch (operation) { + case ADD: + return "<+ " + left->toString() + " " + right->toString() + ">"; + case SUB: + return "<- " + left->toString() + " " + right->toString() + ">"; + case MUL: + return "<* " + left->toString() + " " + right->toString() + ">"; + case DIV: + return "toString() + " " + right->toString() + ">"; + case MOD: + return "<% " + left->toString() + " " + right->toString() + ">"; + case NONE: + return "NONE"; + } + case INVALID: + return "INVALID"; + } +} \ No newline at end of file diff --git a/src/Expression.h b/src/Expression.h index 5adc04b..d74ae7f 100644 --- a/src/Expression.h +++ b/src/Expression.h @@ -3,23 +3,43 @@ #include "Token.h" -class ExpressionInvalid; +using namespace std; class Expression { public: - static ExpressionInvalid Invalid; + enum Kind { + LITERAL, + BINARY, + INVALID + }; - virtual std::string toString() = 0; -}; + enum Operation { + ADD, + SUB, + MUL, + DIV, + MOD, + NONE + }; -class ExpressionInvalid { +private: + Kind kind = INVALID; + int64_t integer = 0; + Operation operation = NONE; + shared_ptr left = nullptr; + shared_ptr right = nullptr; -}; + void setupLiteral(Token token); + void setupBinary(Token token, shared_ptr left, shared_ptr right); -/*class ExpressionInteger: Expression { public: - ExpressionInteger(Token token); - std::string toString() override; -};*/ + Expression(Kind kind, Token token, shared_ptr left, shared_ptr right); + Kind getKind(); + bool operator==(Expression const& other); + bool operator!=(Expression const& other); + string toString(); + + static shared_ptr Invalid; +}; #endif \ No newline at end of file diff --git a/src/Parser.cpp b/src/Parser.cpp index f4403be..3b7b487 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -1,24 +1,61 @@ #include "Parser.h" -Parser::Parser(std::vector tokens) : tokens(tokens) { +Parser::Parser(vector tokens): tokens(tokens) { } -/*Expression Parser::getExpression() { +shared_ptr Parser::getExpression() { return term(); -}*/ +} -/*Expression Parser::term() { +shared_ptr Parser::term() { + shared_ptr expression = factor(); -}*/ + while (tokens.at(currentIndex).isOneOf({Token::Kind::PLUS, Token::Kind::MINUS})) { + expression = matchBinary(expression); + } -/*Expression Parser::primary() { + return expression; +} -}*/ +shared_ptr Parser::factor() { + shared_ptr expression = primary(); -Expression Parser::matchInteger() { - //Token token = tokens.at(currentIndex); - //if (token.getKind() == Token::Kind::INTEGER) - // ExpressionInteger(token); + while (tokens.at(currentIndex).isOneOf({Token::Kind::STAR, Token::Kind::SLASH, Token::Kind::PERCENT})) { + expression = matchBinary(expression); + } + + return expression; +} + +shared_ptr Parser::primary() { + shared_ptr expression = Expression::Invalid; + + do { + if((expression = matchInteger()) != Expression::Invalid) + break; + + } while(false); + + return expression; +} + +shared_ptr Parser::matchInteger() { + Token token = tokens.at(currentIndex); + if (token.getKind() == Token::Kind::INTEGER) { + currentIndex++; + return make_shared(Expression::Kind::LITERAL, token, nullptr, nullptr); + } + + return Expression::Invalid; +} + +shared_ptr Parser::matchBinary(shared_ptr left) { + Token token = tokens.at(currentIndex); + if (token.isOneOf({Token::Kind::PLUS, Token::Kind::MINUS, Token::Kind::STAR, Token::Kind::SLASH, Token::Kind::PERCENT})) { + currentIndex++; + shared_ptr right = factor(); + return make_shared(Expression::Kind::BINARY, token, left, right); + } return Expression::Invalid; } \ No newline at end of file diff --git a/src/Parser.h b/src/Parser.h index 8ad227c..452d65e 100644 --- a/src/Parser.h +++ b/src/Parser.h @@ -5,19 +5,23 @@ #include "Token.h" #include "Expression.h" +using namespace std; + class Parser { private: - std::vector tokens; + vector tokens; int currentIndex = 0; - //Expression term(); - //Expression primary(); + shared_ptr term(); // +, - + shared_ptr factor(); // *, /, % + shared_ptr primary(); - Expression matchInteger(); + shared_ptr matchInteger(); + shared_ptr matchBinary(shared_ptr left); public: - Parser(std::vector tokens); - //Expression getExpression(); + Parser(vector tokens); + shared_ptr getExpression(); }; #endif \ No newline at end of file diff --git a/src/Token.cpp b/src/Token.cpp index e6c99af..c1c4bd6 100644 --- a/src/Token.cpp +++ b/src/Token.cpp @@ -21,6 +21,15 @@ bool Token::operator!=(Token const& other) { return kind != other.kind; } +bool Token::isOneOf(std::vector kinds) { + for (Kind &kind : kinds) { + if (kind == this->kind) + return true; + } + + return false; +} + std::string Token::toString() { switch (kind) { case PLUS: diff --git a/src/Token.h b/src/Token.h index 12d05eb..1a2b844 100644 --- a/src/Token.h +++ b/src/Token.h @@ -35,6 +35,7 @@ public: std::string getLexme(); bool operator==(Token const& other); bool operator!=(Token const& other); + bool isOneOf(std::vector kinds); std::string toString(); static Token Invalid; diff --git a/src/main.cpp b/src/main.cpp index 6f2c9c1..ffeaa50 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,13 @@ #include #include -#include "Lexer.h" + #include "Token.h" +#include "Lexer.h" + +#include "Expression.h" +#include "Parser.h" + +using namespace std; std::string readFile(std::string fileName) { std::ifstream file(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate); @@ -30,5 +36,9 @@ int main(int argc, char **argv) { std::cout << token.toString() << " "; std::cout << std::endl; + Parser parser(tokens); + shared_ptr expression = parser.getExpression(); + cout << expression->toString() << endl; + return 0; } \ No newline at end of file