diff options
| Commit | d5cb498ba37949193fecafa8c1f15d70ade79515 (patch) | |
|---|---|---|
| Author | 2018-10-21 21:27:36 +0300 | |
| Committer | 2018-10-24 19:43:48 +0300 | |
| Files | dbf7da8806366afa5d435ff6a3e9d1adf397aa77 /JSImpl/src | |
| IPL-d5cb498ba37949193fecafa8c1f15d70ade79515.tar IPL-d5cb498ba37949193fecafa8c1f15d70ade79515.tar.gz IPL-d5cb498ba37949193fecafa8c1f15d70ade79515.zip | ||
| Parent | d57561ef43c80fa6050e80f4876a45ba886818ff (diff) | |
Added a tree interpreter
3 files changed, 221 insertions, 1 deletions
| -rw-r--r-- | JSImpl/src/ASTInterpreter.cpp | 154 | ||||
| -rw-r--r-- | JSImpl/src/ASTInterpreter.h | 44 | ||||
| -rw-r--r-- | JSImpl/src/main.cpp | 24 |
diff --git a/JSImpl/src/ASTInterpreter.cpp b/JSImpl/src/ASTInterpreter.cpp new file mode 100644 index 0000000..7ce6d59 --- /dev/null +++ b/JSImpl/src/ASTInterpreter.cpp @@ -0,0 +1,154 @@ +#include "ASTInterpreter.h" +#include "Expression.h" +#include <cassert> +#include <iostream> + +ASTInterpreter::ASTInterpreter() +{} + +ASTInterpreter::~ASTInterpreter() +{} + +ASTInterpreter::ValueStack ASTInterpreter::Run(Expression* program) +{ + program->Accept(*this); + ValueStack result; + m_Evaluation.swap(result); + return result; +} + +void ASTInterpreter::RunExpression(const ExpressionPtr& e) +{ + if (e) { + e->Accept(*this); + } +} + +bool ASTInterpreter::EvalToBool(const ExpressionPtr& e) +{ + e->Accept(*this); + auto result = m_Evaluation.top(); + m_Evaluation.pop(); + return result != 0.0; +} + +#define NOT_IMPLEMENTED (void)e; assert(0 && "not-implemented") + +void ASTInterpreter::Visit(LiteralNull* e) { + NOT_IMPLEMENTED; +} + +void ASTInterpreter::Visit(LiteralUndefined* e) { + NOT_IMPLEMENTED; +} +void ASTInterpreter::Visit(LiteralString* e) { + NOT_IMPLEMENTED; +} + +void ASTInterpreter::Visit(LiteralNumber* e) { + m_Evaluation.push(e->GetValue()); +} +void ASTInterpreter::Visit(LiteralBoolean* e) { + m_Evaluation.push(e->GetValue()); +} + +void ASTInterpreter::Visit(BinaryExpression* e) { + e->GetLeft()->Accept(*this); + e->GetRight()->Accept(*this); + auto right = m_Evaluation.top(); + m_Evaluation.pop(); + + auto left = m_Evaluation.top(); + m_Evaluation.pop(); + + switch (e->GetOperator()) { + case TokenType::Plus: + std::cout << "PLUS:" << left << ':' << right << std::endl; + m_Evaluation.push(left + right); + break; + case TokenType::Minus: + m_Evaluation.push(left - right); + break; + case TokenType::Star: + m_Evaluation.push(left * right); + break; + case TokenType::Division: + m_Evaluation.push(left / right); + break; + default: + NOT_IMPLEMENTED; + } +} + +void ASTInterpreter::Visit(UnaryExpression* e) { + NOT_IMPLEMENTED; +} + +void ASTInterpreter::Visit(IdentifierExpression* e) { + auto values = m_Variables.find(e->GetName()); + if (values != m_Variables.end()) { + m_Evaluation.push(values->second.top()); + } else { + throw "Not-defined"; + } +} +void ASTInterpreter::Visit(ListExpression* e) { + for (const auto& stmt: e->GetValues()) { + stmt->Accept(*this); + } +} + +void ASTInterpreter::Visit(VariableDefinitionExpression* e) { + e->GetValue()->Accept(*this); + m_Variables[e->GetName()].push(m_Evaluation.top()); + m_Evaluation.pop(); +} + +void ASTInterpreter::Visit(BlockStatement* e) { + for (const auto& stmt: e->GetValues()) { + stmt->Accept(*this); + } +} + +void ASTInterpreter::Visit(LabeledStatement* e) { + RunExpression(e->GetStatement()); +} + +void ASTInterpreter::Visit(IfStatement* e) { + if (EvalToBool(e->GetCondition())) { + RunExpression(e->GetIfStatement()); + } else { + RunExpression(e->GetElseStatement()); + } +} + +void ASTInterpreter::Visit(SwitchStatement* e) { NOT_IMPLEMENTED;} +void ASTInterpreter::Visit(CaseStatement *e) { NOT_IMPLEMENTED;} + +void ASTInterpreter::Visit(WhileStatement* e) { + if (e->GetDoWhile()) { + RunExpression(e->GetBody()); + } + while (EvalToBool(e->GetCondition())) { + RunExpression(e->GetBody()); + } +} + +void ASTInterpreter::Visit(ForStatement* e) { + for (RunExpression(e->GetInitialization()); + EvalToBool(e->GetCondition()); + RunExpression(e->GetIteration())) { + RunExpression(e->GetBody()); + } +} + +void ASTInterpreter::Visit(FunctionDeclaration* e) { NOT_IMPLEMENTED;} +void ASTInterpreter::Visit(TopStatements* e) { + for (const auto& stmt: e->GetValues()) { + stmt->Accept(*this); + } +} + +void ASTInterpreter::Visit(EmptyExpression* e) { + NOT_IMPLEMENTED; +} diff --git a/JSImpl/src/ASTInterpreter.h b/JSImpl/src/ASTInterpreter.h new file mode 100644 index 0000000..1ffecde --- /dev/null +++ b/JSImpl/src/ASTInterpreter.h @@ -0,0 +1,44 @@ +#pragma once + +#include "ExpressionVisitor.h" +#include <stack> +#include <string> +#include <unordered_map> + +class ASTInterpreter : public ExpressionVisitor +{ +public: + ASTInterpreter(); + ~ASTInterpreter(); + + typedef double value_type; + typedef std::stack<value_type> ValueStack; + + ValueStack Run(Expression* program); + + virtual void Visit(LiteralNull* e) override; + virtual void Visit(LiteralUndefined* e) override; + virtual void Visit(LiteralString* e) override; + virtual void Visit(LiteralNumber* e) override; + virtual void Visit(LiteralBoolean* e) override; + virtual void Visit(BinaryExpression* e) override; + virtual void Visit(UnaryExpression* e) override; + virtual void Visit(IdentifierExpression* e) override; + virtual void Visit(ListExpression* e) override; + virtual void Visit(VariableDefinitionExpression* e) override; + virtual void Visit(BlockStatement* e) override; + virtual void Visit(LabeledStatement* e) override; + virtual void Visit(IfStatement* e) override; + virtual void Visit(SwitchStatement* e) override; + virtual void Visit(CaseStatement *) override; + virtual void Visit(WhileStatement* e) override; + virtual void Visit(ForStatement* e) override; + virtual void Visit(FunctionDeclaration* e) override; + virtual void Visit(TopStatements* e) override; + virtual void Visit(EmptyExpression* e) override; +private: + void RunExpression(const ExpressionPtr& e); + bool EvalToBool(const ExpressionPtr& e); + ValueStack m_Evaluation; + std::unordered_map<std::string, ValueStack> m_Variables; +}; diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp index 73f883f..80dcd32 100644 --- a/JSImpl/src/main.cpp +++ b/JSImpl/src/main.cpp @@ -1,6 +1,7 @@ #include "Lexer.h" #include "Parser.h" #include "ASTPrinter.h" +#include "ASTInterpreter.h" #include <iostream> #define LOG(msg) std::cout << msg << std::endl #define EXECUTE_TEST(test) std::cout << #test << " "; test(); @@ -198,6 +199,26 @@ void TestParseUnaryExpr() expr->Accept(p); } +void RunParseCalc() +{ + IPLVector<Token> tokens; + //Tokenize("var a = 0; var b = a + 123;a+b;", tokens); + Tokenize("123 + 321", tokens); + + // TODO make actual test :D + auto expr = Parse(tokens); + ASTPrinter p(std::cout); + expr->Accept(p); + ASTInterpreter i; + std::cout << "Running" << std::endl; + auto result = i.Run(expr.get()); + std::cout << "Stack after run, top to bottom:" << std::endl; + while (!result.empty()) { + std::cout << result.top() << std::endl; + result.pop(); + } +} + void TestHexNumber() { IPLVector<Token> tokens; @@ -235,7 +256,8 @@ int main() EXECUTE_TEST(TestHexNumber); EXECUTE_TEST(TestScientificNotationNumber); - // TestParseUnaryExpr(); + //TestParseUnaryExpr(); + //RunParseCalc(); #if defined(_WIN32) std::system("pause"); #endif |
