Rough implementation of ASTPrinter complete with nasty shared_ptr syntax :)
This commit is contained in:
parent
c5f981321c
commit
d909e546f2
18
headers/ASTPrinter.h
Normal file
18
headers/ASTPrinter.h
Normal 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);
|
||||
|
||||
};
|
||||
@ -5,45 +5,74 @@
|
||||
#pragma once
|
||||
#include "Lexer.h"
|
||||
#include <iostream>
|
||||
|
||||
template <typename T>
|
||||
struct Visitor;
|
||||
|
||||
template <typename T>
|
||||
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 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)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct GroupingExpr : Expr
|
||||
{
|
||||
const Expr expression;
|
||||
|
||||
GroupingExpr(Expr expression) : expression(expression)
|
||||
{
|
||||
T accept(Visitor<T>* visitor) override{
|
||||
return visitor->visitBinaryExpr(this);
|
||||
}
|
||||
};
|
||||
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;
|
||||
|
||||
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<T>* visitor) override{
|
||||
return visitor->visitLiteralExpr(this);
|
||||
}
|
||||
};
|
||||
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;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
43
source/ASTPrinter.cpp
Normal file
43
source/ASTPrinter.cpp
Normal 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;
|
||||
|
||||
}
|
||||
@ -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<Expr<std::string> > expression = std::make_shared<BinaryExpr<std::string> >(
|
||||
std::make_shared<UnaryExpr<std::string> >(
|
||||
Token{MINUS, "-", 0},
|
||||
std::make_shared<LiteralExpr<std::string> >("123")
|
||||
),
|
||||
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);
|
||||
if(std::shared_ptr<BinaryExpr> binexpr = std::dynamic_pointer_cast<BinaryExpr>(any))
|
||||
{
|
||||
std::cout << binexpr->oper.lexeme;
|
||||
}
|
||||
// Expr<std::string>* e = new BinaryExpr<std::string>(
|
||||
// new UnaryExpr<std::string>(Token{MINUS, "-", 0}, new LiteralExpr<std::string>("123")),
|
||||
// Token{STAR, "*", 0},
|
||||
// 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);
|
||||
if(std::shared_ptr<BinaryExpr> binexpr = std::dynamic_pointer_cast<BinaryExpr>(any))
|
||||
{
|
||||
std::cout << binexpr->oper.lexeme;
|
||||
}
|
||||
std::cout << printer.print(expression.get());
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
bobLang.runPrompt();
|
||||
//bobLang.runPrompt();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
48
testthing
48
testthing
@ -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 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;
|
||||
|
||||
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<T> visitor){
|
||||
return visitor.visitLiteralExpr(this);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
struct UnaryExpr : Expr<T>, Visitor<T>
|
||||
{
|
||||
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.
@ -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 <typename T>\n";
|
||||
out << "struct " << className << "Expr : " << baseName << "<T>" << ", Visitor<T>" << "\n{\n";
|
||||
std::vector<std::string> 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<T>" : trim(fieldClass);
|
||||
out << " const " << fieldClass << " " << fieldName << ";\n";
|
||||
}
|
||||
|
||||
fieldList = replaceSubstring(fieldList, "Expr", "Expr<T>");
|
||||
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<T>" : 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<T> visitor){\n";
|
||||
out << " return visitor.visit" << className << "Expr(this);\n";
|
||||
out << " }\n";
|
||||
|
||||
out << "};" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user