Skip to content

Commit

Permalink
Working variable assignment & retrievement
Browse files Browse the repository at this point in the history
  • Loading branch information
Samathingamajig committed Feb 20, 2021
1 parent fabd0fd commit 4054e1e
Show file tree
Hide file tree
Showing 20 changed files with 253 additions and 11 deletions.
5 changes: 3 additions & 2 deletions BarkScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
#include "interpreter/interpreter.h"
#include "context/context.h"

const std::string bsversion = "0.0.12";
const std::string bsversion = "0.1.0";

int main() {
std::cout << "BarkScript version " << bsversion << std::endl;
spContext context = std::make_shared<Context>(Context("<main>"));
context->symbolTable = std::make_shared<SymbolTable>(SymbolTable());
while (true) {
//std::string input = "5+55";
std::string input;
Expand Down Expand Up @@ -42,7 +44,6 @@ int main() {
std::cout << std::endl;

Interpreter interpreter;
spContext context = std::make_shared<Context>(Context("<main>"));
RuntimeResult rt = interpreter.visit(abSyTree.node, context);
if (rt.hasError()) {
std::cout << rt.error->to_string() << std::endl;
Expand Down
3 changes: 3 additions & 0 deletions BarkScript.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
<ClCompile Include="lexer/Lexer.cpp" />
<ClCompile Include="object/Object.cpp" />
<ClCompile Include="parser/Parser.cpp" />
<ClCompile Include="symboltable/SymbolTable.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ast/ast.h" />
Expand All @@ -154,7 +155,9 @@
<ClInclude Include="object/object.h" />
<ClInclude Include="parser/parser.h" />
<ClInclude Include="position/position.h" />
<ClInclude Include="reservedwords/reservedwords.h" />
<ClInclude Include="strings_with_arrows/strings_with_arrows.h" />
<ClInclude Include="symboltable/symboltable.h" />
<ClInclude Include="token/token.h" />
<ClInclude Include="token/tokens.h" />
</ItemGroup>
Expand Down
9 changes: 9 additions & 0 deletions BarkScript.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
<ClCompile Include="object/Object.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="symboltable/SymbolTable.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="token/tokens.h">
Expand Down Expand Up @@ -66,5 +69,11 @@
<ClInclude Include="context/context.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="reservedwords/reservedwords.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="symboltable/symboltable.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
windowsvs : build BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp
windowsvs : build BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp symboltable/SymbolTable.cpp
.\build.bat

linuxgpp : build BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp
g++ -o ./build/BarkScript -O2 -Wall BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp
linuxgpp : build BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp symboltable/SymbolTable.cpp
g++ -o ./build/BarkScript -O2 -Wall BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp symboltable/SymbolTable.cpp

cleanobj :
rm *.obj
Expand Down
31 changes: 31 additions & 0 deletions ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
#include <memory>
#include "../token/token.h"
#include "../position/position.h"
#include "../symboltable/symboltable.h"

namespace nodetypes {
using namespace std;

const string Number = "NUMBER";
const string VariableAssignment = "VARASS";
const string VariableRetrievement = "VARRET";
const string BinaryOperator = "BINOP";
const string UnaryOperator = "UNOP";
const string Error = "ERROR";
Expand Down Expand Up @@ -41,6 +44,7 @@ struct Node {

spNode leftNode;
spNode rightNode;
spNode valueNode;
};

struct NumberNode : Node {
Expand All @@ -56,6 +60,33 @@ struct NumberNode : Node {
}
};

struct VariableAssignmentNode : Node {
VariableAssignmentNode(Token token, spNode valueNode) {
this->nodeType = nodetypes::VariableAssignment;
this->token = token;
this->valueNode = valueNode;
this->positionStart = token.positionStart;
this->positionEnd = valueNode->positionEnd;
}

std::string to_string() override {
return token.value + " = " + valueNode->to_string();
}
};

struct VariableRetrievementNode : Node {
VariableRetrievementNode(Token token) {
this->nodeType = nodetypes::VariableRetrievement;
this->token = token;
this->positionStart = token.positionStart;
this->positionEnd = token.positionEnd;
}

std::string to_string() override {
return token.value;
}
};

struct BinaryOperatorNode : Node {
BinaryOperatorNode(spNode leftNode, Token token, spNode rightNode) {
this->nodeType = nodetypes::BinaryOperator;
Expand Down
2 changes: 1 addition & 1 deletion build.bat
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && cl.exe /EHsc BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp /link /out:build/BarkScript.exe
"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && cl.exe /EHsc BarkScript.cpp lexer/Lexer.cpp parser/Parser.cpp object/Object.cpp interpreter/Interpreter.cpp symboltable/SymbolTable.cpp /link /out:build/BarkScript.exe
2 changes: 2 additions & 0 deletions context/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <memory>
#include <string>
#include "../position/position.h"
#include "../symboltable/symboltable.h"

struct Context;

Expand All @@ -13,6 +14,7 @@ struct Context {
std::string displayName = "UNKNOWN_CONTEXT_NAME";
spContext parent;
Position parentEntryPosition;
spSymbolTable symbolTable;

Context(std::string displayName, spContext parent = nullptr, Position parentEntryPosition = Position()) {
this->displayName = displayName;
Expand Down
26 changes: 26 additions & 0 deletions interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ RuntimeResult Interpreter::visit(spNode node, spContext context) {

if (type == nodetypes::Number) {
return visitNumberNode(node, context);
} else if (type == nodetypes::VariableAssignment) {
return visitVariableAssignmentNode(node, context);
} else if (type == nodetypes::VariableRetrievement) {
return visitVariableRetrievementNode(node, context);
} else if (type == nodetypes::BinaryOperator) {
return visitBinaryOperatorNode(node, context);
} else if (type == nodetypes::UnaryOperator) {
Expand All @@ -49,6 +53,28 @@ RuntimeResult Interpreter::visitNumberNode(spNode node, spContext context) {
return RuntimeResult().success(number);
}

RuntimeResult Interpreter::visitVariableAssignmentNode(spNode node, spContext context) {
RuntimeResult rt;
std::string variableName = node->token.value;
spObject value = rt.registerRT(visit(node->valueNode, context));
if (rt.hasError()) return rt;
bool success = context->symbolTable->set(variableName, value, true);
if (!success)
return rt.failure(makeSharedError(RuntimeError(node->token.positionStart, node->positionEnd, "Variable not reassigned properly", context)));
return rt.success(value);
}

RuntimeResult Interpreter::visitVariableRetrievementNode(spNode node, spContext context) {
RuntimeResult rt;
std::string variableName = node->token.value;
spObject value = context->symbolTable->get(variableName);
if (value == nullptr)
return rt.failure(makeSharedError(RuntimeError(node->positionStart, node->positionEnd, "Variable \"" + variableName + "\" is not defined in the current scope!", context)));
value = value->copy();
value->setPosition(node->positionStart, node->positionEnd);
return rt.success(value);
}

RuntimeResult Interpreter::visitBinaryOperatorNode(spNode node, spContext context) {
RuntimeResult rt;
spObject left = rt.registerRT(visit(node->leftNode, context));
Expand Down
2 changes: 2 additions & 0 deletions interpreter/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ struct Interpreter {
RuntimeResult visit(spNode node, spContext context);

RuntimeResult visitNumberNode(spNode node, spContext context);
RuntimeResult visitVariableAssignmentNode(spNode node, spContext context);
RuntimeResult visitVariableRetrievementNode(spNode node, spContext context);
RuntimeResult visitBinaryOperatorNode(spNode node, spContext context);
RuntimeResult visitUnaryOperatorNode(spNode node, spContext context);
};
Expand Down
33 changes: 32 additions & 1 deletion lexer/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../token/tokens.h"
#include "../position/position.h"
#include "../error/error.h"
#include "../reservedwords/reservedwords.h"

Lexer::Lexer(std::string input, std::string filename) {
this->input = input;
Expand Down Expand Up @@ -82,6 +83,11 @@ SingleLexResult Lexer::nextToken() {
token = Token(tokens::CLOSE_PAREN, ")", position, position);
break;
}
case '=':
{
token = Token(tokens::EQUAL, "=", position, position);
break;
}
case ' ':
{
readChar();
Expand All @@ -107,6 +113,15 @@ SingleLexResult Lexer::nextToken() {
}
token = Token(tokens::NUMBER, value, positionStart, position);
break;
} else if (isIdentifierStarter(current)) {
std::string value = std::string(1, current);
Position positionStart = position.copy();
while (isIdentifierCharacter(peekChar())) {
value += peekChar();
readChar();
}
token = Token(isReservedWord(value) ? tokens::KEYWORD : tokens::IDENTIFIER, value, positionStart, position);
break;
} else {
Position positionStart = position.copy();
char tempCurrent = current;
Expand All @@ -120,7 +135,23 @@ SingleLexResult Lexer::nextToken() {
}

bool Lexer::isNumeric(char c) {
return 48 <= c && c <= 57;
return '0' <= c && c <= '9';
}

bool Lexer::isAlpha(char c) {
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}

bool Lexer::isUnderscore(char c) {
return c == '_';
}

bool Lexer::isIdentifierStarter(char c) {
return isAlpha(c) || isUnderscore(c);
}

bool Lexer::isIdentifierCharacter(char c) {
return isIdentifierStarter(c) || isNumeric(c);
}

MultiLexResult Lexer::tokenize() {
Expand Down
4 changes: 4 additions & 0 deletions lexer/lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ struct Lexer {
void readChar();
char peekChar(int num);
bool isNumeric(char c);
bool isAlpha(char c);
bool isUnderscore(char c);
bool isIdentifierStarter(char c);
bool isIdentifierCharacter(char c);
SingleLexResult nextToken();

MultiLexResult tokenize();
Expand Down
13 changes: 13 additions & 0 deletions object/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ std::string Number::to_string() {
return out.str();
}

spObject Number::copy() {
spObject other = makeSharedObject(Number());
other->doubleValue = this->doubleValue;
other->sign = this->sign;
other->isPureDouble = this->isPureDouble;
other->isPureZero = this->isPureZero;
other->isInfinity = this->isInfinity;
other->isNaN = this->isNaN;
other->setPosition(this->positionStart, this->positionEnd);
other->setContext(this->context);
return other;
}

RuntimeResult Number::binary_plus(spObject other) {
RuntimeResult rt;

Expand Down
5 changes: 4 additions & 1 deletion object/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ struct Object {
Position positionEnd;
spContext context;

void setPosition(Position positionStart, Position postionEnd);
void setPosition(Position positionStart, Position positionEnd);
void setContext(spContext context);

std::string virtual to_string() { return "to_string is not implemented for type " + this->type; };
spObject virtual copy() = 0;

RuntimeResult virtual binary_plus(spObject other) { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, other->positionEnd, "binary_plus for " + this->type + " is not implemented!", this->context))); };
RuntimeResult virtual binary_minus(spObject other) { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, other->positionEnd, "binary_minus for " + this->type + " is not implemented!", this->context))); };
Expand All @@ -59,10 +60,12 @@ struct Object {
};

struct Number : Object {
Number() { this->type = "Number"; };
Number(double value, bool sign = +1);
Number(std::string value, bool sign = +1);

std::string to_string() override;
spObject copy() override;

RuntimeResult binary_plus(spObject other) override;
RuntimeResult binary_minus(spObject other) override;
Expand Down
23 changes: 21 additions & 2 deletions parser/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../token/token.h"
#include "../token/tokens.h"
#include "../ast/ast.h"
#include "../reservedwords/reservedwords.h"

// https://stackoverflow.com/a/20303915/12101554
bool in_array(const std::string& value, const std::vector<std::string>& array) {
Expand All @@ -31,6 +32,9 @@ ParseResult Parser::atom() {
if (token.type == tokens::NUMBER) {
nextToken();
return pr.success(makeSharedNode(NumberNode(token)));
} else if (token.type == tokens::IDENTIFIER) {
nextToken();
return pr.success(makeSharedNode(VariableRetrievementNode(token)));
} else if (token.type == tokens::OPEN_PAREN) {
nextToken();
spNode exprRes = pr.registerPR(expr());
Expand Down Expand Up @@ -69,8 +73,23 @@ ParseResult Parser::term() {
}

ParseResult Parser::expr() {
std::function<ParseResult()> rule = [this]() { return term(); };
return binaryOperation(rule, { tokens::PLUS, tokens::MINUS });
if (currentToken.matches(tokens::KEYWORD, reservedWords::LET)) {
ParseResult pr;
nextToken();
if (!currentToken.matches(tokens::IDENTIFIER))
return pr.failure(makeSharedError(InvalidSyntaxError(currentToken.positionStart, currentToken.positionEnd, "Expected an identifier")));
Token variableNameToken = currentToken;
nextToken();
if (!currentToken.matches(tokens::EQUAL))
return pr.failure(makeSharedError(InvalidSyntaxError(currentToken.positionStart, currentToken.positionEnd, "Expected an '='")));
nextToken();
spNode exprRes = pr.registerPR(expr());
if (pr.hasError()) return pr;
return pr.success(makeSharedNode(VariableAssignmentNode(variableNameToken, exprRes)));
} else {
std::function<ParseResult()> rule = [this]() { return term(); };
return binaryOperation(rule, { tokens::PLUS, tokens::MINUS });
}
}

ParseResult Parser::parse() {
Expand Down
21 changes: 21 additions & 0 deletions reservedwords/reservedwords.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#ifndef RESERVEDWORDS_H
#define RESERVEDWORDS_H
#include <string>
#include <algorithm>

namespace reservedWords {
using namespace std;

const string LET = "let";
}

const std::string reservedWordsArray[] = {
reservedWords::LET,
};

inline bool isReservedWord(std::string identifier) {
return std::find(std::begin(reservedWordsArray), std::end(reservedWordsArray), identifier) != std::end(reservedWordsArray);
}

#endif // !RESERVEDWORDS_H
Loading

0 comments on commit 4054e1e

Please sign in to comment.