Made toString functions and overloaded the stream operator
This commit is contained in:
parent
8dd2e789c0
commit
d740cc17af
4 changed files with 94 additions and 79 deletions
|
@ -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
|
||||
|
|
|
@ -24,7 +24,11 @@ class Node {
|
|||
/* at most three children nodes */
|
||||
uint num_children;
|
||||
std::array<Node*, MAX_CHILDREN> 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);
|
||||
|
|
|
@ -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<long>(val->val);
|
||||
}
|
||||
double get_double(Value* val) {
|
||||
// return val->value.dec;
|
||||
double get_double(const Value* val) {
|
||||
return std::get<double>(val->val);
|
||||
}
|
||||
Node* get_expression(Value* val) {
|
||||
// return val->value.expr;
|
||||
Node* get_expression(const Value* val) {
|
||||
return std::get<Node*>(val->val);
|
||||
}
|
||||
std::string get_string(Value* val) {
|
||||
// return val->value.str;
|
||||
std::string get_string(const Value* val) {
|
||||
return std::get<std::string>(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 << "<LambdaExpression>";
|
||||
result += "<LambdaExpression>";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream &out, const Value* val) {
|
||||
out << val->toString();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@ class Value {
|
|||
enum TypeTag type;
|
||||
std::variant<long, double, Node*, std::string> 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
|
||||
|
|
Reference in a new issue