diff --git a/src/lexer.l b/src/lexer.l index 9c0d989..6c6c927 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -39,8 +39,9 @@ DIGIT [0-9] "while" {return WHILE;} "print" {return PRINT;} "input" {return INPUT;} -{DIGIT}*"."?{DIGIT}+ {yylval.value = make_node(VALUE, atof(yytext), ""); return VALUE;} -[_a-zA-Z][_a-zA-Z0-9]* {yylval.value = make_node(IDENTIFIER, 0, strdup(yytext)); return IDENTIFIER;} +{DIGIT} {yylval.value = make_node(VALUE, make_value(LONG, atoi(yytext), 0), ""); return VALUE;} +{DIGIT}*"."?{DIGIT}+ {yylval.value = make_node(VALUE, make_value(DOUBLE, 0, atof(yytext)), ""); return VALUE;} +[_a-zA-Z][_a-zA-Z0-9]* {yylval.value = make_node(IDENTIFIER, NULL, strdup(yytext)); return IDENTIFIER;} [\n] {linenum++;} [ \t\r]+ {} . {printf("Error: invlaid lexeme '%s'.\n", yytext); return 0;} diff --git a/src/node.h b/src/node.h index e607b1c..3b410cb 100644 --- a/src/node.h +++ b/src/node.h @@ -6,13 +6,16 @@ #define STATEMENT 200 #define MAX_VARIABLES 200 +#define DOUBLE 300 +#define LONG 301 + // Share the line number between files extern int linenum; /* a tree node definition */ struct Node { int type; - double value; + struct Value* value; /* the id of the node (used for identifiers only) */ char id[ID_SIZE]; @@ -23,7 +26,7 @@ struct Node { }; // Abstract Syntax Tree Functions -struct Node* make_node(int type, double value, char* id); +struct Node* make_node(int type, struct Value* value, char* id); void attach_node(struct Node* parent, struct Node* child); void print_tree(struct Node* node, int tabs); void delete_tree(struct Node* node); @@ -31,7 +34,7 @@ void delete_tree(struct Node* node); struct Variable { char id[ID_SIZE]; - double value; + struct Value* value; }; typedef union typeval { @@ -45,15 +48,17 @@ struct Value { }; // Value functions -int get_int(struct Value* val); +struct Value* make_value(int type, long num, double dec); +void delete_value(struct Value* val); +long get_long(struct Value* val); double get_double(struct Value* val); -void set_int(struct Value* val); -void set_double(struct Value* val); +void set_long(struct Value* val, long num); +void set_double(struct Value* val, double dec); // Variable Functions -struct Variable* make_variable(char* id, double value); -void set_value(struct Variable* var, double value); -double get_value(struct Variable* var); +struct Variable* make_variable(char* id, struct Value* value); +void set_value(struct Variable* var, struct Value* value); +struct Value* get_value(struct Variable* var); struct Environment { int num_vars; @@ -69,6 +74,6 @@ void add_variable(struct Environment* env, struct Variable* var); // Interpreting AST void eval_statement(struct Node* node, struct Environment* env); -double eval_expression(struct Node* node, struct Environment* env); +struct Value* eval_expression(struct Node* node, struct Environment* env); #endif diff --git a/src/parser.y b/src/parser.y index e5c8565..c9e9db9 100644 --- a/src/parser.y +++ b/src/parser.y @@ -70,32 +70,32 @@ statement: assignment { $$ = $1; } | statements { $$ = $1; } assignment: ident ASSIGN expression SEMICOLON { - $$ = make_node(ASSIGN, 0, ""); + $$ = make_node(ASSIGN, NULL, ""); attach_node($$, $1); attach_node($$, $3); } if-statement: IF expression THEN statement { - $$ = make_node(IF, 0, ""); + $$ = make_node(IF, NULL, ""); attach_node($$, $2); attach_node($$, $4); } if-else-statement: IF expression THEN statement ELSE statement { - $$ = make_node(IF, 0, ""); + $$ = make_node(IF, NULL, ""); attach_node($$, $2); attach_node($$, $4); attach_node($$, $6); } while: WHILE expression DO statement { - $$ = make_node(WHILE, 0, ""); + $$ = make_node(WHILE, NULL, ""); attach_node($$, $2); attach_node($$, $4); } print: PRINT expression SEMICOLON { - $$ = make_node(PRINT, 0, ""); + $$ = make_node(PRINT, NULL, ""); attach_node($$, $2); } @@ -103,31 +103,31 @@ print: PRINT expression SEMICOLON { statements: BEGINTOK substatements END { $$ = $2; } | BEGINTOK END {} -substatements: statement substatements {$$ = make_node(STATEMENT, 0, ""); attach_node($$, $1); attach_node($$, $2); } - | statement {$$ = make_node(STATEMENT, 0, ""); attach_node($$, $1); } +substatements: statement substatements {$$ = make_node(STATEMENT, NULL, ""); attach_node($$, $1); attach_node($$, $2); } + | statement {$$ = make_node(STATEMENT, NULL, ""); attach_node($$, $1); } -expression : expression OR subexpression { $$ = make_node(OR, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | expression AND subexpression { $$ = make_node(AND, 0, ""); attach_node($$, $1); attach_node($$, $3);} +expression : expression OR subexpression { $$ = make_node(OR, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | expression AND subexpression { $$ = make_node(AND, NULL, ""); attach_node($$, $1); attach_node($$, $3);} | subexpression { $$ = $1; } -subexpression: subexpression LESS term { $$ = make_node(LESS, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | subexpression LESSEQ term { $$ = make_node(LESSEQ, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | subexpression GREATER term { $$ = make_node(GREATER, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | subexpression GREATEREQ term { $$ = make_node(GREATEREQ, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | subexpression EQUALS term { $$ = make_node(EQUALS, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | subexpression NEQUALS term { $$ = make_node(NEQUALS, 0, ""); attach_node($$, $1); attach_node($$, $3);} +subexpression: subexpression LESS term { $$ = make_node(LESS, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | subexpression LESSEQ term { $$ = make_node(LESSEQ, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | subexpression GREATER term { $$ = make_node(GREATER, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | subexpression GREATEREQ term { $$ = make_node(GREATEREQ, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | subexpression EQUALS term { $$ = make_node(EQUALS, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | subexpression NEQUALS term { $$ = make_node(NEQUALS, NULL, ""); attach_node($$, $1); attach_node($$, $3);} | term { $$ = $1; } -term : term PLUS subterm { $$ = make_node(PLUS, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | term MINUS subterm { $$ = make_node(MINUS, 0, ""); attach_node($$, $1); attach_node($$, $3);} +term : term PLUS subterm { $$ = make_node(PLUS, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | term MINUS subterm { $$ = make_node(MINUS, NULL, ""); attach_node($$, $1); attach_node($$, $3);} | subterm { $$ = $1; } -subterm: subterm TIMES factor { $$ = make_node(TIMES, 0, ""); attach_node($$, $1); attach_node($$, $3);} - | subterm DIVIDE factor { $$ = make_node(DIVIDE, 0, ""); attach_node($$, $1); attach_node($$, $3);} +subterm: subterm TIMES factor { $$ = make_node(TIMES, NULL, ""); attach_node($$, $1); attach_node($$, $3);} + | subterm DIVIDE factor { $$ = make_node(DIVIDE, NULL, ""); attach_node($$, $1); attach_node($$, $3);} | factor { $$ = $1; } -factor : MINUS factor { $$ = make_node(MINUS, 0, ""); attach_node($$, $2); } - | NOT factor { $$ = make_node(NOT, 0, ""); attach_node($$, $2); } +factor : MINUS factor { $$ = make_node(MINUS, NULL, ""); attach_node($$, $2); } + | NOT factor { $$ = make_node(NOT, NULL, ""); attach_node($$, $2); } | atom { $$ = $1; } atom: OPENPAREM expression ENDPAREM { $$ = $2; } @@ -137,7 +137,7 @@ ident: IDENTIFIER { $$ = $1; } identvalue: IDENTIFIER { $$ = $1; } | VALUE { $$ = $1; } - | INPUT { $$ = make_node(INPUT, 0 , ""); } + | INPUT { $$ = make_node(INPUT, NULL , ""); } @@ -184,7 +184,7 @@ int main(int argc, char* argv[]) { /* creates a new node and returns it */ -struct Node* make_node(int type, double value, char* id) { +struct Node* make_node(int type, struct Value* value, char* id) { int i; /* allocate space */ @@ -212,6 +212,7 @@ void attach_node(struct Node* parent, struct Node* child) { } void print_tree(struct Node* node, int tabs) { + int i; /* base case */ if(!node) { fprintf(stderr, "NO TREE STRUCTURE\n"); @@ -219,13 +220,12 @@ void print_tree(struct Node* node, int tabs) { } /* print leading tabs */ - for(int i = 0; i < tabs; i++) { + for(i = 0; i < tabs; i++) { printf(" "); } switch(node->type) { case IDENTIFIER: printf("IDENTIFIER: %s\n", node->id); break; - case VALUE: printf("VALUE: %lf\n", node->value); break; case PLUS: printf("PLUS:\n"); break; case MINUS: printf("MINUS:\n"); break; case DIVIDE: printf("DIVIDE:\n"); break; @@ -245,6 +245,13 @@ void print_tree(struct Node* node, int tabs) { case PRINT: printf("PRINT:\n"); break; case INPUT: printf("INPUT:\n"); break; case STATEMENT: printf("STATEMENT:\n"); break; + case VALUE: + if (node->value->type == LONG) { + printf("VALUE: %li\n", get_long(node->value)); + } else { // Assume double + printf("VALUE: %lf\n", get_double(node->value)); + } + break; default: printf("Error, %d not a valid node type.\n", node->type); exit(1); @@ -265,7 +272,7 @@ void delete_tree(struct Node* node) { } /* creates a new variable and returns it */ -struct Variable* make_variable(char* id, double value) { +struct Variable* make_variable(char* id, struct Value* value) { /* allocate space */ struct Variable* var = malloc(sizeof(struct Variable)); @@ -277,12 +284,12 @@ struct Variable* make_variable(char* id, double value) { return var; } -void set_value(struct Variable* var, double value) { +void set_value(struct Variable* var, struct Value* value) { if (!var) { fprintf(stderr, "Error: Invalid Variable\n"); return; } var->value = value; } -double get_value(struct Variable* var) { +struct Value* get_value(struct Variable* var) { if (!var) { fprintf(stderr, "Error: Invalid Variable\n"); return 0; } return var->value; } @@ -337,7 +344,281 @@ void check_num_nodes(struct Node* node, int num_children, char* error) { } } -double eval_expression(struct Node* node, struct Environment* env) { +struct Value* make_value(int type, long num, double dec) { + /* allocate space */ + struct Value* val = malloc(sizeof(struct Value)); + + /* set properties */ + val->type = type; + if (type == LONG) { + val->value.num = num; + } else { // Assume DOUBLE + val->value.dec = dec; + } + + /* return new variable */ + return val; +} +void delete_value(struct Value* val) { + free(val); +} +long get_long(struct Value* val) { + return val->value.num; +} +double get_double(struct Value* val) { + return val->value.dec; +} +void set_long(struct Value* val, long num) { + val->type = LONG; + val->value.num = num; +} +void set_double(struct Value* val, double dec) { + val->type = DOUBLE; + val->value.dec = dec; +} +struct Value* add(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in add.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) + get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) + get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) + get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) + get_double(y)); + } + + return ans; +} + +struct Value* subtract(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in subtract.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) - get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) - get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) - get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) - get_double(y)); + } + + return ans; +} + +struct Value* division(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in divide.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) / get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) / get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) / get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) / get_double(y)); + } + + return ans; +} + +struct Value* multiplication(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in multiply.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) * get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) * get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) * get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) * get_double(y)); + } + + return ans; +} + +struct Value* less(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in <.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) < get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) < get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) < get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) < get_double(y)); + } + + return ans; +} + +struct Value* greater(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in greater.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) > get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) > get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) > get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) > get_double(y)); + } + + return ans; +} + +struct Value* less_equal(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in <=.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) <= get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) <= get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) <= get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) <= get_double(y)); + } + + return ans; +} + +struct Value* greater_equal(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in >=.\n"); } + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) >= get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) >= get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) >= get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) >= get_double(y)); + } + + return ans; +} + +struct Value* equals(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in ==.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) == get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) == get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) == get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) == get_double(y)); + } + + return ans; +} + +struct Value* not_equals(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in !=.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) != get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) != get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) != get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) != get_double(y)); + } + + return ans; +} + +struct Value* and(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in &&.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) && get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) && get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) && get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) && get_double(y)); + } + + return ans; +} + +struct Value* or(struct Value* x, struct Value* y) { + if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in ||.\n"); } + + struct Value* ans; + + // Destruct all four cases + if (x->type == LONG && y->type == LONG) { + ans = make_value(LONG, get_long(x) || get_long(y), 0); + } else if (x->type == LONG && y->type == DOUBLE) { + ans = make_value(DOUBLE, 0, get_long(x) || get_double(y)); + } else if (x->type == DOUBLE && y->type == LONG) { + ans = make_value(DOUBLE, 0, get_double(x) || get_long(y)); + } else { // Both are DOUBLE + ans = make_value(DOUBLE, 0, get_double(x) || get_double(y)); + } + + return ans; +} + +struct Value* not(struct Value* x) { + if (!x) { fprintf(stderr, "Error, uninitialized values being used in !.\n"); } + + struct Value* ans; + + // Destruct all two cases + if (x->type == LONG) { + ans = make_value(LONG, !get_long(x), 0); + } else { // Assume it's a double + ans = make_value(DOUBLE, 0, !get_double(x)); + } + + return ans; +} + +struct Value* eval_expression(struct Node* node, struct Environment* env) { /* base case */ if(!node) { fprintf(stderr, "Error: No tree structure to evaluate\n"); @@ -349,13 +630,16 @@ double eval_expression(struct Node* node, struct Environment* env) { struct Variable* var = NULL; // Evaluate subexpressions if existent - double val1, val2, val3; + struct Value* val1 = NULL; + struct Value* val2 = NULL; + struct Value* val3 = NULL; if (node->num_children > 0) { val1 = eval_expression(node->children[0], env); if (node->num_children > 1) { val2 = eval_expression(node->children[1], env); if (node->num_children > 2) { val3 = eval_expression(node->children[2], env); + // delete_value(val3); // No code below uses val3 for now... } } } @@ -363,73 +647,87 @@ double eval_expression(struct Node* node, struct Environment* env) { switch(node->type) { case PLUS: check_num_nodes(node, 2, "cannot add more than two expressions."); - return val1 + val2; + return add(val1, val2); + // return val1 + val2; break; //---------- case MINUS: check_num_nodes(node, 2, "cannot subtract more than two expressions."); - return val1 - val2; + return subtract(val1, val2); + // return val1 - val2; break; //---------- case DIVIDE: check_num_nodes(node, 2, "cannot divide more than two expressions."); - return val1 / val2; + return division(val1, val2); + // return val1 / val2; break; //---------- case TIMES: check_num_nodes(node, 2, "cannot multiply more than two expressions."); - return val1 * val2; + return multiplication(val1, val2); + // return val1 * val2; break; //---------- case LESS: check_num_nodes(node, 2, "cannot compare more than two expressions."); if (node->num_children != 2) { fprintf(stderr, "Error, cannot compare more than two expressions.\n"); } - return val1 < val2; + return less(val1, val2); + // return val1 < val2; break; //---------- case GREATER: check_num_nodes(node, 2, "cannot compare more than two expressions."); - return val1 > val2; + return greater(val1, val2); + // return val1 > val2; break; //---------- case LESSEQ: check_num_nodes(node, 2, "cannot compare more than two expressions."); - return val1 <= val2; + return less_equal(val1, val2); + // return val1 <= val2; break; //---------- case GREATEREQ: check_num_nodes(node, 2, "cannot compare more than two expressions."); - return val1 >= val2; + return greater_equal(val1, val2); + // return val1 >= val2; break; //---------- case EQUALS: check_num_nodes(node, 2, "cannot compare more than two expressions."); - return val1 == val2; + return equals(val1, val2); + // return val1 == val2; break; //---------- case NEQUALS: check_num_nodes(node, 2, "cannot compare more than two expressions."); - return val1 != val2; + return not_equals(val1, val2); + // return val1 != val2; break; //---------- case AND: check_num_nodes(node, 2, "cannot perform logical operators on more than two expressions."); - return val1 && val2; + return and(val1, val2); + // return val1 && val2; break; //---------- case OR: check_num_nodes(node, 2, "cannot perform logical operators on more than two expressions."); - return val1 || val2; + return or(val1, val2); + // return val1 || val2; break; //---------- case NOT: check_num_nodes(node, 1, "cannot negate more than one expressions."); - return !val1; + return not(val1); + // return !val1; break; //---------- - case INPUT: + case INPUT: // We're only going to support reading in doubles + // Look into deleting possible values...? scanf("%lf", &temp); - return temp; + return make_value(DOUBLE, 0, temp); break; //---------- case IDENTIFIER: @@ -459,6 +757,7 @@ void eval_statement(struct Node* node, struct Environment* env) { fprintf(stderr, "Error: No tree structure to evaluate\n"); return; } + struct Value* tempVal; switch(node->type) { case ASSIGN: @@ -472,23 +771,47 @@ void eval_statement(struct Node* node, struct Environment* env) { if (node->num_children != 2 && node->num_children != 3) { fprintf(stderr, "Error: The format of an if-statement is if expression statement with an optional else.\n"); } - if (eval_expression(node->children[0], env)) { - eval_statement(node->children[1], env); - } else if (node->num_children == 3) { + tempVal = eval_expression(node->children[0], env); + if (tempVal->type == LONG) { + if (get_long(tempVal)) { + eval_statement(node->children[1], env); + } else if (node->num_children == 3) { eval_statement(node->children[2], env); + } + } else { // Assume DOUBLE + if (get_double(tempVal)) { + eval_statement(node->children[1], env); + } else if (node->num_children == 3) { + eval_statement(node->children[2], env); + } } break; //------------ case WHILE: check_num_nodes(node, 2, "the format of a while statement is: while expression statement(s)"); - while (eval_expression(node->children[0], env)) { - eval_statement(node->children[1], env); + tempVal = eval_expression(node->children[0], env); + if (tempVal->type == LONG) { + while (get_long(tempVal)) { + eval_statement(node->children[1], env); + tempVal = eval_expression(node->children[0], env); + } + } else { // Assume DOUBLE + while (get_double(tempVal)) { + eval_statement(node->children[1], env); + tempVal = eval_expression(node->children[0], env); + } } + break; //------------ case PRINT: check_num_nodes(node, 1, "can only print out one expression at a time."); - printf("%lf\n", eval_expression(node->children[0], env)); + tempVal = eval_expression(node->children[0], env); + if (tempVal->type == LONG) { + printf("%li\n", get_long(tempVal)); + } else { + printf("%lf\n", get_double(tempVal)); + } break; //------------ case STATEMENT: // Can have a maximum of two children statement nodes