ASTPrinter now prints generated AST from parser

This commit is contained in:
Bobby Lucero 2023-05-27 02:05:06 -04:00
parent fc0d9137a5
commit a0ec4af169
11 changed files with 306 additions and 82 deletions

6
.idea/misc.xml generated
View File

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CidrRootsConfiguration">
<sourceRoots>
<file path="$PROJECT_DIR$/headers" />
<file path="$PROJECT_DIR$/source" />
</sourceRoots>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings"> <component name="MakefileSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">

View File

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

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <utility>
#include <vector> #include <vector>
#include "Lexer.h" #include "Lexer.h"
#include "Expression.h" #include "Expression.h"
@ -11,8 +12,27 @@ private:
int current = 0; int current = 0;
public: public:
Parser(std::vector<Token> tokens) : tokens(tokens){}; explicit Parser(std::vector<Token> tokens) : tokens(std::move(tokens)){};
std::shared_ptr<Expr<std::shared_ptr<Object>>> parse();
private: private:
std::shared_ptr<Expr<Object>> expression(); std::shared_ptr<Expr<std::shared_ptr<Object>>> expression();
std::shared_ptr<Expr<std::shared_ptr<Object>>> equality();
std::shared_ptr<Expr<std::shared_ptr<Object>>> comparison();
std::shared_ptr<Expr<std::shared_ptr<Object>>> term();
std::shared_ptr<Expr<std::shared_ptr<Object>>> factor();
std::shared_ptr<Expr<std::shared_ptr<Object>>> unary();
std::shared_ptr<Expr<std::shared_ptr<Object>>> primary();
bool match(std::vector<TokenType> types);
bool check(TokenType type);
bool isAtEnd();
Token advance();
Token peek();
Token previous();
Token consume(TokenType type, std::string message);
void sync();
}; };

View File

@ -2,7 +2,9 @@
#include <string> #include <string>
struct Object struct Object
{ {
virtual ~Object(){}; static int count;
Object();
virtual ~Object();
}; };
struct Number : public Object struct Number : public Object

View File

@ -1,16 +1 @@
bob.test 10 + 10
10
11.1
test = (11 + 2 "xs
hello
end")
//
//11.
12//11
11.
11.69 + 66.735293857293875 + 235982735987235.0 + 1
123a

View File

@ -4,40 +4,40 @@
#include "../headers/ASTPrinter.h" #include "../headers/ASTPrinter.h"
std::string ASTPrinter::visitBinaryExpr(BinaryExpr<std::string>* expression){ std::shared_ptr<Object> ASTPrinter::visitBinaryExpr(BinaryExpr<std::shared_ptr<Object>>* expression){
std::cout << expression->left << std::endl; std::cout << expression->left << std::endl;
return parenthesize(expression->oper.lexeme, std::vector<std::shared_ptr<Expr<std::string>>>{expression->left, expression->right}); return parenthesize(expression->oper.lexeme, std::vector<std::shared_ptr<Expr<std::shared_ptr<Object>>>>{expression->left, expression->right});
} }
std::string ASTPrinter::visitGroupingExpr(GroupingExpr<std::string>* expression){ std::shared_ptr<Object> ASTPrinter::visitGroupingExpr(GroupingExpr<std::shared_ptr<Object>>* expression){
return parenthesize("group", std::vector<std::shared_ptr<Expr<std::string>>>{expression->expression}); return parenthesize("group", std::vector<std::shared_ptr<Expr<std::shared_ptr<Object>>>>{expression->expression});
} }
std::string ASTPrinter::visitLiteralExpr(LiteralExpr<std::string>* expression){ std::shared_ptr<Object> ASTPrinter::visitLiteralExpr(LiteralExpr<std::shared_ptr<Object>>* expression){
return expression->value; return std::make_shared<String>(expression->value);
} }
std::string ASTPrinter::visitUnaryExpr(UnaryExpr<std::string>* expression){ std::shared_ptr<Object> ASTPrinter::visitUnaryExpr(UnaryExpr<std::shared_ptr<Object>>* expression){
return parenthesize(expression->oper.lexeme, std::vector<std::shared_ptr<Expr<std::string>>>{expression->right}); return parenthesize(expression->oper.lexeme, std::vector<std::shared_ptr<Expr<std::shared_ptr<Object>>>>{expression->right});
} }
std::string ASTPrinter::print(Expr<std::string> *expr) { std::shared_ptr<Object> ASTPrinter::print(Expr<std::shared_ptr<Object>> *expr) {
return expr->accept(this); return expr->accept(this);
} }
std::string ASTPrinter::parenthesize(std::string name, std::vector<std::shared_ptr<Expr<std::string>>> exprs) { std::shared_ptr<Object> ASTPrinter::parenthesize(std::string name, std::vector<std::shared_ptr<Expr<std::shared_ptr<Object>>>> exprs) {
std::string builder; std::string builder;
builder += "(" + name; builder += "(" + name;
for(std::shared_ptr<Expr<std::string>> expr : exprs) for(const std::shared_ptr<Expr<std::shared_ptr<Object>>>& expr : exprs)
{ {
std::cout << expr << std::endl;
builder += " "; builder += " ";
builder += expr->accept(this); builder += std::dynamic_pointer_cast<String>(expr->accept(this))->value;
} }
builder += ")"; builder += ")";
return builder; return std::make_shared<String>(builder);
} }

View File

@ -130,7 +130,7 @@ std::vector<Token> Lexer::Tokenize(std::string source){
} }
if(src.empty()) if(src.empty())
{ {
throw std::runtime_error("Unterminated string at line: " + std::to_string(this->line)); throw std::runtime_error("LEXER: Unterminated string at line: " + std::to_string(this->line));
} }
else if(src[0] == '"') else if(src[0] == '"')
{ {
@ -172,7 +172,7 @@ std::vector<Token> Lexer::Tokenize(std::string source){
} }
else else
{ {
throw std::runtime_error("malformed number at: " + std::to_string(this->line)); throw std::runtime_error("LEXER: malformed number at: " + std::to_string(this->line));
} }
} }
@ -205,14 +205,14 @@ std::vector<Token> Lexer::Tokenize(std::string source){
else else
{ {
throw std::runtime_error("Unknown Token: '" + std::string(1, t) + "'"); throw std::runtime_error("LEXER: Unknown Token: '" + std::string(1, t) + "'");
} }
} }
} }
tokens.push_back({END_OF_FILE, "eof", line});
return tokens; return tokens;
} }

View File

@ -3,6 +3,176 @@
// //
#include "../headers/Parser.h" #include "../headers/Parser.h"
std::shared_ptr<Expr<Object> > Parser::expression() {
// Precedence
// to all the morons on facebook who don't know what pemdas is, fuck you
///////////////////////////////////////////
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::expression()
{
return equality();
}
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::equality()
{
std::shared_ptr<Expr<std::shared_ptr<Object>>> expr = comparison();
while(match({BANG_EQUAL, DOUBLE_EQUAL}))
{
Token op = previous();
std::shared_ptr<Expr<std::shared_ptr<Object>>> right = comparison();
expr = std::make_shared<BinaryExpr<std::shared_ptr<Object>>>(expr, op, right);
}
return expr;
}
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::comparison()
{
std::shared_ptr<Expr<std::shared_ptr<Object>>> expr = term();
while(match({GREATER, GREATER_EQUAL, LESS, LESS_EQUAL}))
{
Token op = previous();
std::shared_ptr<Expr<std::shared_ptr<Object>>> right = term();
expr = std::make_shared<BinaryExpr<std::shared_ptr<Object>>>(expr, op, right);
}
return expr;
}
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::term()
{
std::shared_ptr<Expr<std::shared_ptr<Object>>> expr = factor();
while(match({MINUS, PLUS}))
{
std::cout << "Found comparison" << std::endl;
Token op = previous();
std::shared_ptr<Expr<std::shared_ptr<Object>>> right = factor();
expr = std::make_shared<BinaryExpr<std::shared_ptr<Object>>>(expr, op, right);
}
return expr;
}
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::factor()
{
std::shared_ptr<Expr<std::shared_ptr<Object>>> expr = unary();
while(match({SLASH, STAR}))
{
Token op = previous();
std::shared_ptr<Expr<std::shared_ptr<Object>>> right = unary();
expr = std::make_shared<BinaryExpr<std::shared_ptr<Object>>>(expr, op, right);
}
return expr;
}
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::unary()
{
if(match({BANG, MINUS}))
{
Token op = previous();
std::shared_ptr<Expr<std::shared_ptr<Object>>> right = unary();
return std::make_shared<UnaryExpr<std::shared_ptr<Object>>>(op, right);
}
return primary();
}
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::primary()
{
if(match({FALSE})) return std::make_shared<LiteralExpr<std::shared_ptr<Object>>>("true", false);
if(match({TRUE})) return std::make_shared<LiteralExpr<std::shared_ptr<Object>>>("true", false);
if(match({NONE})) return std::make_shared<LiteralExpr<std::shared_ptr<Object>>>("none", false);
if(match({NUMBER})) return std::make_shared<LiteralExpr<std::shared_ptr<Object>>>(previous().lexeme, true);
if(match({STRING})) return std::make_shared<LiteralExpr<std::shared_ptr<Object>>>(previous().lexeme, false);
if(match({OPEN_PAREN}))
{
std::shared_ptr<Expr<std::shared_ptr<Object>>> expr = expression();
consume(CLOSE_PAREN, "Expected ')' after expression on line " + std::to_string(peek().line));
return std::make_shared<GroupingExpr<std::shared_ptr<Object>>>(expr);
}
throw std::runtime_error("Expression expected at: " + std::to_string(peek().line));
}
///////////////////////////////////////////
std::shared_ptr<Expr<std::shared_ptr<Object>>> Parser::parse() {
return expression();
} }
bool Parser::match(std::vector<TokenType> types) {
for(TokenType t : types)
{
if(check(t))
{
advance();
return true;
}
}
return false;
}
bool Parser::check(TokenType type) {
if(isAtEnd()) return false;
return peek().type == type;
}
bool Parser::isAtEnd() {
return peek().type == END_OF_FILE;
}
Token Parser::advance() {
if(!isAtEnd()) current++;
return previous();
}
Token Parser::peek() {
return tokens[current];
}
Token Parser::previous() {
return tokens[current - 1];
}
Token Parser::consume(TokenType type, std::string message) {
if(check(type)) return advance();
throw std::runtime_error(peek().lexeme +": "+ message);
}
void Parser::sync()
{
advance();
while(!isAtEnd())
{
if(previous().type == SEMICOLON) return;
switch (peek().type) {
case CLASS:
case FUNCTION:
case VAR:
case FOR:
case IF:
case WHILE:
case RETURN:
return;
}
advance();
}
}

18
source/TypeWrapper.cpp Normal file
View File

@ -0,0 +1,18 @@
//
// Created by Bobby Lucero on 5/27/23.
//
#include "../headers/TypeWrapper.h"
#include <iostream>
int Object::count;
Object::Object() {
std::cout << "Inc"<<std::endl;
Object::count += 1;
}
Object::~Object() {
std::cout << "dec"<<std::endl;
Object::count -= 1;
}

View File

@ -1,4 +1,6 @@
#include "../headers/bob.h" #include "../headers/bob.h"
#include "../headers/Parser.h"
#include "../headers/ASTPrinter.h"
using namespace std; using namespace std;
void Bob::runFile(string path) void Bob::runFile(string path)
@ -45,11 +47,31 @@ void Bob::error(int line, string message)
void Bob::run(string source) void Bob::run(string source)
{ {
try {
vector<Token> tokens = lexer.Tokenize(source); vector<Token> tokens = lexer.Tokenize(source);
Parser p(tokens);
shared_ptr<Expr<shared_ptr<Object>>> expr = p.parse();
ASTPrinter printer;
cout << dynamic_pointer_cast<String>(printer.print(expr.get()))->value << endl;
for(Token t : tokens){ for(Token t : tokens){
cout << "{type: " << t.type << ", value: " << t.lexeme << "}" << endl; //cout << "{type: " << t.type << ", value: " << t.lexeme << "}" << endl;
} }
}
catch(std::exception &e)
{
cout << "ERROR OCCURRED: " << e.what() << endl;
return;
}
cout << "Current object count: " << Object::count << endl;
} }
void Bob::report(int line, string where, string message) void Bob::report(int line, string where, string message)

View File

@ -9,46 +9,47 @@
#include "../headers/ASTPrinter.h" #include "../headers/ASTPrinter.h"
#include "../headers/TypeWrapper.h" #include "../headers/TypeWrapper.h"
int main(){ int main(){
Object::count = 0;
Bob bobLang; Bob bobLang;
//bobLang.runFile("source.bob"); //bobLang.runFile("source.bob");
bobLang.runPrompt();
ASTPrinter printer; //ASTPrinter printer;
//
std::shared_ptr<Expr<std::string>> expression = std::make_shared<BinaryExpr<std::string> >( // std::shared_ptr<Expr<std::shared_ptr<Object>>> expression = std::make_shared<BinaryExpr<std::shared_ptr<Object>> >(
std::make_shared<UnaryExpr<std::string>>( // std::make_shared<UnaryExpr<std::shared_ptr<Object>>>(
Token{MINUS, "-", 1}, // Token{MINUS, "-", 1},
std::make_shared<LiteralExpr<std::string>>("123", true) // std::make_shared<LiteralExpr<std::shared_ptr<Object>>>("123", true)
), // ),
Token{MINUS, "-", 1}, // Token{MINUS, "-", 1},
std::make_shared<GroupingExpr<std::string>>( // std::make_shared<GroupingExpr<std::shared_ptr<Object>>>(
std::make_shared<LiteralExpr<std::string>>("45.67", true) // std::make_shared<LiteralExpr<std::shared_ptr<Object>>>("45.67", true)
) // )
);
// 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", true); //
//// Expr<std::string>* e = new BinaryExpr<std::string>(
std::cout << printer.print(expression.get()); //// new UnaryExpr<std::string>(Token{MINUS, "-", 0}, new LiteralExpr<std::string>("123")),
//// Token{STAR, "*", 0},
std::cout << std::endl; //// new UnaryExpr<std::string>(Token{PLUS, "+", 0}, new LiteralExpr<std::string>("535"))
//// );
//
//
// std::cout << std::dynamic_pointer_cast<String>(printer.print(expression.get()))->value;
//
// std::cout << std::endl;
//bobLang.runPrompt(); //bobLang.runPrompt();
std::shared_ptr<Object> object = std::make_shared<String>(String{"Hi"}); // std::shared_ptr<Object> object = std::make_shared<String>(String{"Hi"});
//
if(auto num = std::dynamic_pointer_cast<Number>(object)) // if(auto num = std::dynamic_pointer_cast<Number>(object))
{ // {
std::cout << num->value << std::endl; // std::cout << num->value << std::endl;
}else if(auto str = std::dynamic_pointer_cast<String>(object)) // }else if(auto str = std::dynamic_pointer_cast<String>(object))
{ // {
std::cout << str->value << std::endl; // std::cout << str->value << std::endl;
} // }
return 0; return 0;
} }