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