diff --git a/src/operations/node.cpp b/src/operations/node.cpp index 8258ee1..04ec804 100644 --- a/src/operations/node.cpp +++ b/src/operations/node.cpp @@ -21,47 +21,53 @@ void check_num_nodes(Node* node, uint num_children, std::string error) { } } -void print_tree(Node* node, uint tabs) { +std::ostream & operator << (std::ostream &out, const Node* n) { + out << n->toString(); + return out; +} + +std::string Node::toString() const { + return tree_string(this, 0); +} + +std::string tree_string(const Node* node, uint tabs) { + std::string result = ""; uint i; /* base case */ if(!node) { - std::cerr << "NO TREE STRUCTURE" << std::endl; - return; + result += "NO TREE STRUCTURE\n"; + return result; } /* print leading tabs */ for(i = 0; i < tabs; i++) { - std::cout << " "; + result += " "; } switch(node->type) { - case IDENTIFIER: std::cout << "IDENTIFIER: " << node->id << std::endl; break; - case PLUS: std::cout << "PLUS:" << std::endl; break; - case MINUS: std::cout << "MINUS:" << std::endl; break; - case DIVIDE: std::cout << "DIVIDE:" << std::endl; break; - case TIMES: std::cout << "TIMES:" << std::endl; break; - case LESS: std::cout << "LESS THAN:" << std::endl; break; - case GREATER: std::cout << "GREATER:" << std::endl; break; - case LESSEQ: std::cout << "LESS EQUAL:" << std::endl; break; - case GREATEREQ: std::cout << "GREATER EQUAL:" << std::endl; break; - case EQUALS: std::cout << "EQUAL:" << std::endl; break; - case NEQUALS: std::cout << "NOT EQUAL:" << std::endl; break; - case AND: std::cout << "AND:" << std::endl; break; - case OR: std::cout << "OR:" << std::endl; break; - case NOT: std::cout << "NOT:" << std::endl; break; - case ASSIGN: std::cout << "ASSIGN:" << std::endl; break; - case IF: std::cout << "IF:" << std::endl; break; - case WHILE: std::cout << "WHILE:" << std::endl; break; - case PRINT: std::cout << "PRINT:" << std::endl; break; - case INPUT: std::cout << "INPUT:" << std::endl; break; - case LAMBDATAG: std::cout << "LAMBDA:" << std::endl; break; - case CALLFUNC: std::cout << "FUNCCALL:" << std::endl; break; - case STATEMENT: std::cout << "STATEMENT:" << std::endl; break; - case VALUE: - std::cout << "VALUE: "; - print_value(node->value); - std::cout << std::endl; - break; + case IDENTIFIER: result += "IDENTIFIER: " + node->id + "\n"; break; + case PLUS: result += "PLUS:\n"; break; + case MINUS: result += "MINUS:\n"; break; + case DIVIDE: result += "DIVIDE:\n"; break; + case TIMES: result += "TIMES:\n"; break; + case LESS: result += "LESS THAN:\n"; break; + case GREATER: result += "GREATER:\n"; break; + case LESSEQ: result += "LESS EQUAL:\n"; break; + case GREATEREQ: result += "GREATER EQUAL:\n"; break; + case EQUALS: result += "EQUAL:\n"; break; + case NEQUALS: result += "NOT EQUAL:\n"; break; + case AND: result += "AND:\n"; break; + case OR: result += "OR:\n"; break; + case NOT: result += "NOT:\n"; break; + case ASSIGN: result += "ASSIGN:\n"; break; + case IF: result += "IF:\n"; break; + case WHILE: result += "WHILE:\n"; break; + case PRINT: result += "PRINT:\n"; break; + case INPUT: result += "INPUT:\n"; break; + case LAMBDATAG: result += "LAMBDA:\n"; break; + case CALLFUNC: result += "FUNCCALL:\n"; break; + case STATEMENT: result += "STATEMENT:\n"; break; + case VALUE: result += "VALUE: " + node->value->toString() + "\n"; break; default: std::cerr << "Error, " << node->type << " is not a valid node type." << std::endl; exit(1); @@ -69,10 +75,11 @@ void print_tree(Node* node, uint tabs) { /* print all children nodes underneath */ for(i = 0; i < node->num_children; i++) { - print_tree(node->children[i], tabs + 1); + result += tree_string(node->children[i], tabs + 1); } -} + return result; +} Value* eval_expression(Node* node, Environment* env) { /* base case */ @@ -195,7 +202,6 @@ Value* eval_expression(Node* node, Environment* env) { break; //---------- case INPUT: // We're only going to support reading in doubles - // Look into deleting possible values...? scanf("%lf", &temp); return make_double(temp); break; @@ -271,8 +277,7 @@ void eval_statement(Node* node, Environment* env) { case PRINT: check_num_nodes(node, 1, "can only print out one expression at a time."); tempVal = eval_expression(node->children[0], env); - print_value(tempVal); - printf("\n"); + std::cout << tempVal << std::endl; break; //------------ case STATEMENT: // Can have a maximum of two children statement nodes diff --git a/src/operations/node.hpp b/src/operations/node.hpp index be56618..1773c9b 100644 --- a/src/operations/node.hpp +++ b/src/operations/node.hpp @@ -24,7 +24,11 @@ class Node { /* at most three children nodes */ uint num_children; std::array children; - + + friend std::ostream & operator << (std::ostream &out, const Node* n); + + std::string toString(void) const; + Node(int t, Value* v, std::string s) { type = t; value = v; @@ -45,7 +49,7 @@ class Node { // Abstract Syntax Tree Functions // struct Node* make_node(int type, struct Value* value, std::string id); void attach_node(Node* parent, Node* child); -void print_tree(Node* node, int tabs); +std::string tree_string(const Node* node, uint tabs); // Interpreting AST void eval_statement(Node* node, Environment* env); diff --git a/src/variables/value.cpp b/src/variables/value.cpp index d0f7eab..cacf211 100644 --- a/src/variables/value.cpp +++ b/src/variables/value.cpp @@ -31,26 +31,21 @@ void delete_value(Value* val) { free(val); } -long get_long(Value* val) { - // return val->value.num; +long get_long(const Value* val) { return std::get(val->val); } -double get_double(Value* val) { - // return val->value.dec; +double get_double(const Value* val) { return std::get(val->val); } -Node* get_expression(Value* val) { - // return val->value.expr; +Node* get_expression(const Value* val) { return std::get(val->val); } -std::string get_string(Value* val) { - // return val->value.str; +std::string get_string(const Value* val) { return std::get(val->val); } void set_long(Value* val, long num) { val->type = LONG; - // val->value.num = num; val->val = num; } void set_double(Value* val, double dec) { @@ -60,29 +55,36 @@ void set_double(Value* val, double dec) { } void set_expression(Value* val, Node* expr) { val->type = LAMBDA; - // val->value.expr = expr; val->val = expr; } void set_sring(Value* val, std::string str) { val->type = STRING; - // val->value.str = str; val->val = str; } -void print_value(Value* val) { - if (val->type == BOOLEAN) { - if (get_long(val)) { - std::cout << "true"; +std::string Value::toString() const { + std::string result = ""; + if (this->type == BOOLEAN) { + if (get_long(this)) { + result += "true"; } else { - std::cout << "false"; + result += "false"; } - } else if (val->type == LONG) { - std::cout << get_long(val); - } else if (val->type == STRING) { - std::cout << get_string(val); - } else if (val->type == DOUBLE) { - std::cout << get_double(val); + } else if (this->type == LONG) { + result += get_long(this); + } else if (this->type == STRING) { + result += get_string(this); + } else if (this->type == DOUBLE) { + result += get_double(this); } else { // Assume lambda expression - std::cout << ""; + result += ""; } + + return result; } + +std::ostream & operator << (std::ostream &out, const Value* val) { + out << val->toString(); + return out; +} + diff --git a/src/variables/value.hpp b/src/variables/value.hpp index a008e9a..063c417 100644 --- a/src/variables/value.hpp +++ b/src/variables/value.hpp @@ -15,6 +15,11 @@ class Value { enum TypeTag type; std::variant val; + // << Overload + friend std::ostream & operator << (std::ostream &out, const Value* val); + std::string toString() const; + + // Constructor Value(TypeTag t, long n, double d, Node* e, std::string s) { /* set properties */ type = t; @@ -30,35 +35,34 @@ class Value { } } + // Destructor ~Value() { std::cout << "VALUE DESTROYED" << std::endl; } }; // Constructors -struct Value* make_long(long num); -struct Value* make_double(double dec); -struct Value* make_true(); -struct Value* make_false(); -struct Value* make_boolean(int x); -struct Value* make_expression(struct Node* expr); -struct Value* make_string(std::string str); +Value* make_long(long num); +Value* make_double(double dec); +Value* make_true(); +Value* make_false(); +Value* make_boolean(int x); +Value* make_expression(Node* expr); +Value* make_string(std::string str); // Destructor -void delete_value(struct Value* val); +void delete_value(Value* val); // Getters -long get_long(struct Value* val); -double get_double(struct Value* val); -struct Node* get_expression(struct Value* val); -std::string get_string(struct Value* val); +long get_long(const Value* val); +double get_double(const Value* val); +Node* get_expression(const Value* val); +std::string get_string(const Value* val); // Setters -void set_long(struct Value* val, long num); -void set_double(struct Value* val, double dec); -void set_expression(struct Value* val, struct Node* node); -void set_string(struct Value* val, std::string str); - -void print_value(struct Value* val); +void set_long(Value* val, long num); +void set_double(Value* val, double dec); +void set_expression(Value* val, Node* node); +void set_string(Value* val, std::string str); #endif