diff --git a/Makefile b/Makefile index 3ed94d1..0a9b5b2 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,14 @@ all: parse parser.cpp parser.hpp: parser.y bison -d -o parser.cpp parser.y +tree.o: tree.cpp + g++ -g -c -o tree.o tree.cpp + scanner.cpp: scanner.l flex -o scanner.cpp scanner.l -parse: main.cpp parser.cpp scanner.cpp - g++ main.cpp parser.cpp scanner.cpp -o parse +parse: main.cpp parser.cpp scanner.cpp tree.o + g++ -g main.cpp parser.cpp scanner.cpp tree.o -o parse clean: - rm -f parse scanner.cpp parser.cpp parser.hpp + rm -f parse scanner.cpp parser.cpp parser.hpp tree.o diff --git a/main.cpp b/main.cpp index 3e2ab16..1f131de 100644 --- a/main.cpp +++ b/main.cpp @@ -9,6 +9,13 @@ extern stmt_ptr target_program; int main() { if (!yylex()) { + std::vector dest; + target_program->print_dot(dest, "start"); + std::cout << "digraph G {" << std::endl; + for(auto& line : dest) { + std::cout << line << std::endl; + } + std::cout << "}" << std::endl; delete target_program; } } diff --git a/parser.y b/parser.y index a902a6f..bbb1c3c 100644 --- a/parser.y +++ b/parser.y @@ -134,7 +134,7 @@ condition ; if_statement - : IF condition COLON NEWLINE block elif_blocks else_block { $$ = new stmt_if($2, $6, $7); delete $6; } + : IF condition COLON NEWLINE block elif_blocks else_block { $$ = new stmt_if($2, $5, $7); delete $6; } ; elif_blocks diff --git a/tree.cpp b/tree.cpp new file mode 100644 index 0000000..bc9bf0f --- /dev/null +++ b/tree.cpp @@ -0,0 +1,146 @@ +#include "tree.hpp" +#include + +template +std::string label(T v) { + return std::to_string(v); +} + +template <> +std::string label(std::string v) { + return v; +} + +template <> +std::string label(const char* v) { + return v; +} + +template <> +std::string label(binop op) { + switch(op) { + case binop::plus: + return "+"; + case binop::minus: + return "-"; + case binop::times: + return "*"; + case binop::divide: + return "/"; + case binop::land: + return "&&"; + case binop::lor: + return "||"; + case binop::eq: + return "=="; + case binop::neq: + return "!="; + case binop::lt: + return "<"; + case binop::lte: + return "<="; + case binop::gt: + return ">"; + case binop::gte: + return ">="; + default: + return ""; + } +} + +template <> +std::string label(unop op) { + switch(op) { + case unop::lnot: + return "!"; + default: + return ""; + } +} + +template +std::string wrap_label(T v) { + return std::string(" [label=\"") + label(v) + "\"]"; +} + +void expr_id::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label(id)); +} + +void expr_int::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label(val)); +} + +void expr_float::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label(val)); +} + +void expr_binop::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label(op)); + std::string lp = prefix + "_left"; + std::string rp = prefix + "_right"; + left->print_dot(into, lp); + right->print_dot(into, rp); + into.push_back(prefix + "->" + lp); + into.push_back(prefix + "->" + rp); +} + +void expr_unop::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label(op)); + std::string cp = prefix + "_child"; + child->print_dot(into, cp); + into.push_back(prefix + "->" + cp); +} + +void expr_assign::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label(var + "=")); + std::string cp = prefix + "_child"; + child->print_dot(into, cp); + into.push_back(prefix + "->" + cp); +} + +void stmt_block::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label("block")); + int index = 0; + for(auto& child : children) { + std::string cp = prefix + "_" + std::to_string(index); + child->print_dot(into, cp); + into.push_back(prefix + "->" + cp); + index++; + } +} + +void stmt_if::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label("if")); + std::string cp = prefix + "_cond"; + std::string tp = prefix + "_then"; + std::string ep = prefix + "_else"; + + cond->print_dot(into, cp); + then->print_dot(into, tp); + if(els) els->print_dot(into, ep); + + into.push_back(prefix + "->" + cp); + into.push_back(prefix + "->" + tp); + if(els) into.push_back(prefix + "->" + ep); +} + +void stmt_while::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label("while")); + std::string cp = prefix + "_cond"; + std::string bp = prefix + "_body"; + + cond->print_dot(into, cp); + body->print_dot(into, bp); + + into.push_back(prefix + "->" + cp); + into.push_back(prefix + "->" + bp); +} + +void stmt_break::print_dot(dot& into, std::string prefix) { + into.push_back(prefix + wrap_label("break")); +} + +void stmt_expr::print_dot(dot& into, std::string prefix) { + child->print_dot(into, prefix); +} diff --git a/tree.hpp b/tree.hpp index b1a291b..0a22fc1 100644 --- a/tree.hpp +++ b/tree.hpp @@ -2,6 +2,8 @@ #include #include +typedef std::vector dot; + enum class binop { plus, minus, @@ -23,6 +25,8 @@ enum class unop { struct expr { virtual ~expr() = default; + + virtual void print_dot(dot& into, std::string prefix) = 0; }; typedef expr* expr_ptr; @@ -32,18 +36,24 @@ struct expr_id : expr { expr_id(std::string i) : id(std::move(i)) {} + + virtual void print_dot(dot& into, std::string prefix); }; struct expr_int : expr { int val; expr_int(int i) : val(i) {} + + virtual void print_dot(dot& into, std::string prefix); }; struct expr_float : expr { double val; expr_float(double f) : val(f) {} + + virtual void print_dot(dot& into, std::string prefix); }; struct expr_binop : expr { @@ -53,6 +63,8 @@ struct expr_binop : expr { expr_binop(binop nop, expr_ptr l, expr_ptr r) : op(nop), left(std::move(l)), right(std::move(r)) {} + + virtual void print_dot(dot& into, std::string prefix); }; struct expr_unop : expr { @@ -61,6 +73,8 @@ struct expr_unop : expr { expr_unop(unop nop, expr_ptr c) : op(nop), child(std::move(c)) {} + + virtual void print_dot(dot& into, std::string prefix); }; struct expr_assign : expr { @@ -69,6 +83,8 @@ struct expr_assign : expr { expr_assign(std::string v, expr_ptr c) : var(std::move(v)), child(std::move(c)) {} + + virtual void print_dot(dot& into, std::string prefix); }; template @@ -78,12 +94,16 @@ expr_ptr make_expr(Ts&& ... ts) { struct stmt { virtual ~stmt() = default; + + virtual void print_dot(dot& into, std::string prefix) = 0; }; typedef stmt* stmt_ptr; struct stmt_block : stmt { std::vector children; + + virtual void print_dot(dot& into, std::string prefix); }; struct stmt_if : stmt { @@ -93,6 +113,8 @@ struct stmt_if : stmt { stmt_if(expr_ptr c, stmt_ptr t, stmt_ptr e = nullptr) : cond(std::move(c)), then(std::move(t)), els(std::move(e)) {} + + virtual void print_dot(dot& into, std::string prefix); }; struct stmt_while : stmt { @@ -101,10 +123,12 @@ struct stmt_while : stmt { stmt_while(expr_ptr c, stmt_ptr b) : cond(std::move(c)), body(std::move(b)) {} + + virtual void print_dot(dot& into, std::string prefix); }; struct stmt_break : stmt { - + virtual void print_dot(dot& into, std::string prefix); }; struct stmt_expr : stmt { @@ -112,6 +136,8 @@ struct stmt_expr : stmt { stmt_expr(expr_ptr c) : child(std::move(c)) {} + + virtual void print_dot(dot& into, std::string prefix); }; template