Skip to content

Commit

Permalink
Merge pull request #4 from Rohith-Raju/statements
Browse files Browse the repository at this point in the history
Statements
  • Loading branch information
Rohith-Raju authored Apr 13, 2024
2 parents 7110ab9 + 4bf7d9d commit 362d5d4
Show file tree
Hide file tree
Showing 17 changed files with 869 additions and 210 deletions.
35 changes: 34 additions & 1 deletion include/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ enum ExprType {
ExprType_Grouping,
ExprType_Unary,
ExprType_Literal,
ExprType_Ternary
ExprType_Ternary,
ExprType_Variable,
ExprType_Assignment,
ExprType_Logical
};

class Expr {
Expand Down Expand Up @@ -67,6 +70,16 @@ class Ternary : public Expr {
~Ternary();
};

class Logical : public Expr {
public:
Expr *left;
Token *op;
Expr *right;
Logical(Expr *left, Token *op, Expr *right);

~Logical();
};

class Literal : public Expr {
public:
Object *literal;
Expand All @@ -76,4 +89,24 @@ class Literal : public Expr {
~Literal();
};

class Variable : public Expr {
public:
Token *name;

Variable(Token *name);

~Variable();
};

class Assignment : public Expr {
public:
Token *name;

Expr *value;

Assignment(Token *name, Expr *value);

~Assignment();
};

#endif
196 changes: 54 additions & 142 deletions include/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,155 +5,67 @@
#ifndef CRUX_INTERPRETER_H
#define CRUX_INTERPRETER_H

#include "Error.h"
#include "Expr.h"
#include "Statement.h"
#include "Token.h"
#include "env/Env.h"
#include "utls/Object.h"
#include "utls/RuntimeError.h"
#include <string>
#include <vector>

class Interpreter {
private:
Object evaluate(Expr *expr) {
switch (expr->type) {
case ExprType_Binary:
return visitBinaryExp((Binary *)expr);
case ExprType_Unary:
return visitUnaryExp((Unary *)expr);
case ExprType_Literal:
return visitLiteral((Literal *)expr);
case ExprType_Grouping:
return visitGroupExp((Grouping *)expr);
case ExprType_Ternary:
return visitTernaryExp((Ternary *)expr);
}
return Object();
}

bool isTruthy(Object right) {
if (right.type == nullptr_type)
return false;
if (right.type == bool_type)
return right.bool_literal;
return true;
}

bool isEqual(Object left, Object right) {
if (left.type == nullptr_type && right.type == nullptr_type)
return true;
if (left.type == nullptr_type)
return false;

return left.num_literal == right.num_literal;
}

void checkNumberOperand(Token *op, Object right) {
if (right.type == num_type)
return;
RuntimeError(*op, "Operand must be a number");
}
bool checkIfSameTypes(Object left, Object right) {
if (left.type == num_type && right.type == num_type)
return true;
else
return false;
}

bool checkCompatibility(Token *op, Object left, Object right) {
if ((left.type == string_type && right.type == num_type) ||
left.type == num_type && right.type == string_type) {
return true;
} else {
return false;
}
}
Environment *environment = new Environment();

void excecute(Statement *stmnt);

void excecuteBlock(std::vector<Statement *> stmnts, Environment *env);

Object evaluate(Expr *expr);

bool isTruthy(Object right);

bool isEqual(Object left, Object right);

void checkNumberOperand(Token *op, Object right);

bool checkIfSameTypes(Object left, Object right);

bool checkCompatibility(Token *op, Object left, Object right);

public:
std ::string interpret(Expr *expression) {
try {
Object expr = evaluate(expression);
return expr.str();
} catch (RuntimeError error) {
crux::runtimeError(error);
}
}

Object visitLiteral(Literal *expr) { return *expr->literal; }

Object visitGroupExp(Grouping *expr) { return evaluate(expr->expression); }

Object visitUnaryExp(Unary *expr) {
Object right = evaluate(expr->right);
switch (expr->op->type) {
case BANG:
return !isTruthy(right);
case MINUS:
checkNumberOperand(expr->op, right);
return -right.num_literal;
default:
RuntimeError(*expr->op, "Invalid operator used");
}
return Object();
}

Object visitBinaryExp(Binary *expr) {
Object left = evaluate(expr->left);
Object right = evaluate(expr->right);
Token *op = expr->op;
switch (op->type) {
case MINUS:
checkIfSameTypes(left, right);
return left.num_literal - right.num_literal;
case SLASH:
checkIfSameTypes(left, right);
return left.num_literal / right.num_literal;
case STAR:
checkIfSameTypes(left, right);
return left.num_literal * right.num_literal;
case PLUS:
if (checkIfSameTypes(left, right)) {
if (left.type == num_type && right.type == num_type)
return left.num_literal + right.num_literal;
if (left.type == string_type && right.type == string_type)
return left.string_literal + right.string_literal;
} else if (checkCompatibility(op, left, right)) {
if (left.type == string_type && right.type == num_type)
return left.string_literal + std::to_string(right.num_literal);
else if (left.type == num_type && right.type == string_type)
return std::to_string(left.num_literal) + right.string_literal;
}
throw new RuntimeError(*op, "Error: Cannot evaluate expression");
case GREATER:
checkIfSameTypes(left, right);
return left.num_literal > right.num_literal;
case GREATER_EQUAL:
checkIfSameTypes(left, right);
return left.num_literal >= right.num_literal;
case LESS:
checkIfSameTypes(left, right);
return left.num_literal < right.num_literal;
case LESS_EQUAL:
checkIfSameTypes(left, right);
return left.num_literal <= right.num_literal;
case BANG_EQUAL:
return !isEqual(left, right);
case EQUAL_EQUAL:
return isEqual(left, right);
}
RuntimeError(*op, "Operator not found");
}

Object visitTernaryExp(Ternary *expr) {
Object condition = evaluate(expr->condition);
if (condition.type == bool_type) {
if (condition.bool_literal)
return evaluate(expr->expression1);
else
return evaluate(expr->expression2);
} else {
RuntimeError(*expr->op1, "Ternary Expression couldn't be evaluated");
}
return Object();
}
bool isBreakUsed = false;

void interpret(std::vector<Statement *> &statements);

void visitPrintStmnt(Print *stmnt);

void visitBlockStmnt(Block *stmnt);

Object visitExprStmnt(Expression *stmnt);

void visitVarStmnt(Var *stmnt);

void visitIfStmnt(If *stmnt);

void visitWhileStmnt(While *stmnt);

Object visitAssignment(Assignment *expr);

Object visitLogicalExp(Logical *expr);

Object visitLiteral(Literal *expr);

Object visitGroupExp(Grouping *expr);

Object visitUnaryExp(Unary *expr);

Object visitBinaryExp(Binary *expr);

Object visitTernaryExp(Ternary *expr);

Object visitVariableExp(Variable *expr);

~Interpreter();
};

#endif // CRUX_INTERPRETER_H
27 changes: 24 additions & 3 deletions include/Parser.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
//
// Created by Rohith on 2/9/24.
//

#ifndef CRUX_PARSER_H
#define CRUX_PARSER_H

#include "Expr.h"
#include "Token.h"
#include <Statement.h>
#include <stdexcept>
#include <vector>

Expand All @@ -17,6 +16,14 @@ class Parser {
};
std::vector<Token> tokens;
int current = 0;
// loopCounter to determine if "break" is valid or not. (break should only
// occur in loops)
int loopCounter = 0;

// Precidence
Expr *Or();
Expr *And();
Expr *assignment();
Expr *expression();
Expr *ternary();
Expr *comparison();
Expand All @@ -25,6 +32,20 @@ class Parser {
Expr *unary();
Expr *primary();

// Statement helper functions
Statement *statement();
Statement *printStatement();
Statement *ifStatement();
Statement *whileStatement();
Statement *forStatement();
Statement *breakStatement();
Statement *expressionStatement();
std::vector<Statement *> blockStatement();

// Variable stuff
Statement *declaration();
Statement *varDeclaration();

// helper functions
Expr *equality();
bool check(TokenType type);
Expand All @@ -40,7 +61,7 @@ class Parser {

public:
Parser(const std::vector<Token> &tokens) : tokens{tokens} {};
Expr *parse();
std::vector<Statement *> parse();
};

#endif // CRUX_PARSER_H
Loading

0 comments on commit 362d5d4

Please sign in to comment.