diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp
new file mode 100644
index 0000000..6351669
--- /dev/null
+++ b/src/parser/Parser.cpp
@@ -0,0 +1,801 @@
+/*
+* Copyright (c) 2024 - Nathanne Isip
+* This file is part of Zhivo.
+*
+* Zhivo is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 3 of the License,
+* or (at your option) any later version.
+*
+* Zhivo is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Zhivo. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+Parser Parser::fromFile(const std::string& fileName) {
+ std::unique_ptr tokenizer = Tokenizer::loadFile(fileName);
+ tokenizer->scan();
+
+ return Parser(tokenizer->getTokens());
+}
+
+bool Parser::isAtEnd() const {
+ return this->index == this->length;
+}
+
+void Parser::advance() {
+ this->index++;
+}
+
+Token Parser::peek() const {
+ if(this->isAtEnd())
+ throw ParserException("Encountered end-of-file.");
+
+ return this->tokens[this->index];
+}
+
+bool Parser::isNext(const std::string& image) const {
+ if(this->isAtEnd())
+ return false;
+
+ return this->peek().getImage() == image;
+}
+
+Token Parser::consume(const std::string& image) {
+ if(this->isAtEnd())
+ throw ParserException("Expecting \"" + image + "\", encountered end-of-code.");
+
+ Token token = this->peek();
+ if(token.getImage() != image)
+ throw ParserException("Expecting \"" + image + "\", encountered " + token.getImage());
+
+ this->advance();
+ return token;
+}
+
+Token Parser::consume(TokenType type) {
+ if(this->isAtEnd())
+ throw ParserException("Expecting token type, encountered end-of-code.");
+
+ Token token = this->peek();
+ if(token.getType() != type)
+ throw ParserException(
+ "Expecting " + tokenTypeToString(type) +
+ ", encountered " + tokenTypeToString(token.getType())
+ );
+
+ this->advance();
+ return token;
+}
+
+const std::vector>& Parser::getGlobalStatements() const {
+ return this->globalStatements;
+}
+
+std::unique_ptr Parser::exprArray() {
+ Token address = this->consume("[");
+ std::vector> expressions;
+
+ while(!this->isNext("]")) {
+ if(!expressions.empty())
+ this->consume(",");
+
+ expressions.push_back(this->expression());
+ }
+
+ this->consume("]");
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(expressions)
+ );
+}
+
+std::unique_ptr Parser::exprBlock() {
+ Token address = this->consume("{");
+ std::vector> body;
+
+ while(!this->isNext("}"))
+ body.emplace_back(this->expression());
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(body)
+ );
+}
+
+std::unique_ptr Parser::exprCatchHandle() {
+ Token address = this->consume("catch");
+ std::unique_ptr catchExpr = this->expression();
+ this->consume("handle");
+
+ Token handler = this->consume(TokenType::IDENTIFIER);
+ std::unique_ptr handleExpr = this->expression();
+
+ std::unique_ptr finalExpr = nullptr;
+ if(this->isNext("handle")) {
+ this->consume("handle");
+ finalExpr = this->expression();
+ }
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(catchExpr),
+ std::move(handleExpr),
+ std::make_unique(handler),
+ std::move(finalExpr)
+ );
+}
+
+std::unique_ptr Parser::exprDoWhile() {
+ Token address = this->consume("do");
+ std::unique_ptr body = this->expression();
+
+ this->consume("while");
+ this->consume("(");
+
+ std::unique_ptr condition = this->expression();
+ this->consume(")");
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(body),
+ std::move(condition)
+ );
+}
+
+std::unique_ptr Parser::exprFunctionDecl() {
+ Token address = this->consume("func");
+ this->consume("(");
+
+ std::vector> parameters;
+ while(!this->isNext(")")) {
+ if(!parameters.empty())
+ this->consume(",");
+
+ parameters.emplace_back(
+ std::make_unique(
+ this->consume(TokenType::IDENTIFIER)
+ )
+ );
+ }
+ this->consume(")");
+
+ std::unique_ptr body = this->expression();
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(parameters),
+ std::move(body)
+ );
+}
+
+std::unique_ptr Parser::exprLoop() {
+ Token address = this->consume("loop");
+ this->consume("(");
+
+ std::unique_ptr initial = this->expression();
+ this->consume(";");
+
+ std::unique_ptr condition = this->expression();
+ this->consume(";");
+
+ std::unique_ptr postexpr = this->expression();
+ this->consume(")");
+
+ std::unique_ptr body = this->expression();
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(initial),
+ std::move(condition),
+ std::move(postexpr),
+ std::move(body)
+ );
+}
+
+std::unique_ptr Parser::exprIf() {
+ Token address = this->consume("if");
+ this->consume("(");
+
+ std::unique_ptr condition = this->expression();
+ this->consume(")");
+
+ std::unique_ptr thenExpr = this->expression();
+ std::unique_ptr elseExpr = nullptr;
+
+ if(this->isNext("else")) {
+ this->consume("else");
+ elseExpr = this->expression();
+ }
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(condition),
+ std::move(thenExpr),
+ std::move(elseExpr)
+ );
+}
+
+std::unique_ptr Parser::exprLiteral() {
+ std::unique_ptr expr = nullptr;
+
+ if(this->isNext("true"))
+ expr = std::make_unique(
+ std::make_unique(this->consume("true")),
+ true
+ );
+ else if(this->isNext("false"))
+ expr = std::make_unique(
+ std::make_unique(this->consume("false")),
+ false
+ );
+ else if(this->isNext("maybe"))
+ expr = std::make_unique(
+ std::make_unique(this->consume("maybe"))
+ );
+ else if(this->isNext("nil"))
+ expr = std::make_unique(
+ std::make_unique(this->consume("nil"))
+ );
+ else if(this->peek().getType() == TokenType::STRING) {
+ Token stringToken = this->consume(TokenType::STRING);
+ expr = std::make_unique(
+ std::make_unique(stringToken),
+ stringToken.getImage()
+ );
+ }
+ else if(this->peek().getType() == TokenType::DIGIT) {
+ Token digitToken = this->consume(TokenType::DIGIT);
+ expr = std::make_unique(
+ std::make_unique(digitToken),
+ ZhivoUtil::Convert::translateDigit(digitToken.getImage())
+ );
+ }
+
+ if(!expr)
+ throw ParserException(
+ "Expecting expression, encountered " +
+ this->peek().getImage()
+ );
+
+ return expr;
+}
+
+std::unique_ptr Parser::exprRandom() {
+ Token address = this->consume("random");
+ std::unique_ptr thenExpr = this->expression();
+ std::unique_ptr elseExpr = nullptr;
+
+ if(this->isNext("else")) {
+ this->consume("else");
+ elseExpr = this->expression();
+ }
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(thenExpr),
+ std::move(elseExpr)
+ );
+}
+
+std::unique_ptr Parser::exprRender() {
+ Token address = this->consume("render");
+ std::unique_ptr expression = this->expression();
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(expression)
+ );
+}
+
+std::unique_ptr Parser::exprType() {
+ Token address = this->consume("type");
+ std::unique_ptr expression = this->expression();
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(expression)
+ );
+}
+
+std::unique_ptr Parser::exprUnless() {
+ Token address = this->consume("unless");
+ this->consume("(");
+
+ std::unique_ptr condition = this->expression();
+ this->consume(")");
+
+ std::unique_ptr thenExpr = this->expression();
+ std::unique_ptr elseExpr = nullptr;
+
+ if(this->isNext("else")) {
+ this->consume("else");
+ elseExpr = this->expression();
+ }
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(condition),
+ std::move(thenExpr),
+ std::move(elseExpr)
+ );
+}
+
+std::unique_ptr Parser::exprWhen() {
+ Token address = this->consume("when");
+ this->consume("(");
+
+ std::unique_ptr expression = this->expression();
+ this->consume(")");
+ this->consume("{");
+
+ std::vector, std::unique_ptr>> cases;
+ std::unique_ptr defaultCase = nullptr;
+
+ while(!this->isNext("}")) {
+ if(!cases.empty())
+ this->consume(",");
+
+ if(this->isNext("if")) {
+ this->consume("if");
+ this->consume("(");
+
+ std::unique_ptr caseExpr = this->expression();
+ this->consume(")");
+
+ std::unique_ptr thenBlock = this->expression();
+ cases.emplace_back(std::make_pair(
+ std::move(caseExpr),
+ std::move(thenBlock)
+ ));
+ }
+ else if(this->isNext("else")) {
+ if(defaultCase)
+ throw std::runtime_error("Cannot have more than one (1) else for when expression.");
+
+ this->consume("else");
+ defaultCase = this->expression();
+ }
+ }
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(expression),
+ std::move(cases),
+ std::move(defaultCase)
+ );
+}
+
+std::unique_ptr Parser::exprWhile() {
+ Token address = this->consume("while");
+ this->consume("(");
+
+ std::unique_ptr condition = this->expression();
+ this->consume(")");
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(condition),
+ this->expression()
+ );
+}
+
+std::unique_ptr Parser::exprPrimary() {
+ std::unique_ptr expression = nullptr;
+
+ if(this->isNext("+") || this->isNext("-") || this->isNext("~")) {
+ Token address = this->consume(TokenType::OPERATOR);
+ expression = std::make_unique(
+ std::make_unique(address),
+ std::move(std::string(address.getImage())),
+ this->expression()
+ );
+ }
+ else if(this->isNext("(")) {
+ Token address = this->consume("(");
+ std::unique_ptr innerExpr = this->expression();
+
+ expression = std::make_unique(
+ std::make_unique(address),
+ std::move(innerExpr)
+ );
+ this->consume(")");
+ }
+ else if(this->isNext("{")) {
+ Token address = this->consume(TokenType::IDENTIFIER);
+ std::vector> statements;
+
+ while(!this->isNext("}")) {
+ std::unique_ptr stmt = this->statement();
+ statements.emplace_back(std::move(stmt));
+ }
+ this->consume("}");
+
+ expression = std::make_unique(
+ std::make_unique(address),
+ std::move(statements)
+ );
+ }
+ else if(this->isNext("render"))
+ expression = this->exprRender();
+ else if(this->isNext("catch"))
+ expression = this->exprCatchHandle();
+ else if(this->isNext("do"))
+ expression = this->exprDoWhile();
+ else if(this->isNext("while"))
+ expression = this->exprWhile();
+ else if(this->isNext("loop"))
+ expression = this->exprLoop();
+ else if(this->isNext("unless"))
+ expression = this->exprUnless();
+ else if(this->isNext("when"))
+ expression = this->exprWhen();
+ else if(this->isNext("func"))
+ expression = this->exprFunctionDecl();
+ else if(this->isNext("["))
+ expression = this->exprArray();
+ else if(this->peek().getType() == TokenType::IDENTIFIER) {
+ expression = std::make_unique(
+ std::make_unique(this->consume(TokenType::IDENTIFIER))
+ );
+
+ while(this->isNext("[")) {
+ Token address = this->consume("[");
+ std::unique_ptr indexExpr = this->expression();
+
+ this->consume("]");
+ expression = std::make_unique(
+ std::make_unique(address),
+ std::move(expression),
+ std::move(indexExpr)
+ );
+ }
+ }
+ else expression = this->exprLiteral();
+
+ while(this->isNext("(") || this->isNext("[")) {
+ while(this->isNext("(")) {
+ Token address = this->consume("(");
+ std::vector> arguments;
+
+ while(!this->isNext(")")) {
+ if(!arguments.empty())
+ this->consume(",");
+
+ arguments.emplace_back(
+ std::move(this->expression())
+ );
+ }
+
+ this->consume(")");
+ expression = std::make_unique(
+ std::make_unique(address),
+ std::move(expression),
+ std::move(arguments)
+ );
+ }
+
+ while(this->isNext("[")) {
+ Token address = this->consume("[");
+ std::unique_ptr indexExpr = this->expression();
+
+ this->consume("]");
+ expression = std::make_unique(
+ std::make_unique(address),
+ std::move(expression),
+ std::move(indexExpr)
+ );
+ }
+ }
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprLogicOr() {
+ std::unique_ptr expression = this->exprLogicAnd();
+
+ while(this->isNext("||"))
+ expression = std::make_unique(
+ std::make_unique(
+ this->consume(TokenType::OPERATOR)
+ ),
+ std::move(expression),
+ "||",
+ std::move(this->exprLogicAnd())
+ );
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprLogicAnd() {
+ std::unique_ptr expression = this->exprBitwiseOr();
+
+ while(this->isNext("&&"))
+ expression = std::make_unique(
+ std::make_unique(
+ this->consume(TokenType::OPERATOR)
+ ),
+ std::move(expression),
+ "&&",
+ std::move(this->exprBitwiseOr())
+ );
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprBitwiseOr() {
+ std::unique_ptr expression = this->exprBitwiseXor();
+
+ while(this->isNext("|"))
+ expression = std::make_unique(
+ std::make_unique(
+ this->consume(TokenType::OPERATOR)
+ ),
+ std::move(expression),
+ "|",
+ std::move(this->exprBitwiseXor())
+ );
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprBitwiseXor() {
+ std::unique_ptr expression = this->exprBitwiseAnd();
+
+ while(this->isNext("^"))
+ expression = std::make_unique(
+ std::make_unique(
+ this->consume(TokenType::OPERATOR)
+ ),
+ std::move(expression),
+ "^",
+ std::move(this->exprBitwiseAnd())
+ );
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprBitwiseAnd() {
+ std::unique_ptr expression = this->exprNilCoalescing();
+
+ while(this->isNext("&"))
+ expression = std::make_unique(
+ std::make_unique(
+ this->consume(TokenType::OPERATOR)
+ ),
+ std::move(expression),
+ "&",
+ std::move(this->exprNilCoalescing())
+ );
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprNilCoalescing() {
+ std::unique_ptr expression = this->exprEquality();
+
+ while(this->isNext("?"))
+ expression = std::make_unique(
+ std::make_unique(
+ this->consume(TokenType::OPERATOR)
+ ),
+ std::move(expression),
+ std::move(this->exprEquality())
+ );
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprEquality() {
+ std::unique_ptr expression = this->exprComparison();
+
+ while(this->isNext("==") || this->isNext("!=") || this->isNext("=")) {
+ Token op = this->consume(TokenType::OPERATOR);
+ expression = std::make_unique(
+ std::make_unique(op),
+ std::move(expression),
+ op.getImage(),
+ std::move(this->exprComparison())
+ );
+ }
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprComparison() {
+ std::unique_ptr expression = this->exprShift();
+
+ while(this->isNext("<") ||
+ this->isNext("<=") ||
+ this->isNext(">") ||
+ this->isNext(">=")
+ ) {
+ Token op = this->consume(TokenType::OPERATOR);
+ expression = std::make_unique(
+ std::make_unique(op),
+ std::move(expression),
+ op.getImage(),
+ std::move(this->exprShift())
+ );
+ }
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprShift() {
+ std::unique_ptr expression = this->exprTerm();
+
+ while(this->isNext("<<") || this->isNext(">>")) {
+ Token op = this->consume(TokenType::OPERATOR);
+ expression = std::make_unique(
+ std::make_unique(op),
+ std::move(expression),
+ op.getImage(),
+ std::move(this->exprTerm())
+ );
+ }
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprTerm() {
+ std::unique_ptr expression = this->exprFactor();
+
+ while(this->isNext("+") || this->isNext("-")) {
+ Token op = this->consume(TokenType::OPERATOR);
+ expression = std::make_unique(
+ std::make_unique(op),
+ std::move(expression),
+ op.getImage(),
+ std::move(this->exprFactor())
+ );
+ }
+
+ return expression;
+}
+
+std::unique_ptr Parser::exprFactor() {
+ std::unique_ptr expression = this->exprPrimary();
+
+ while(this->isNext("*") || this->isNext("/") || this->isNext("%")) {
+ Token op = this->consume(TokenType::OPERATOR);
+ expression = std::make_unique(
+ std::make_unique(op),
+ std::move(expression),
+ op.getImage(),
+ std::move(this->exprPrimary())
+ );
+ }
+
+ return expression;
+}
+
+std::unique_ptr Parser::expression() {
+ return this->exprLogicOr();
+}
+
+std::unique_ptr Parser::stmtBreak() {
+ Token address = this->consume("break");
+ this->consume(";");
+
+ return std::make_unique(
+ std::make_unique(address)
+ );
+}
+
+std::unique_ptr Parser::stmtContinue() {
+ Token address = this->consume("continue");
+ this->consume(";");
+
+ return std::make_unique(
+ std::make_unique(address)
+ );
+}
+
+std::unique_ptr Parser::stmtRet() {
+ Token address = this->consume("ret");
+ std::unique_ptr expression = this->expression();
+
+ this->consume(";");
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(expression)
+ );
+}
+
+std::unique_ptr Parser::stmtThrow() {
+ Token address = this->consume("throw");
+ std::unique_ptr expression = this->expression();
+
+ this->consume(";");
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(expression)
+ );
+}
+
+std::unique_ptr Parser::stmtTest() {
+ Token address = this->consume("test");
+ this->consume("(");
+
+ std::unique_ptr testName = this->expression();
+ this->consume(")");
+
+ std::unique_ptr testBody = this->expression();
+ this->consume(";");
+
+ return std::make_unique(
+ std::make_unique(address),
+ std::move(testName),
+ std::move(testBody)
+ );
+}
+
+std::unique_ptr Parser::statement() {
+ if(this->isNext("break"))
+ return this->stmtBreak();
+ else if(this->isNext("continue"))
+ return this->stmtContinue();
+ else if(this->isNext("ret"))
+ return this->stmtRet();
+ else if(this->isNext("throw"))
+ return this->stmtThrow();
+ else if(this->isNext("test"))
+ return this->stmtTest();
+
+ std::unique_ptr expr = this->expression();
+ this->consume(";");
+
+ return expr;
+}
+
+void Parser::parse() {
+ while(!this->isAtEnd())
+ this->globalStatements.push_back(this->statement());
+}