diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..20aff15
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/headers/Expression.h b/headers/Expression.h
index dc4b053..6f5b1f5 100644
--- a/headers/Expression.h
+++ b/headers/Expression.h
@@ -28,7 +28,7 @@ struct ExprVisitor
struct Expr{
virtual sptr(Object) accept(ExprVisitor* visitor) = 0;
- virtual ~Expr(){}
+ virtual ~Expr() = default;
};
struct AssignExpr : Expr, public std::enable_shared_from_this
diff --git a/headers/Interpreter.h b/headers/Interpreter.h
index 5e7def7..9380e63 100644
--- a/headers/Interpreter.h
+++ b/headers/Interpreter.h
@@ -23,25 +23,21 @@ public:
void interpret(std::vector statements);
- Interpreter(){
+ explicit Interpreter(bool IsInteractive) : IsInteractive(IsInteractive){
environment = msptr(Environment)();
}
+ ~Interpreter();
private:
sptr(Environment) environment;
-
-
+ bool IsInteractive;
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);
-
bool isWholeNumer(double num);
-
void execute(std::shared_ptr statement);
-
void executeBlock(std::vector> statements, std::shared_ptr env);
};
diff --git a/headers/Lexer.h b/headers/Lexer.h
index 134125f..8459ae6 100644
--- a/headers/Lexer.h
+++ b/headers/Lexer.h
@@ -8,7 +8,7 @@ enum TokenType{
OPEN_PAREN, CLOSE_PAREN, OPEN_BRACE, CLOSE_BRACE,
COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR, PERCENT,
- BINARY_OP,
+ BIN_OR, BIN_AND, BIN_NOT, BIN_XOR, BIN_SLEFT, BIN_SRIGHT,
BANG, BANG_EQUAL,
EQUAL, DOUBLE_EQUAL,
@@ -56,7 +56,8 @@ const std::map KEYWORDS {
{"this", THIS},
{"none", NONE},
{"return", RETURN},
- {"print", PRINT}
+ {"print", PRINT},
+
};
struct Token
diff --git a/headers/Parser.h b/headers/Parser.h
index 92ad4cc..0759891 100644
--- a/headers/Parser.h
+++ b/headers/Parser.h
@@ -26,14 +26,14 @@ private:
sptr(Expr) unary();
sptr(Expr) primary();
- bool match(std::vector types);
+ bool match(const std::vector& types);
bool check(TokenType type);
bool isAtEnd();
Token advance();
Token peek();
Token previous();
- Token consume(TokenType type, std::string message);
+ Token consume(TokenType type, const std::string& message);
sptr(Stmt) statement();
void sync();
diff --git a/headers/bob.h b/headers/bob.h
index af73f19..5058dfb 100644
--- a/headers/bob.h
+++ b/headers/bob.h
@@ -12,14 +12,19 @@ class Bob
{
public:
Lexer lexer;
- Interpreter interpreter;
+ Interpreter* interpreter;
+
+ ~Bob()
+ {
+ delete interpreter;
+ }
public:
- void runFile(std::string path);
+ void runFile(const std::string& path);
void runPrompt();
- void error(int line, std::string message);
+ void error(int line, const std::string& message);
private:
diff --git a/source/Interpreter.cpp b/source/Interpreter.cpp
index ec5aef8..de6a383 100644
--- a/source/Interpreter.cpp
+++ b/source/Interpreter.cpp
@@ -58,6 +58,19 @@ sptr(Object) Interpreter::visitUnaryExpr(sptr(UnaryExpr) expression)
return msptr(Boolean)(!isTruthy(right));
}
+ if(expression->oper.type == BIN_NOT)
+ {
+ if(std::dynamic_pointer_cast(right))
+ {
+ double value = std::dynamic_pointer_cast(right)->value;
+ return msptr(Number)((~(long)value));
+ }
+ else
+ {
+ throw std::runtime_error("Operand must be an int when using: " + expression->oper.lexeme);
+ }
+ }
+
//unreachable
throw std::runtime_error("Invalid unary expression");
@@ -162,7 +175,10 @@ void Interpreter::visitBlockStmt(std::shared_ptr statement) {
}
void Interpreter::visitExpressionStmt(sptr(ExpressionStmt) statement) {
- evaluate(statement->expression);
+ sptr(Object) value = evaluate(statement->expression);
+
+ if(IsInteractive)
+ std::cout << "\u001b[38;5;8m[" << stringify(value) << "]\u001b[38;5;15m" << std::endl;
}
void Interpreter::visitPrintStmt(sptr(PrintStmt) statement) {
@@ -336,6 +352,8 @@ bool Interpreter::isWholeNumer(double num) {
}
}
+Interpreter::~Interpreter() = default;
+
diff --git a/source/Lexer.cpp b/source/Lexer.cpp
index e48b6ae..25b2b37 100644
--- a/source/Lexer.cpp
+++ b/source/Lexer.cpp
@@ -68,6 +68,11 @@ std::vector Lexer::Tokenize(std::string source){
tokens.push_back(Token{PERCENT, std::string(1, t), line});
advance();
}
+ else if(t == '~')
+ {
+ tokens.push_back(Token{BIN_NOT, std::string(1, t), line});
+ advance();
+ }
else if(t == '=')
{
std::string token = std::string(1, t);
@@ -88,9 +93,19 @@ std::vector Lexer::Tokenize(std::string source){
{
std::string token = std::string(1, t);
advance();
- bool match = matchOn('=');
- token += match ? "=" : "";
- tokens.push_back(Token{match ? LESS_EQUAL : LESS, token, line});
+ if(matchOn('='))
+ {
+ tokens.push_back(Token{LESS_EQUAL, "<=", line});
+ }
+ else if(matchOn('<'))
+ {
+ tokens.push_back(Token{BIN_SLEFT, "<<", line});
+ }
+ else
+ {
+ tokens.push_back(Token{LESS, token, line});
+ }
+
}
else if(t == '>')
{
diff --git a/source/Parser.cpp b/source/Parser.cpp
index 7b68d49..d6922d9 100644
--- a/source/Parser.cpp
+++ b/source/Parser.cpp
@@ -96,7 +96,7 @@ sptr(Expr) Parser::factor()
sptr(Expr) Parser::unary()
{
- if(match({BANG, MINUS}))
+ if(match({BANG, MINUS, BIN_NOT}))
{
Token op = previous();
sptr(Expr) right = unary();
@@ -144,6 +144,32 @@ std::vector Parser::parse() {
}
+sptr(Stmt) Parser::declaration()
+{
+ try{
+ if(match({VAR})) return varDeclaration();
+ return statement();
+ }
+ catch(std::runtime_error& e)
+ {
+ sync();
+ throw std::runtime_error(e.what());
+ }
+}
+
+sptr(Stmt) Parser::varDeclaration()
+{
+ Token name = consume(IDENTIFIER, "Expected variable name.");
+
+ sptr(Expr) initializer = msptr(LiteralExpr)("none", false, true);
+ if(match({EQUAL}))
+ {
+ initializer = expression();
+ }
+ consume(SEMICOLON, "Expected ';' after variable declaration.");
+ return msptr(VarStmt)(name, initializer);
+}
+
sptr(Stmt) Parser::statement()
{
if(match({PRINT})) return printStatement();
@@ -178,35 +204,11 @@ std::vector Parser::block()
return statements;
}
-sptr(Stmt) Parser::declaration()
-{
- try{
- if(match({VAR})) return varDeclaration();
- return statement();
- }
- catch(std::runtime_error e)
- {
- sync();
- throw std::runtime_error(e.what());
- }
-}
-
-sptr(Stmt) Parser::varDeclaration()
-{
- Token name = consume(IDENTIFIER, "Expected variable name.");
-
- sptr(Expr) initializer = msptr(LiteralExpr)("none", false, true);
- if(match({EQUAL}))
- {
- initializer = expression();
- }
- consume(SEMICOLON, "Expected ';' after variable declaration.");
- return msptr(VarStmt)(name, initializer);
-}
-bool Parser::match(std::vector types) {
+
+bool Parser::match(const std::vector& types) {
for(TokenType t : types)
{
if(check(t))
@@ -241,10 +243,10 @@ Token Parser::previous() {
return tokens[current - 1];
}
-Token Parser::consume(TokenType type, std::string message) {
+Token Parser::consume(TokenType type, const std::string& message) {
if(check(type)) return advance();
- throw std::runtime_error(peek().lexeme +": "+ message);
+ throw std::runtime_error("Unexpected symbol '" + peek().lexeme +"': "+ message);
}
void Parser::sync()
diff --git a/source/bob.cpp b/source/bob.cpp
index 4198651..c055619 100644
--- a/source/bob.cpp
+++ b/source/bob.cpp
@@ -1,13 +1,16 @@
+#include
+
#include "../headers/bob.h"
#include "../headers/Parser.h"
#include "../headers/ASTPrinter.h"
using namespace std;
-void Bob::runFile(string path)
+void Bob::runFile(const string& path)
{
+ this->interpreter = new Interpreter(false);
ifstream file = ifstream(path);
- string source = "";
+ string source;
if(file.is_open()){
source = string(istreambuf_iterator(file), istreambuf_iterator());
@@ -23,6 +26,8 @@ void Bob::runFile(string path)
void Bob::runPrompt()
{
+ this->interpreter = new Interpreter(true);
+
cout << "Bob v" << VERSION << ", 2023" << endl;
for(;;)
{
@@ -40,7 +45,7 @@ void Bob::runPrompt()
}
}
-void Bob::error(int line, string message)
+void Bob::error(int line, const string& message)
{
}
@@ -48,7 +53,7 @@ void Bob::error(int line, string message)
void Bob::run(string source)
{
try {
- vector tokens = lexer.Tokenize(source);
+ vector tokens = lexer.Tokenize(std::move(source));
// for(Token t : tokens){
// cout << "{type: " << enum_mapping[t.type] << ", value: " << t.lexeme << "}" << endl;
// }
@@ -56,7 +61,7 @@ void Bob::run(string source)
Parser p(tokens);
vector statements = p.parse();
- interpreter.interpret(statements);
+ interpreter->interpret(statements);
//cout << "=========================" << endl;
diff --git a/source/main.cpp b/source/main.cpp
index 3c74612..bfbf871 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -1,15 +1,13 @@
//
// Created by Bobby Lucero on 5/21/23.
//
-
-
#include "../headers/bob.h"
int main(){
Bob bobLang;
bobLang.runFile("source.bob");
- //bobLang.runPrompt();
+ bobLang.runPrompt();
return 0;
}