Switch to macros for better readability and add printer.hh
This commit is contained in:
parent
a6e129eb12
commit
1118e825f3
@ -18,13 +18,13 @@ int main(int argc, char *argv[]) {
|
||||
// run_interpreter(argc, argv);
|
||||
|
||||
Token unary_op{TokenType::MINUS, "-", Object{}, 1};
|
||||
Expr left{unary_op, Expr{123}};
|
||||
Expr left{Unary(unary_op, Literal(123))};
|
||||
|
||||
Token op{TokenType::STAR, "*", Object{}, 1};
|
||||
|
||||
Expr right{Expr{45.67}, nullptr};
|
||||
Expr right{Grouping(Literal(45.67))};
|
||||
|
||||
Expr expr{left, op, right};
|
||||
Expr expr{Binary(left, op, right)};
|
||||
|
||||
AstPrinter printer{};
|
||||
std::cout << printer.print(expr) << '\n';
|
||||
|
@ -2,5 +2,6 @@
|
||||
#define PARSER_CC
|
||||
|
||||
#include "parser/expr.cc"
|
||||
#include "parser/printer.cc"
|
||||
|
||||
#endif
|
||||
|
@ -2,5 +2,6 @@
|
||||
#define PARSER_HH
|
||||
|
||||
#include "parser/expr.hh"
|
||||
#include "parser/printer.hh"
|
||||
|
||||
#endif
|
||||
|
@ -2,101 +2,176 @@
|
||||
#include "../tokenizer.hh"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
Expr::Expr(ExprType type, ExprVariant value) : type{type}, value{value} {}
|
||||
|
||||
// Copy constructor
|
||||
Expr::Expr(const Expr &other) : type{other.type} {
|
||||
switch(type) {
|
||||
case ExprType::BINARY: {
|
||||
std::shared_ptr<Binary> ptr = std::get<std::shared_ptr<Binary>>(other.value);
|
||||
value = std::make_shared<Binary>(*ptr);
|
||||
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(other.value);
|
||||
value = std::make_shared<_Binary>(*ptr);
|
||||
break;
|
||||
}
|
||||
case ExprType::GROUPING: {
|
||||
std::shared_ptr<Grouping> ptr = std::get<std::shared_ptr<Grouping>>(other.value);
|
||||
value = std::make_shared<Grouping>(*ptr);
|
||||
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(other.value);
|
||||
value = std::make_shared<_Grouping>(*ptr);
|
||||
break;
|
||||
}
|
||||
case ExprType::LITERAL: {
|
||||
std::shared_ptr<Literal> ptr = std::get<std::shared_ptr<Literal>>(other.value);
|
||||
value = std::make_shared<Literal>(*ptr);
|
||||
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(other.value);
|
||||
value = std::make_shared<_Literal>(*ptr);
|
||||
break;
|
||||
}
|
||||
case ExprType::UNARY: {
|
||||
std::shared_ptr<Unary> ptr = std::get<std::shared_ptr<Unary>>(other.value);
|
||||
value = std::make_shared<Unary>(*ptr);
|
||||
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(other.value);
|
||||
value = std::make_shared<_Unary>(*ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move constructor
|
||||
Expr::Expr(const Expr &&other) : type{other.type}, value{std::move(other.value)} {}
|
||||
|
||||
// Binary expressoin
|
||||
Expr::Expr(const Expr &left, Token op, const Expr &right)
|
||||
: type{ExprType::BINARY}, value{std::make_shared<Binary>(left, op, right)} {}
|
||||
|
||||
// Literal expression
|
||||
Expr::Expr(Object value)
|
||||
: type{ExprType::LITERAL}, value{std::make_shared<Literal>(value)} {}
|
||||
|
||||
// Unary expressoin
|
||||
Expr::Expr(Token op, const Expr &right)
|
||||
: type{ExprType::UNARY}, value{std::make_shared<Unary>(op, right)} {}
|
||||
|
||||
// Group expression
|
||||
// Has to take an extra parameter to avoid conflicting with copy constructor
|
||||
Expr::Expr(const Expr &expr, void *ptr)
|
||||
: type{ExprType::GROUPING}, value{std::make_shared<Grouping>(expr)} { (void)ptr; }
|
||||
|
||||
std::string AstPrinter::print(const Expr &expr) {
|
||||
switch (expr.type) {
|
||||
Expr::Expr(const Expr &&other) : type{other.type}, value{std::move(other.value)} {
|
||||
switch(type) {
|
||||
case ExprType::BINARY: {
|
||||
std::shared_ptr<Binary> binary = std::get<std::shared_ptr<Binary>>(expr.value);
|
||||
assert(binary != nullptr);
|
||||
return parenthesize(binary->op.lexeme, {&binary->left, &binary->right});
|
||||
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(other.value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::GROUPING: {
|
||||
std::shared_ptr<Grouping> group = std::get<std::shared_ptr<Grouping>>(expr.value);
|
||||
assert(group != nullptr);
|
||||
return parenthesize("group", {&group->expr});
|
||||
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(other.value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::LITERAL: {
|
||||
std::shared_ptr<Literal> literal = std::get<std::shared_ptr<Literal>>(expr.value);
|
||||
assert(literal != nullptr);
|
||||
switch (literal->value.type) {
|
||||
case ObjectType::NIL:
|
||||
return "nil";
|
||||
case ObjectType::IDENTIFIER:
|
||||
case ObjectType::STRING_LIT: {
|
||||
std::string value = std::get<std::string>(literal->value.value);
|
||||
return value;
|
||||
}
|
||||
case ObjectType::NUMBER: {
|
||||
double value = std::get<double>(literal->value.value);
|
||||
return std::to_string(value);
|
||||
}
|
||||
}
|
||||
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(other.value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::UNARY: {
|
||||
std::shared_ptr<Unary> unary = std::get<std::shared_ptr<Unary>>(expr.value);
|
||||
assert(unary != nullptr);
|
||||
return parenthesize(unary->op.lexeme, {&unary->right});
|
||||
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(other.value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string AstPrinter::parenthesize(const std::string &name, std::vector<const Expr *> exprs) {
|
||||
std::stringstream ss{};
|
||||
ss << '(' << name;
|
||||
for (const Expr *expr : exprs) {
|
||||
ss << ' ' << print(*expr);
|
||||
// Copy assignment
|
||||
Expr &Expr::operator=(const Expr &other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
ss << ')';
|
||||
|
||||
return ss.str();
|
||||
switch(type) {
|
||||
case ExprType::BINARY: {
|
||||
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::GROUPING: {
|
||||
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::LITERAL: {
|
||||
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::UNARY: {
|
||||
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
type = other.type;
|
||||
|
||||
switch(type) {
|
||||
case ExprType::BINARY: {
|
||||
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(other.value);
|
||||
value = std::make_shared<_Binary>(*ptr);
|
||||
break;
|
||||
}
|
||||
case ExprType::GROUPING: {
|
||||
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(other.value);
|
||||
value = std::make_shared<_Grouping>(*ptr);
|
||||
break;
|
||||
}
|
||||
case ExprType::LITERAL: {
|
||||
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(other.value);
|
||||
value = std::make_shared<_Literal>(*ptr);
|
||||
break;
|
||||
}
|
||||
case ExprType::UNARY: {
|
||||
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(other.value);
|
||||
value = std::make_shared<_Unary>(*ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Move assignment
|
||||
Expr &Expr::operator=(const Expr &&other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case ExprType::BINARY: {
|
||||
std::shared_ptr<_Binary> ptr = std::get<std::shared_ptr<_Binary>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::GROUPING: {
|
||||
std::shared_ptr<_Grouping> ptr = std::get<std::shared_ptr<_Grouping>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::LITERAL: {
|
||||
std::shared_ptr<_Literal> ptr = std::get<std::shared_ptr<_Literal>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::UNARY: {
|
||||
std::shared_ptr<_Unary> ptr = std::get<std::shared_ptr<_Unary>>(value);
|
||||
ptr.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
type = other.type;
|
||||
|
||||
switch(type) {
|
||||
case ExprType::BINARY: {
|
||||
std::shared_ptr<_Binary> optr = std::get<std::shared_ptr<_Binary>>(other.value);
|
||||
value = std::move(other.value);
|
||||
optr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::GROUPING: {
|
||||
std::shared_ptr<_Grouping> optr = std::get<std::shared_ptr<_Grouping>>(other.value);
|
||||
value = std::move(other.value);
|
||||
optr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::LITERAL: {
|
||||
std::shared_ptr<_Literal> optr = std::get<std::shared_ptr<_Literal>>(other.value);
|
||||
value = std::move(other.value);
|
||||
optr.reset();
|
||||
break;
|
||||
}
|
||||
case ExprType::UNARY: {
|
||||
std::shared_ptr<_Unary> optr = std::get<std::shared_ptr<_Unary>>(other.value);
|
||||
value = std::move(other.value);
|
||||
optr.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -3,14 +3,13 @@
|
||||
|
||||
#include "../tokenizer.hh"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
struct Expr;
|
||||
struct Binary;
|
||||
struct Grouping;
|
||||
struct Literal;
|
||||
struct Unary;
|
||||
struct _Binary;
|
||||
struct _Grouping;
|
||||
struct _Literal;
|
||||
struct _Unary;
|
||||
|
||||
enum class ExprType {
|
||||
BINARY,
|
||||
@ -20,64 +19,57 @@ enum class ExprType {
|
||||
};
|
||||
|
||||
using ExprVariant = std::variant<
|
||||
std::shared_ptr<Binary>,
|
||||
std::shared_ptr<Grouping>,
|
||||
std::shared_ptr<Literal>,
|
||||
std::shared_ptr<Unary>
|
||||
std::shared_ptr<_Binary>,
|
||||
std::shared_ptr<_Grouping>,
|
||||
std::shared_ptr<_Literal>,
|
||||
std::shared_ptr<_Unary>
|
||||
>;
|
||||
|
||||
#define Binary(LEFT, OP, RIGHT) (Expr{ExprType::BINARY, std::make_shared<_Binary>(LEFT, OP, RIGHT)})
|
||||
#define Grouping(EXPR) (Expr{ExprType::GROUPING, std::make_shared<_Grouping>(EXPR)})
|
||||
#define Literal(VALUE) (Expr{ExprType::LITERAL, std::make_shared<_Literal>(VALUE)})
|
||||
#define Unary(OP, RIGHT) (Expr{ExprType::UNARY, std::make_shared<_Unary>(OP, RIGHT)})
|
||||
|
||||
struct Expr {
|
||||
Expr(ExprType type, ExprVariant value);
|
||||
|
||||
// Copy constructor
|
||||
Expr(const Expr &other);
|
||||
|
||||
// Move constructor
|
||||
Expr(const Expr &&other);
|
||||
|
||||
// Binary expressoin
|
||||
Expr(const Expr &left, Token op, const Expr &right);
|
||||
// Copy assignment
|
||||
Expr &operator=(const Expr &other);
|
||||
|
||||
// Literal expression
|
||||
Expr(Object value);
|
||||
|
||||
// Unary expressoin
|
||||
Expr(Token op, const Expr &right);
|
||||
|
||||
// Group expression
|
||||
// Has to take an extra parameter to avoid conflicting with copy constructor
|
||||
Expr(const Expr &expr, void *ptr);
|
||||
// Move assignment
|
||||
Expr &operator=(const Expr &&other);
|
||||
|
||||
ExprType type;
|
||||
ExprVariant value;
|
||||
};
|
||||
|
||||
struct Binary {
|
||||
Binary(const Expr &left, Token op, const Expr &right) : left{left}, op{op}, right{right} {}
|
||||
struct _Binary {
|
||||
_Binary(const Expr &left, Token op, const Expr &right) : left{left}, op{op}, right{right} {}
|
||||
Expr left;
|
||||
Token op;
|
||||
Expr right;
|
||||
};
|
||||
|
||||
struct Grouping {
|
||||
Grouping(const Expr &expr) : expr{expr} {}
|
||||
struct _Grouping {
|
||||
_Grouping(const Expr &expr) : expr{expr} {}
|
||||
Expr expr;
|
||||
};
|
||||
|
||||
struct Literal {
|
||||
Literal(Object value) : value{value} {}
|
||||
struct _Literal {
|
||||
_Literal(Object value) : value{value} {}
|
||||
Object value;
|
||||
};
|
||||
|
||||
struct Unary {
|
||||
Unary(Token op, const Expr &right) : op{op}, right{right} {}
|
||||
struct _Unary {
|
||||
_Unary(Token op, const Expr &right) : op{op}, right{right} {}
|
||||
Token op;
|
||||
Expr right;
|
||||
};
|
||||
|
||||
class AstPrinter {
|
||||
public:
|
||||
std::string print(const Expr &expr);
|
||||
private:
|
||||
std::string parenthesize(const std::string &name, std::vector<const Expr *> exprs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
53
cclox_src/parser/printer.cc
Normal file
53
cclox_src/parser/printer.cc
Normal file
@ -0,0 +1,53 @@
|
||||
#include "printer.hh"
|
||||
#include "expr.hh"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
std::string AstPrinter::print(const Expr &expr) {
|
||||
switch (expr.type) {
|
||||
case ExprType::BINARY: {
|
||||
std::shared_ptr<_Binary> binary = std::get<std::shared_ptr<_Binary>>(expr.value);
|
||||
assert(binary != nullptr);
|
||||
return parenthesize(binary->op.lexeme, {&binary->left, &binary->right});
|
||||
}
|
||||
case ExprType::GROUPING: {
|
||||
std::shared_ptr<_Grouping> group = std::get<std::shared_ptr<_Grouping>>(expr.value);
|
||||
assert(group != nullptr);
|
||||
return parenthesize("group", {&group->expr});
|
||||
}
|
||||
case ExprType::LITERAL: {
|
||||
std::shared_ptr<_Literal> literal = std::get<std::shared_ptr<_Literal>>(expr.value);
|
||||
assert(literal != nullptr);
|
||||
switch (literal->value.type) {
|
||||
case ObjectType::NIL:
|
||||
return "nil";
|
||||
case ObjectType::IDENTIFIER:
|
||||
case ObjectType::STRING_LIT: {
|
||||
std::string value = std::get<std::string>(literal->value.value);
|
||||
return value;
|
||||
}
|
||||
case ObjectType::NUMBER: {
|
||||
double value = std::get<double>(literal->value.value);
|
||||
return std::to_string(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
case ExprType::UNARY: {
|
||||
std::shared_ptr<_Unary> unary = std::get<std::shared_ptr<_Unary>>(expr.value);
|
||||
assert(unary != nullptr);
|
||||
return parenthesize(unary->op.lexeme, {&unary->right});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string AstPrinter::parenthesize(const std::string &name, std::vector<const Expr *> exprs) {
|
||||
std::stringstream ss{};
|
||||
ss << '(' << name;
|
||||
for (const Expr *expr : exprs) {
|
||||
ss << ' ' << print(*expr);
|
||||
}
|
||||
ss << ')';
|
||||
|
||||
return ss.str();
|
||||
}
|
14
cclox_src/parser/printer.hh
Normal file
14
cclox_src/parser/printer.hh
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef PRINTER_HH
|
||||
#define PRINTER_HH
|
||||
|
||||
#include "expr.hh"
|
||||
#include <string>
|
||||
|
||||
class AstPrinter {
|
||||
public:
|
||||
std::string print(const Expr &expr);
|
||||
private:
|
||||
std::string parenthesize(const std::string &name, std::vector<const Expr *> exprs);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user