Rough implementation of ASTPrinter complete with nasty shared_ptr syntax :)

This commit is contained in:
Bobby Lucero 2023-05-24 00:29:12 -04:00
parent c5f981321c
commit d909e546f2
8 changed files with 199 additions and 61 deletions

18
headers/ASTPrinter.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "Expression.h"
#include <string>
#include <initializer_list>
class ASTPrinter : public Visitor<std::string>
{
std::string visitBinaryExpr(BinaryExpr<std::string>* expression) override;
// std::string visitGroupingExpr(GroupingExpr<std::string> expression);
std::string visitLiteralExpr(LiteralExpr<std::string>* expression) override;
std::string visitUnaryExpr(UnaryExpr<std::string>* expression) override;
public:
int test = 10;
std::string print(Expr<std::string>* expr);
private:
std::string parenthesize(std::string name, std::vector<std::shared_ptr<Expr<std::string> > > exprs);
};

View File

@ -5,45 +5,74 @@
#pragma once #pragma once
#include "Lexer.h" #include "Lexer.h"
#include <iostream> #include <iostream>
template <typename T>
struct Visitor;
template <typename T>
struct Expr{ struct Expr{
virtual ~Expr() virtual T accept(Visitor<T>* visitor) = 0;
{ virtual ~Expr(){}
}
}; };
struct BinaryExpr : Expr template <typename T>
struct BinaryExpr : Expr<T>
{ {
const Expr left; const std::shared_ptr<Expr<T> > left;
const Token oper; const Token oper;
const Expr right; const std::shared_ptr<Expr<T> > right;
BinaryExpr(Expr left, Token oper, Expr right) : left(left), oper(oper), right(right) BinaryExpr(std::shared_ptr<Expr<T> > left, Token oper, std::shared_ptr<Expr<T> > right) : left(left), oper(oper), right(right)
{ {
} }
}; T accept(Visitor<T>* visitor) override{
struct GroupingExpr : Expr return visitor->visitBinaryExpr(this);
{
const Expr expression;
GroupingExpr(Expr expression) : expression(expression)
{
} }
}; };
struct LiteralExpr : Expr //template <typename T>
//struct GroupingExpr : Expr<T>, Visitor<T>
//{
// Expr<T> expression;
//
// GroupingExpr(Expr<T> expression) : expression(expression)
// {
// }
// T accept(Visitor<T> visitor){
// return visitor.visitGroupingExpr(this);
// }
//};
template <typename T>
struct LiteralExpr : Expr<T>
{ {
const std::string value; const std::string value;
LiteralExpr(std::string value) : value(value) LiteralExpr(std::string value) : value(value)
{ {
} }
}; T accept(Visitor<T>* visitor) override{
struct UnaryExpr : Expr return visitor->visitLiteralExpr(this);
{
const Token oper;
const Expr right;
UnaryExpr(Token oper, Expr right) : oper(oper), right(right)
{
} }
}; };
template <typename T>
struct UnaryExpr : Expr<T>
{
const Token oper;
const std::shared_ptr<Expr<T> > right;
UnaryExpr(Token oper, std::shared_ptr<Expr<T> > right) : oper(oper), right(right)
{
}
T accept(Visitor<T>* visitor) override{
return visitor->visitUnaryExpr(this);
}
};
////
template <typename T>
struct Visitor
{
virtual T visitBinaryExpr(BinaryExpr<T>* expression) = 0;
// virtual T visitGroupingExpr(GroupingExpr<T> expression){};
virtual T visitLiteralExpr(LiteralExpr<T>* expression) = 0;
virtual T visitUnaryExpr(UnaryExpr<T>* expression) = 0;
};

View File

@ -37,4 +37,16 @@ std::string trim(const std::string& str) {
// Extract the trimmed substring // Extract the trimmed substring
return str.substr(start, end - start + 1); 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;
} }

43
source/ASTPrinter.cpp Normal file
View File

@ -0,0 +1,43 @@
//
// Created by Bobby Lucero on 5/23/23.
//
#include "../headers/ASTPrinter.h"
std::string ASTPrinter::visitBinaryExpr(BinaryExpr<std::string>* expression){
std::cout << expression->left << std::endl;
return parenthesize(expression->oper.lexeme, std::vector<std::shared_ptr<Expr<std::string> > >{expression->left, expression->right});
}
//std::string ASTPrinter::visitGroupingExpr(GroupingExpr<std::string> expression){
// return "hi";
//}
std::string ASTPrinter::visitLiteralExpr(LiteralExpr<std::string>* expression){
return expression->value;
}
std::string ASTPrinter::visitUnaryExpr(UnaryExpr<std::string>* expression){
return parenthesize(expression->oper.lexeme, std::vector<std::shared_ptr<Expr<std::string> > >{expression->right});
}
std::string ASTPrinter::print(Expr<std::string> *expr) {
return expr->accept(this);
}
std::string ASTPrinter::parenthesize(std::string name, std::vector<std::shared_ptr<Expr<std::string> > > exprs) {
std::string builder;
builder += "(" + name;
for(std::shared_ptr<Expr<std::string> > expr : exprs)
{
std::cout << expr << std::endl;
builder += " ";
builder += expr->accept(this);
}
builder += ")";
return builder;
}

View File

@ -1,37 +1,44 @@
// //
// Created by Bobby Lucero on 5/21/23. // Created by Bobby Lucero on 5/21/23.
// //
#include "../headers/bob.h" #include "../headers/bob.h"
#include "../headers/Expression.h" #include "../headers/Expression.h"
#include "../headers/Lexer.h" #include "../headers/Lexer.h"
#include "../headers/ASTPrinter.h"
int main(){ int main(){
Bob bobLang; Bob bobLang;
//bobLang.runFile("source.bob"); //bobLang.runFile("source.bob");
ASTPrinter printer;
Expr a; std::shared_ptr<Expr<std::string> > expression = std::make_shared<BinaryExpr<std::string> >(
Expr b; std::make_shared<UnaryExpr<std::string> >(
Token t = {PLUS, "+", 1}; Token{MINUS, "-", 0},
Token t2 = {MINUS, "-", 1}; std::make_shared<LiteralExpr<std::string> >("123")
BinaryExpr e = BinaryExpr(a, t, b); ),
Token{STAR, "*", 0},
std::make_shared<UnaryExpr<std::string> >(
Token{MINUS, "+", 0},
std::make_shared<LiteralExpr<std::string> >("987")
)
);
std::shared_ptr<Expr> any = std::make_shared<BinaryExpr>(a, t, b); // Expr<std::string>* e = new BinaryExpr<std::string>(
if(std::shared_ptr<BinaryExpr> binexpr = std::dynamic_pointer_cast<BinaryExpr>(any)) // new UnaryExpr<std::string>(Token{MINUS, "-", 0}, new LiteralExpr<std::string>("123")),
{ // Token{STAR, "*", 0},
std::cout << binexpr->oper.lexeme; // new UnaryExpr<std::string>(Token{PLUS, "+", 0}, new LiteralExpr<std::string>("535"))
} // );
LiteralExpr<std::string>* le = new LiteralExpr<std::string>("123");
any = std::make_shared<BinaryExpr>(a, t2, b); std::cout << printer.print(expression.get());
if(std::shared_ptr<BinaryExpr> binexpr = std::dynamic_pointer_cast<BinaryExpr>(any))
{
std::cout << binexpr->oper.lexeme;
}
std::cout << std::endl; std::cout << std::endl;
bobLang.runPrompt(); //bobLang.runPrompt();
return 0; return 0;
} }

View File

@ -1,35 +1,51 @@
struct BinaryExpr : Expr template <typename T>
struct BinaryExpr : Expr<T>, Visitor<T>
{ {
const Expr left; const Expr<T> left;
const Token oper; const Token oper;
const Expr right; const Expr<T> right;
BinaryExpr(Expr left, Token oper, Expr right) : left(left), oper(oper), right(right) BinaryExpr(Expr<T> left, Token oper, Expr<T> right) : left(left), oper(oper), right(right)
{ {
} }
T accept(Visitor<T> visitor){
return visitor.visitBinaryExpr(this);
}
}; };
struct GroupingExpr : Expr template <typename T>
struct GroupingExpr : Expr<T>, Visitor<T>
{ {
const Expr expression; const Expr<T> expression;
GroupingExpr(Expr expression) : expression(expression) GroupingExpr(Expr<T> expression) : expression(expression)
{ {
} }
T accept(Visitor<T> visitor){
return visitor.visitGroupingExpr(this);
}
}; };
struct LiteralExpr : Expr template <typename T>
struct LiteralExpr : Expr<T>, Visitor<T>
{ {
const std::string value; const std::string value;
LiteralExpr(std::string value) : value(value) LiteralExpr(std::string value) : value(value)
{ {
} }
}; T accept(Visitor<T> visitor){
struct UnaryExpr : Expr return visitor.visitLiteralExpr(this);
{ }
const Token oper; };
const Expr right; template <typename T>
struct UnaryExpr : Expr<T>, Visitor<T>
UnaryExpr(Token oper, Expr right) : oper(oper), right(right) {
{ const Token oper;
const Expr<T> right;
UnaryExpr(Token oper, Expr<T> right) : oper(oper), right(right)
{
}
T accept(Visitor<T> visitor){
return visitor.visitUnaryExpr(this);
} }
}; };

Binary file not shown.

View File

@ -8,21 +8,29 @@
void defineType(std::ofstream &out, std::string baseName, std::string className, std::string fieldList) void defineType(std::ofstream &out, std::string baseName, std::string className, std::string fieldList)
{ {
out << "struct " << className << "Expr : " << baseName << "\n{\n"; out << "template <typename T>\n";
out << "struct " << className << "Expr : " << baseName << "<T>" << ", Visitor<T>" << "\n{\n";
std::vector<std::string> fields = splitString(fieldList, ", "); std::vector<std::string> fields = splitString(fieldList, ", ");
for(std::string field : fields) 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<T>" : trim(fieldClass);
out << " const " << fieldClass << " " << fieldName << ";\n";
} }
fieldList = replaceSubstring(fieldList, "Expr", "Expr<T>");
out << "\n " << className << "Expr(" << fieldList << ") : "; out << "\n " << className << "Expr(" << fieldList << ") : ";
std::string explicitDeclaration; std::string explicitDeclaration;
for(std::string field : fields) 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<T>" : trim(fieldClass);
explicitDeclaration += trim(name) + "(" + trim(name) + "), "; explicitDeclaration += trim(fieldName) + "(" + trim(fieldName) + "), ";
} }
explicitDeclaration = trim(explicitDeclaration); explicitDeclaration = trim(explicitDeclaration);
explicitDeclaration.pop_back(); explicitDeclaration.pop_back();
@ -31,6 +39,11 @@ void defineType(std::ofstream &out, std::string baseName, std::string className,
out << "\n {\n"; out << "\n {\n";
out << " }\n"; out << " }\n";
out << " T accept(Visitor<T> visitor){\n";
out << " return visitor.visit" << className << "Expr(this);\n";
out << " }\n";
out << "};" << std::endl; out << "};" << std::endl;
} }