A working but clunky solution for expressions
This commit is contained in:
		@@ -2,6 +2,7 @@
 | 
			
		||||
#include "error_handler.hh"
 | 
			
		||||
#include "parser.hh"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <sysexits.h>
 | 
			
		||||
 | 
			
		||||
ErrorHandler error_handler{};
 | 
			
		||||
@@ -16,11 +17,15 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
  //
 | 
			
		||||
  // run_interpreter(argc, argv);
 | 
			
		||||
 | 
			
		||||
  Unary left {Token{TokenType::MINUS, "-", Object{}, 1}, Literal{123}};
 | 
			
		||||
  Token op{TokenType::STAR, "*", Object{}, 1};
 | 
			
		||||
  Grouping right{Literal{45.67}};
 | 
			
		||||
  ExprPtr literal = std::make_shared<Expr>(ExprType::LITERAL, Literal{123});
 | 
			
		||||
  ExprPtr left = std::make_shared<Expr>(ExprType::UNARY, Unary{Token{TokenType::MINUS, "-", Object{}, 1}, literal});
 | 
			
		||||
 | 
			
		||||
  Binary expr {left, op, right};
 | 
			
		||||
  Token op{TokenType::STAR, "*", Object{}, 1};
 | 
			
		||||
 | 
			
		||||
  ExprPtr gliteral = std::make_shared<Expr>(ExprType::LITERAL, Literal{45.67});
 | 
			
		||||
  ExprPtr right = std::make_shared<Expr>(ExprType::GROUPING, gliteral);
 | 
			
		||||
 | 
			
		||||
  Expr expr = {ExprType::BINARY, Binary{left, op, right}};
 | 
			
		||||
 | 
			
		||||
  AstPrinter printer{};
 | 
			
		||||
  std::cout << printer.print(expr) << '\n';
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,24 @@
 | 
			
		||||
#include "expr.hh"
 | 
			
		||||
#include "../tokenizer.hh"
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
#include <variant>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
std::string AstPrinter::print(const Expression &expr) {
 | 
			
		||||
  return std::visit([this](auto &&node) -> std::string {
 | 
			
		||||
    using T = std::decay_t<decltype(node)>;
 | 
			
		||||
 | 
			
		||||
    if constexpr(std::is_same_v<T, Binary>) {
 | 
			
		||||
      return parenthesize(node.op.lexeme, {node.left, node.right});
 | 
			
		||||
    } else if constexpr(std::is_same_v<T, Grouping>) {
 | 
			
		||||
      return parenthesize("group", {node.expression});
 | 
			
		||||
    } else if constexpr(std::is_same_v<T, Literal>) {
 | 
			
		||||
std::string AstPrinter::print(const Expr &expr) {
 | 
			
		||||
  switch (expr.type) {
 | 
			
		||||
    case ExprType::BINARY: {
 | 
			
		||||
      Binary node = std::get<Binary>(expr.value);
 | 
			
		||||
      assert(node.left != NULL && node.right != NULL);
 | 
			
		||||
      return parenthesize(node.op.lexeme, {*node.left, *node.right});
 | 
			
		||||
    }
 | 
			
		||||
    case ExprType::GROUPING: {
 | 
			
		||||
      Grouping node = std::get<Grouping>(expr.value);
 | 
			
		||||
      assert(node.expression != NULL);
 | 
			
		||||
      return parenthesize("group", {*node.expression});
 | 
			
		||||
    }
 | 
			
		||||
    case ExprType::LITERAL: {
 | 
			
		||||
      Literal node = std::get<Literal>(expr.value);
 | 
			
		||||
      switch (node.value.type) {
 | 
			
		||||
        case ObjectType::NIL:
 | 
			
		||||
          return "nil";
 | 
			
		||||
@@ -28,22 +32,20 @@ std::string AstPrinter::print(const Expression &expr) {
 | 
			
		||||
          return std::to_string(value);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else if constexpr(std::is_same_v<T, Unary>) {
 | 
			
		||||
      return parenthesize(node.op.lexeme, {node.right});
 | 
			
		||||
    }
 | 
			
		||||
    case ExprType::UNARY: {
 | 
			
		||||
      Unary node = std::get<Unary>(expr.value);
 | 
			
		||||
      assert(node.right != NULL);
 | 
			
		||||
      return parenthesize(node.op.lexeme, {*node.right});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    return "";
 | 
			
		||||
  }, expr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string AstPrinter::parenthesize(const std::string &name, std::vector<Expression> exprs) {
 | 
			
		||||
std::string AstPrinter::parenthesize(const std::string &name, std::vector<Expr> exprs) {
 | 
			
		||||
  std::stringstream ss{};
 | 
			
		||||
  ss << '(' << name;
 | 
			
		||||
  for (auto &expr : exprs) {
 | 
			
		||||
    std::string value = std::visit([this](auto &&node) -> std::string {
 | 
			
		||||
      return print(node);
 | 
			
		||||
    }, expr);
 | 
			
		||||
    ss << ' ' << value;
 | 
			
		||||
    ss << ' ' << print(expr);
 | 
			
		||||
  }
 | 
			
		||||
  ss << ')';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,45 +2,61 @@
 | 
			
		||||
#define EXPR_HH
 | 
			
		||||
 | 
			
		||||
#include "../tokenizer.hh"
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <variant>
 | 
			
		||||
 | 
			
		||||
struct Expr {};
 | 
			
		||||
struct Expr;
 | 
			
		||||
 | 
			
		||||
struct Binary : public Expr {
 | 
			
		||||
  Binary(Expr left, Token op, Expr right) : left{left}, op{op}, right{right} {};
 | 
			
		||||
using ExprPtr = std::shared_ptr<Expr>;
 | 
			
		||||
 | 
			
		||||
  Expr left;
 | 
			
		||||
struct Binary {
 | 
			
		||||
  Binary(ExprPtr left, Token op, ExprPtr right) : left{left}, op{op}, right{right} {};
 | 
			
		||||
 | 
			
		||||
  ExprPtr left;
 | 
			
		||||
  Token op;
 | 
			
		||||
  Expr right;
 | 
			
		||||
  ExprPtr right;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Grouping : public Expr {
 | 
			
		||||
  Grouping(Expr expr) : expression{expr} {};
 | 
			
		||||
struct Grouping {
 | 
			
		||||
  Grouping(ExprPtr expr) : expression{expr} {};
 | 
			
		||||
 | 
			
		||||
  Expr expression;
 | 
			
		||||
  ExprPtr expression;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Literal : public Expr {
 | 
			
		||||
struct Literal {
 | 
			
		||||
  Literal(Object value) : value{value} {};
 | 
			
		||||
 | 
			
		||||
  Object value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Unary : public Expr {
 | 
			
		||||
  Unary(Token op, Expr right) : op{op}, right{right} {};
 | 
			
		||||
struct Unary {
 | 
			
		||||
  Unary(Token op, ExprPtr right) : op{op}, right{right} {};
 | 
			
		||||
 | 
			
		||||
  Token op;
 | 
			
		||||
  Expr right;
 | 
			
		||||
  ExprPtr right;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using Expression = std::variant<Expr, Binary, Grouping, Literal, Unary>;
 | 
			
		||||
enum class ExprType {
 | 
			
		||||
  BINARY,
 | 
			
		||||
  GROUPING,
 | 
			
		||||
  LITERAL,
 | 
			
		||||
  UNARY,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using Expression = std::variant<Binary, Grouping, Literal, Unary>;
 | 
			
		||||
 | 
			
		||||
struct Expr {
 | 
			
		||||
  Expr(ExprType type, Expression value) : type{type}, value{value} {}
 | 
			
		||||
  ExprType type;
 | 
			
		||||
  Expression value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class AstPrinter {
 | 
			
		||||
public:
 | 
			
		||||
  std::string print(const Expression &expr);
 | 
			
		||||
  std::string print(const Expr &expr);
 | 
			
		||||
private:
 | 
			
		||||
  std::string parenthesize(const std::string &name, std::vector<Expression> exprs);
 | 
			
		||||
  std::string parenthesize(const std::string &name, std::vector<Expr> exprs);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user