diff --git a/cclox_src/main.cc b/cclox_src/main.cc index faed62b..493db57 100644 --- a/cclox_src/main.cc +++ b/cclox_src/main.cc @@ -1,17 +1,29 @@ #include "interpreter.hh" #include "error_handler.hh" +#include "parser.hh" #include #include ErrorHandler error_handler{}; int main(int argc, char *argv[]) { - if (argc > 2) { - std::cout << "Usage: cclox [script]\n"; - exit(EX_USAGE); - } + (void)argc; + (void)argv; + // if (argc > 2) { + // std::cout << "Usage: cclox [script]\n"; + // exit(EX_USAGE); + // } + // + // run_interpreter(argc, 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}}; + + Binary expr {left, op, right}; + + AstPrinter printer{}; + std::cout << printer.print(expr) << '\n'; return 0; } diff --git a/cclox_src/parser.cc b/cclox_src/parser.cc new file mode 100644 index 0000000..51b13f6 --- /dev/null +++ b/cclox_src/parser.cc @@ -0,0 +1,6 @@ +#ifndef PARSER_CC +#define PARSER_CC + +#include "parser/expr.cc" + +#endif diff --git a/cclox_src/parser.hh b/cclox_src/parser.hh new file mode 100644 index 0000000..bba6ee1 --- /dev/null +++ b/cclox_src/parser.hh @@ -0,0 +1,6 @@ +#ifndef PARSER_HH +#define PARSER_HH + +#include "parser/expr.hh" + +#endif diff --git a/cclox_src/parser/expr.cc b/cclox_src/parser/expr.cc new file mode 100644 index 0000000..53b5613 --- /dev/null +++ b/cclox_src/parser/expr.cc @@ -0,0 +1,51 @@ +#include "expr.hh" +#include "../tokenizer.hh" +#include +#include +#include +#include +#include + +std::string AstPrinter::print(const Expression &expr) { + return std::visit([this](auto &&node) -> std::string { + using T = std::decay_t; + + if constexpr(std::is_same_v) { + return parenthesize(node.op.lexeme, {node.left, node.right}); + } else if constexpr(std::is_same_v) { + return parenthesize("group", {node.expression}); + } else if constexpr(std::is_same_v) { + switch (node.value.type) { + case ObjectType::NIL: + return "nil"; + case ObjectType::IDENTIFIER: + case ObjectType::STRING_LIT: { + std::string value = std::get(node.value.value); + return value; + } + case ObjectType::NUMBER: { + double value = std::get(node.value.value); + return std::to_string(value); + } + } + } else if constexpr(std::is_same_v) { + return parenthesize(node.op.lexeme, {node.right}); + } + + return ""; + }, expr); +} + +std::string AstPrinter::parenthesize(const std::string &name, std::vector 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 << ')'; + + return ss.str(); +} diff --git a/cclox_src/parser/expr.hh b/cclox_src/parser/expr.hh new file mode 100644 index 0000000..3f0ecd3 --- /dev/null +++ b/cclox_src/parser/expr.hh @@ -0,0 +1,46 @@ +#ifndef EXPR_HH +#define EXPR_HH + +#include "../tokenizer.hh" +#include +#include + +struct Expr {}; + +struct Binary : public Expr { + Binary(Expr left, Token op, Expr right) : left{left}, op{op}, right{right} {}; + + Expr left; + Token op; + Expr right; +}; + +struct Grouping : public Expr { + Grouping(Expr expr) : expression{expr} {}; + + Expr expression; +}; + +struct Literal : public Expr { + Literal(Object value) : value{value} {}; + + Object value; +}; + +struct Unary : public Expr { + Unary(Token op, Expr right) : op{op}, right{right} {}; + + Token op; + Expr right; +}; + +using Expression = std::variant; + +class AstPrinter { +public: + std::string print(const Expression &expr); +private: + std::string parenthesize(const std::string &name, std::vector exprs); +}; + +#endif