It's alive! (implemented base interpreter)
This commit is contained in:
parent
9500cf9773
commit
3e5ba29283
6
Makefile
6
Makefile
@ -22,7 +22,7 @@ OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(CPP_FILES))
|
||||
$(shell mkdir -p $(dir $(OBJ_FILES)))
|
||||
|
||||
# Default target
|
||||
all: clean $(BUILD_DIR)/bob
|
||||
all: build run
|
||||
|
||||
# Rule to create necessary directories
|
||||
$(DIRS):
|
||||
@ -37,8 +37,12 @@ $(BUILD_DIR)/bob: $(OBJ_FILES)
|
||||
$(CC) $(CFLAGS) $^ -o $@
|
||||
|
||||
|
||||
run:
|
||||
./$(BUILD_DIR)/bob
|
||||
|
||||
build: clean $(BUILD_DIR)/bob
|
||||
|
||||
|
||||
# Clean build directory
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)/*
|
||||
|
||||
@ -6,14 +6,14 @@
|
||||
#include <initializer_list>
|
||||
|
||||
|
||||
class ASTPrinter : public Visitor
|
||||
class ASTPrinter : Visitor
|
||||
{
|
||||
sptr(Object) visitBinaryExpr(BinaryExpr* expression) override;
|
||||
sptr(Object) visitGroupingExpr(GroupingExpr* expression) override;
|
||||
sptr(Object) visitLiteralExpr(LiteralExpr* expression) override;
|
||||
sptr(Object) visitUnaryExpr(UnaryExpr* expression) override;
|
||||
sptr(Object) visitBinaryExpr(sptr(BinaryExpr) expr) override;
|
||||
sptr(Object) visitGroupingExpr(sptr(GroupingExpr) expr) override;
|
||||
sptr(Object) visitLiteralExpr(sptr(LiteralExpr) expr) override;
|
||||
sptr(Object) visitUnaryExpr(sptr(UnaryExpr) expr) override;
|
||||
public:
|
||||
sptr(Object) print(Expr* expr);
|
||||
sptr(Object) print(sptr(Expr) expr);
|
||||
private:
|
||||
sptr(Object) parenthesize(std::string name, std::vector<sptr(Expr)> exprs);
|
||||
|
||||
|
||||
@ -15,10 +15,10 @@ struct UnaryExpr;
|
||||
|
||||
struct Visitor
|
||||
{
|
||||
virtual sptr(Object) visitBinaryExpr(BinaryExpr* expression) = 0;
|
||||
virtual sptr(Object) visitGroupingExpr(GroupingExpr* expression) = 0;
|
||||
virtual sptr(Object) visitLiteralExpr(LiteralExpr* expression) = 0;
|
||||
virtual sptr(Object) visitUnaryExpr(UnaryExpr* expression) = 0;
|
||||
virtual sptr(Object) visitBinaryExpr(sptr(BinaryExpr) expr) = 0;
|
||||
virtual sptr(Object) visitGroupingExpr(sptr(GroupingExpr) expr) = 0;
|
||||
virtual sptr(Object) visitLiteralExpr(sptr(LiteralExpr) expr) = 0;
|
||||
virtual sptr(Object) visitUnaryExpr(sptr(UnaryExpr) expr) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ struct Expr{
|
||||
};
|
||||
|
||||
|
||||
struct BinaryExpr : Expr
|
||||
struct BinaryExpr : Expr, public std::enable_shared_from_this<BinaryExpr>
|
||||
{
|
||||
const std::shared_ptr<Expr> left;
|
||||
const Token oper;
|
||||
@ -38,11 +38,11 @@ struct BinaryExpr : Expr
|
||||
{
|
||||
}
|
||||
sptr(Object) accept(Visitor* visitor) override{
|
||||
return visitor->visitBinaryExpr(this);
|
||||
return visitor->visitBinaryExpr(shared_from_this() );
|
||||
}
|
||||
};
|
||||
|
||||
struct GroupingExpr : Expr
|
||||
struct GroupingExpr : Expr, public std::enable_shared_from_this<GroupingExpr>
|
||||
{
|
||||
const std::shared_ptr<Expr> expression;
|
||||
|
||||
@ -50,23 +50,24 @@ struct GroupingExpr : Expr
|
||||
{
|
||||
}
|
||||
sptr(Object) accept(Visitor* visitor) override{
|
||||
return visitor->visitGroupingExpr(this);
|
||||
return visitor->visitGroupingExpr(shared_from_this());
|
||||
}
|
||||
};
|
||||
|
||||
struct LiteralExpr : Expr
|
||||
struct LiteralExpr : Expr, public std::enable_shared_from_this<LiteralExpr>
|
||||
{
|
||||
const std::string value;
|
||||
const bool isNumber;
|
||||
LiteralExpr(std::string value, bool isNumber) : value(value), isNumber(isNumber)
|
||||
const bool isNull;
|
||||
LiteralExpr(std::string value, bool isNumber, bool isNull) : value(value), isNumber(isNumber), isNull(isNull)
|
||||
{
|
||||
}
|
||||
sptr(Object) accept(Visitor* visitor) override{
|
||||
return visitor->visitLiteralExpr(this);
|
||||
return visitor->visitLiteralExpr(shared_from_this());
|
||||
}
|
||||
};
|
||||
|
||||
struct UnaryExpr : Expr
|
||||
struct UnaryExpr : Expr, public std::enable_shared_from_this<UnaryExpr>
|
||||
{
|
||||
const Token oper;
|
||||
const std::shared_ptr<Expr> right;
|
||||
@ -75,7 +76,7 @@ struct UnaryExpr : Expr
|
||||
{
|
||||
}
|
||||
sptr(Object) accept(Visitor* visitor) override{
|
||||
return visitor->visitUnaryExpr(this);
|
||||
return visitor->visitUnaryExpr(shared_from_this());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
23
headers/Interpreter.h
Normal file
23
headers/Interpreter.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "Expression.h"
|
||||
#include "helperFunctions/ShortHands.h"
|
||||
#include "TypeWrapper.h"
|
||||
|
||||
class Interpreter : Visitor
|
||||
{
|
||||
|
||||
public:
|
||||
sptr(Object) visitBinaryExpr(sptr(BinaryExpr) expression) override;
|
||||
sptr(Object) visitGroupingExpr(sptr(GroupingExpr) expression) override;
|
||||
sptr(Object) visitLiteralExpr(sptr(LiteralExpr) expression) override;
|
||||
sptr(Object) visitUnaryExpr(sptr(UnaryExpr) expression) override;
|
||||
|
||||
void interpret(sptr(Expr) expr);
|
||||
|
||||
private:
|
||||
sptr(Object) evaluate(sptr(Expr) expr);
|
||||
bool isTruthy(sptr(Object) object);
|
||||
bool isEqual(sptr(Object) a, sptr(Object) b);
|
||||
|
||||
std::string stringify(sptr(Object) object);
|
||||
};
|
||||
@ -5,14 +5,25 @@ struct Object
|
||||
virtual ~Object(){};
|
||||
};
|
||||
|
||||
struct Number : public Object
|
||||
struct Number : Object
|
||||
{
|
||||
double value;
|
||||
explicit Number(double value) : value(value) {}
|
||||
};
|
||||
|
||||
struct String : public Object
|
||||
struct String : Object
|
||||
{
|
||||
std::string value;
|
||||
explicit String(std::string str) : value(str) {}
|
||||
};
|
||||
|
||||
struct Boolean : Object
|
||||
{
|
||||
bool value;
|
||||
explicit Boolean(bool value) : value(value) {}
|
||||
};
|
||||
|
||||
struct None : public Object
|
||||
{
|
||||
|
||||
};
|
||||
@ -4,6 +4,7 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "../headers/Lexer.h"
|
||||
#include "../headers/Interpreter.h"
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
@ -11,6 +12,7 @@ class Bob
|
||||
{
|
||||
public:
|
||||
Lexer lexer;
|
||||
Interpreter interpreter;
|
||||
|
||||
public:
|
||||
void runFile(std::string path);
|
||||
|
||||
@ -4,22 +4,22 @@
|
||||
#include "../headers/ASTPrinter.h"
|
||||
|
||||
|
||||
sptr(Object) ASTPrinter::visitBinaryExpr(BinaryExpr* expression){
|
||||
sptr(Object) ASTPrinter::visitBinaryExpr(sptr(BinaryExpr) expression){
|
||||
std::cout << expression->left << std::endl;
|
||||
return parenthesize(expression->oper.lexeme, std::vector<sptr(Expr)>{expression->left, expression->right});
|
||||
}
|
||||
|
||||
sptr(Object) ASTPrinter::visitGroupingExpr(GroupingExpr* expression){
|
||||
sptr(Object) ASTPrinter::visitGroupingExpr(sptr(GroupingExpr) expression){
|
||||
return parenthesize("group", std::vector<sptr(Expr)>{expression->expression});
|
||||
}
|
||||
sptr(Object) ASTPrinter::visitLiteralExpr(LiteralExpr* expression){
|
||||
sptr(Object) ASTPrinter::visitLiteralExpr(sptr(LiteralExpr) expression){
|
||||
return msptr(String)(expression->value);
|
||||
}
|
||||
sptr(Object) ASTPrinter::visitUnaryExpr(UnaryExpr* expression){
|
||||
sptr(Object) ASTPrinter::visitUnaryExpr(sptr(UnaryExpr) expression){
|
||||
return parenthesize(expression->oper.lexeme, std::vector<sptr(Expr)>{expression->right});
|
||||
}
|
||||
|
||||
sptr(Object) ASTPrinter::print(Expr *expr) {
|
||||
sptr(Object) ASTPrinter::print(sptr(Expr) expr) {
|
||||
return expr->accept(this);
|
||||
}
|
||||
|
||||
|
||||
206
source/Interpreter.cpp
Normal file
206
source/Interpreter.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
//
|
||||
// Created by Bobby Lucero on 5/27/23.
|
||||
//
|
||||
#include <utility>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include "../headers/Interpreter.h"
|
||||
|
||||
|
||||
sptr(Object) Interpreter::visitLiteralExpr(sptr(LiteralExpr) expr) {
|
||||
if(expr->isNull) return msptr(None)();
|
||||
if(expr->isNumber) return msptr(Number)(std::stod(expr->value));
|
||||
return msptr(String)(expr->value);
|
||||
}
|
||||
|
||||
sptr(Object) Interpreter::visitGroupingExpr(sptr(GroupingExpr) expression) {
|
||||
|
||||
return evaluate(expression->expression);
|
||||
}
|
||||
|
||||
sptr(Object) Interpreter::visitUnaryExpr(sptr(UnaryExpr) expression)
|
||||
{
|
||||
sptr(Object) right = evaluate(expression->right);
|
||||
|
||||
if(expression->oper.type == MINUS)
|
||||
{
|
||||
if(std::dynamic_pointer_cast<Number>(right))
|
||||
{
|
||||
double value = std::dynamic_pointer_cast<Number>(right)->value;
|
||||
return msptr(Number)(-value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Operand must be a number when using: " + expression->oper.lexeme);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(expression->oper.type == BANG)
|
||||
{
|
||||
return msptr(Boolean)(!isTruthy(right));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sptr(Object) Interpreter::visitBinaryExpr(sptr(BinaryExpr) expression)
|
||||
{
|
||||
sptr(Object) left = evaluate(expression->left);
|
||||
sptr(Object) right = evaluate(expression->right);
|
||||
|
||||
switch (expression->oper.type) {
|
||||
case BANG_EQUAL:
|
||||
return msptr(Boolean)(!isEqual(left, right));
|
||||
case DOUBLE_EQUAL:
|
||||
return msptr(Boolean)(isEqual(left, right));
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if(std::dynamic_pointer_cast<Number>(left) && std::dynamic_pointer_cast<Number>(right))
|
||||
{
|
||||
double left_double = std::dynamic_pointer_cast<Number>(left)->value;
|
||||
double right_double = std::dynamic_pointer_cast<Number>(right)->value;
|
||||
switch (expression->oper.type) {
|
||||
case GREATER:
|
||||
return msptr(Boolean)(left_double > right_double);
|
||||
case GREATER_EQUAL:
|
||||
return msptr(Boolean)(left_double >= right_double);
|
||||
case LESS:
|
||||
return msptr(Boolean)(left_double < right_double);
|
||||
case LESS_EQUAL:
|
||||
return msptr(Boolean)(left_double <= right_double);
|
||||
case MINUS:
|
||||
return msptr(Number)(left_double - right_double);
|
||||
case PLUS:
|
||||
return msptr(Number)(left_double + right_double);
|
||||
case SLASH:
|
||||
return msptr(Number)(left_double / right_double);
|
||||
case STAR:
|
||||
return msptr(Number)(left_double * right_double);
|
||||
default:
|
||||
return msptr(None)(); //unreachable
|
||||
}
|
||||
}
|
||||
else if(std::dynamic_pointer_cast<String>(left) && std::dynamic_pointer_cast<String>(right))
|
||||
{
|
||||
std::string left_string = std::dynamic_pointer_cast<String>(left)->value;
|
||||
std::string right_string = std::dynamic_pointer_cast<String>(right)->value;
|
||||
return msptr(String)(left_string + right_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Operands must be of same type when using: " + expression->oper.lexeme);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sptr(Object) Interpreter::evaluate(sptr(Expr) expr) {
|
||||
return expr->accept(this);
|
||||
}
|
||||
|
||||
bool Interpreter::isTruthy(sptr(Object) object) {
|
||||
|
||||
if(auto boolean = std::dynamic_pointer_cast<Boolean>(object))
|
||||
{
|
||||
boolean->value;
|
||||
}
|
||||
|
||||
if(auto obj = std::dynamic_pointer_cast<None>(object))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Interpreter::isEqual(sptr(Object) a, sptr(Object) b) {
|
||||
if(auto left = std::dynamic_pointer_cast<Number>(a))
|
||||
{
|
||||
if(auto right = std::dynamic_pointer_cast<Number>(b))
|
||||
{
|
||||
return left->value == right->value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(auto left = std::dynamic_pointer_cast<Boolean>(a))
|
||||
{
|
||||
if(auto right = std::dynamic_pointer_cast<Boolean>(b))
|
||||
{
|
||||
return left->value == right->value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(auto left = std::dynamic_pointer_cast<String>(a))
|
||||
{
|
||||
if(auto right = std::dynamic_pointer_cast<String>(b))
|
||||
{
|
||||
return left->value == right->value;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(auto left = std::dynamic_pointer_cast<None>(a))
|
||||
{
|
||||
if(auto right = std::dynamic_pointer_cast<None>(b))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::interpret(std::shared_ptr<Expr> expr) {
|
||||
|
||||
sptr(Object) value = evaluate(std::move(expr));
|
||||
std::cout << stringify(value) << std::endl;
|
||||
|
||||
}
|
||||
|
||||
std::string Interpreter::stringify(std::shared_ptr<Object> object) {
|
||||
if(std::dynamic_pointer_cast<None>(object))
|
||||
{
|
||||
return "None";
|
||||
}
|
||||
else if(auto num = std::dynamic_pointer_cast<Number>(object))
|
||||
{
|
||||
double integral = num->value;
|
||||
double fractional = std::modf(num->value, &integral);
|
||||
|
||||
std::stringstream ss;
|
||||
if(std::abs(fractional) < std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ss << std::fixed << std::setprecision(0) << integral;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << std::fixed << std::setprecision(std::numeric_limits<double>::digits10) << num->value;\
|
||||
std::string str = ss.str();
|
||||
str.erase(str.find_last_not_of('0') + 1, std::string::npos);
|
||||
if (str.back() == '.') {
|
||||
str.pop_back();
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
else if(auto string = std::dynamic_pointer_cast<String>(object))
|
||||
{
|
||||
return string->value;
|
||||
}
|
||||
else if(auto Bool = std::dynamic_pointer_cast<Boolean>(object))
|
||||
{
|
||||
return Bool->value == 1 ? "true" : "false";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -120,7 +120,7 @@ std::vector<Token> Lexer::Tokenize(std::string source){
|
||||
}
|
||||
else if(t == '"')
|
||||
{
|
||||
std::string str = std::string(1, src[0]);
|
||||
std::string str;
|
||||
advance();
|
||||
while(!src.empty() && src[0] != '"')
|
||||
{
|
||||
@ -134,7 +134,7 @@ std::vector<Token> Lexer::Tokenize(std::string source){
|
||||
}
|
||||
else if(src[0] == '"')
|
||||
{
|
||||
str += '"';
|
||||
|
||||
advance();
|
||||
tokens.push_back(Token{STRING, str, line});
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@ sptr(Expr) Parser::term()
|
||||
|
||||
while(match({MINUS, PLUS}))
|
||||
{
|
||||
std::cout << "Found comparison" << std::endl;
|
||||
Token op = previous();
|
||||
sptr(Expr) right = factor();
|
||||
expr = msptr(BinaryExpr)(expr, op, right);
|
||||
@ -84,12 +83,12 @@ sptr(Expr) Parser::unary()
|
||||
|
||||
sptr(Expr) Parser::primary()
|
||||
{
|
||||
if(match({FALSE})) return msptr(LiteralExpr)("true", false);
|
||||
if(match({TRUE})) return msptr(LiteralExpr)("true", false);
|
||||
if(match({NONE})) return msptr(LiteralExpr)("none", false);
|
||||
if(match({FALSE})) return msptr(LiteralExpr)("true", false, false);
|
||||
if(match({TRUE})) return msptr(LiteralExpr)("true", false, false);
|
||||
if(match({NONE})) return msptr(LiteralExpr)("none", false, false);
|
||||
|
||||
if(match({NUMBER})) return msptr(LiteralExpr)(previous().lexeme, true);
|
||||
if(match({STRING})) return msptr(LiteralExpr)(previous().lexeme, false);
|
||||
if(match({NUMBER})) return msptr(LiteralExpr)(previous().lexeme, true, false);
|
||||
if(match({STRING})) return msptr(LiteralExpr)(previous().lexeme, false, false);
|
||||
|
||||
if(match({OPEN_PAREN}))
|
||||
{
|
||||
|
||||
@ -51,11 +51,7 @@ void Bob::run(string source)
|
||||
vector<Token> tokens = lexer.Tokenize(source);
|
||||
Parser p(tokens);
|
||||
shared_ptr<Expr> expr = p.parse();
|
||||
|
||||
|
||||
ASTPrinter printer;
|
||||
|
||||
cout << dynamic_pointer_cast<String>(printer.print(expr.get()))->value << endl;
|
||||
interpreter.interpret(expr);
|
||||
|
||||
|
||||
for(Token t : tokens){
|
||||
|
||||
Loading…
Reference in New Issue
Block a user