diff --git a/headers/ASTPrinter.h b/headers/ASTPrinter.h new file mode 100644 index 0000000..adc4d2d --- /dev/null +++ b/headers/ASTPrinter.h @@ -0,0 +1,18 @@ +#pragma once +#include "Expression.h" +#include +#include + +class ASTPrinter : public Visitor +{ + std::string visitBinaryExpr(BinaryExpr* expression) override; +// std::string visitGroupingExpr(GroupingExpr expression); + std::string visitLiteralExpr(LiteralExpr* expression) override; + std::string visitUnaryExpr(UnaryExpr* expression) override; +public: + int test = 10; + std::string print(Expr* expr); +private: + std::string parenthesize(std::string name, std::vector > > exprs); + +}; \ No newline at end of file diff --git a/headers/Expression.h b/headers/Expression.h index ef21c20..a911617 100644 --- a/headers/Expression.h +++ b/headers/Expression.h @@ -5,45 +5,74 @@ #pragma once #include "Lexer.h" #include + +template +struct Visitor; + +template struct Expr{ - virtual ~Expr() - { - - } + virtual T accept(Visitor* visitor) = 0; + virtual ~Expr(){} }; -struct BinaryExpr : Expr +template +struct BinaryExpr : Expr { - const Expr left; + const std::shared_ptr > left; const Token oper; - const Expr right; + const std::shared_ptr > right; - BinaryExpr(Expr left, Token oper, Expr right) : left(left), oper(oper), right(right) + BinaryExpr(std::shared_ptr > left, Token oper, std::shared_ptr > right) : left(left), oper(oper), right(right) { } -}; -struct GroupingExpr : Expr -{ - const Expr expression; - - GroupingExpr(Expr expression) : expression(expression) - { + T accept(Visitor* visitor) override{ + return visitor->visitBinaryExpr(this); } }; -struct LiteralExpr : Expr +//template +//struct GroupingExpr : Expr, Visitor +//{ +// Expr expression; +// +// GroupingExpr(Expr expression) : expression(expression) +// { +// } +// T accept(Visitor visitor){ +// return visitor.visitGroupingExpr(this); +// } +//}; +template +struct LiteralExpr : Expr { const std::string value; LiteralExpr(std::string value) : value(value) { } -}; -struct UnaryExpr : Expr -{ - const Token oper; - const Expr right; - - UnaryExpr(Token oper, Expr right) : oper(oper), right(right) - { + T accept(Visitor* visitor) override{ + return visitor->visitLiteralExpr(this); } }; +template +struct UnaryExpr : Expr +{ + const Token oper; + const std::shared_ptr > right; + + UnaryExpr(Token oper, std::shared_ptr > right) : oper(oper), right(right) + { + } + T accept(Visitor* visitor) override{ + return visitor->visitUnaryExpr(this); + } +}; + +//// +template +struct Visitor +{ + virtual T visitBinaryExpr(BinaryExpr* expression) = 0; +// virtual T visitGroupingExpr(GroupingExpr expression){}; + virtual T visitLiteralExpr(LiteralExpr* expression) = 0; + virtual T visitUnaryExpr(UnaryExpr* expression) = 0; +}; diff --git a/headers/helperFunctions/HelperFunctions.h b/headers/helperFunctions/HelperFunctions.h index e0aae20..7738f09 100644 --- a/headers/helperFunctions/HelperFunctions.h +++ b/headers/helperFunctions/HelperFunctions.h @@ -37,4 +37,16 @@ std::string trim(const std::string& str) { // Extract the trimmed substring return str.substr(start, end - start + 1); +} + +std::string replaceSubstring(const std::string& str, const std::string& findSubstring, const std::string& replacement) { + std::string result = str; + size_t startPos = result.find(findSubstring); + + while (startPos != std::string::npos) { + result.replace(startPos, findSubstring.length(), replacement); + startPos = result.find(findSubstring, startPos + replacement.length()); + } + + return result; } \ No newline at end of file diff --git a/source/ASTPrinter.cpp b/source/ASTPrinter.cpp new file mode 100644 index 0000000..9ac6c7c --- /dev/null +++ b/source/ASTPrinter.cpp @@ -0,0 +1,43 @@ +// +// Created by Bobby Lucero on 5/23/23. +// +#include "../headers/ASTPrinter.h" + + +std::string ASTPrinter::visitBinaryExpr(BinaryExpr* expression){ + std::cout << expression->left << std::endl; + return parenthesize(expression->oper.lexeme, std::vector > >{expression->left, expression->right}); +} + +//std::string ASTPrinter::visitGroupingExpr(GroupingExpr expression){ +// return "hi"; +//} +std::string ASTPrinter::visitLiteralExpr(LiteralExpr* expression){ + return expression->value; +} +std::string ASTPrinter::visitUnaryExpr(UnaryExpr* expression){ + return parenthesize(expression->oper.lexeme, std::vector > >{expression->right}); +} + +std::string ASTPrinter::print(Expr *expr) { + return expr->accept(this); +} + +std::string ASTPrinter::parenthesize(std::string name, std::vector > > exprs) { + std::string builder; + + builder += "(" + name; + + for(std::shared_ptr > expr : exprs) + { + std::cout << expr << std::endl; + + builder += " "; + builder += expr->accept(this); + } + + builder += ")"; + + return builder; + +} diff --git a/source/main.cpp b/source/main.cpp index d49ca38..8042f78 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,37 +1,44 @@ // // Created by Bobby Lucero on 5/21/23. // + + #include "../headers/bob.h" #include "../headers/Expression.h" #include "../headers/Lexer.h" +#include "../headers/ASTPrinter.h" int main(){ Bob bobLang; //bobLang.runFile("source.bob"); + ASTPrinter printer; - Expr a; - Expr b; - Token t = {PLUS, "+", 1}; - Token t2 = {MINUS, "-", 1}; - BinaryExpr e = BinaryExpr(a, t, b); + std::shared_ptr > expression = std::make_shared >( + std::make_shared >( + Token{MINUS, "-", 0}, + std::make_shared >("123") + ), + Token{STAR, "*", 0}, + std::make_shared >( + Token{MINUS, "+", 0}, + std::make_shared >("987") + ) + ); - std::shared_ptr any = std::make_shared(a, t, b); - if(std::shared_ptr binexpr = std::dynamic_pointer_cast(any)) - { - std::cout << binexpr->oper.lexeme; - } +// Expr* e = new BinaryExpr( +// new UnaryExpr(Token{MINUS, "-", 0}, new LiteralExpr("123")), +// Token{STAR, "*", 0}, +// new UnaryExpr(Token{PLUS, "+", 0}, new LiteralExpr("535")) +// ); + LiteralExpr* le = new LiteralExpr("123"); - any = std::make_shared(a, t2, b); - if(std::shared_ptr binexpr = std::dynamic_pointer_cast(any)) - { - std::cout << binexpr->oper.lexeme; - } + std::cout << printer.print(expression.get()); std::cout << std::endl; - bobLang.runPrompt(); + //bobLang.runPrompt(); return 0; } diff --git a/testthing b/testthing index c250188..a1ced34 100644 --- a/testthing +++ b/testthing @@ -1,35 +1,51 @@ -struct BinaryExpr : Expr +template +struct BinaryExpr : Expr, Visitor { - const Expr left; + const Expr left; const Token oper; - const Expr right; + const Expr right; - BinaryExpr(Expr left, Token oper, Expr right) : left(left), oper(oper), right(right) + BinaryExpr(Expr left, Token oper, Expr right) : left(left), oper(oper), right(right) { } + T accept(Visitor visitor){ + return visitor.visitBinaryExpr(this); + } }; -struct GroupingExpr : Expr +template +struct GroupingExpr : Expr, Visitor { - const Expr expression; + const Expr expression; - GroupingExpr(Expr expression) : expression(expression) + GroupingExpr(Expr expression) : expression(expression) { } + T accept(Visitor visitor){ + return visitor.visitGroupingExpr(this); + } }; -struct LiteralExpr : Expr +template +struct LiteralExpr : Expr, Visitor { const std::string value; LiteralExpr(std::string value) : value(value) { } -}; -struct UnaryExpr : Expr -{ - const Token oper; - const Expr right; - - UnaryExpr(Token oper, Expr right) : oper(oper), right(right) - { + T accept(Visitor visitor){ + return visitor.visitLiteralExpr(this); + } +}; +template +struct UnaryExpr : Expr, Visitor +{ + const Token oper; + const Expr right; + + UnaryExpr(Token oper, Expr right) : oper(oper), right(right) + { + } + T accept(Visitor visitor){ + return visitor.visitUnaryExpr(this); } }; diff --git a/tools/GenerateAST b/tools/GenerateAST index 20ee1ae..f7a7ff6 100755 Binary files a/tools/GenerateAST and b/tools/GenerateAST differ diff --git a/tools/GenerateAST.cpp b/tools/GenerateAST.cpp index ae78bb9..3f672be 100644 --- a/tools/GenerateAST.cpp +++ b/tools/GenerateAST.cpp @@ -8,21 +8,29 @@ void defineType(std::ofstream &out, std::string baseName, std::string className, std::string fieldList) { - out << "struct " << className << "Expr : " << baseName << "\n{\n"; + out << "template \n"; + out << "struct " << className << "Expr : " << baseName << "" << ", Visitor" << "\n{\n"; std::vector fields = splitString(fieldList, ", "); for(std::string field : fields) { - out << " const " << trim(field) << ";\n"; + std::cout << trim(field) << std::endl; + std::string fieldClass = splitString(trim(field), " ")[0]; + std::string fieldName = splitString(trim(field), " ")[1]; + fieldClass = trim(fieldClass) == "Expr" ? "Expr" : trim(fieldClass); + out << " const " << fieldClass << " " << fieldName << ";\n"; } - + fieldList = replaceSubstring(fieldList, "Expr", "Expr"); out << "\n " << className << "Expr(" << fieldList << ") : "; std::string explicitDeclaration; for(std::string field : fields) { - std::string name = splitString(trim(field), " ")[1]; + std::cout << trim(field) << std::endl; + std::string fieldClass = splitString(trim(field), " ")[0]; + std::string fieldName = splitString(trim(field), " ")[1]; + fieldClass = trim(fieldClass) == "Expr" ? "Expr" : trim(fieldClass); - explicitDeclaration += trim(name) + "(" + trim(name) + "), "; + explicitDeclaration += trim(fieldName) + "(" + trim(fieldName) + "), "; } explicitDeclaration = trim(explicitDeclaration); explicitDeclaration.pop_back(); @@ -31,6 +39,11 @@ void defineType(std::ofstream &out, std::string baseName, std::string className, out << "\n {\n"; out << " }\n"; + + out << " T accept(Visitor visitor){\n"; + out << " return visitor.visit" << className << "Expr(this);\n"; + out << " }\n"; + out << "};" << std::endl; }