Added an int type
This commit is contained in:
parent
0ddbe79d25
commit
16575da1dc
3 changed files with 392 additions and 63 deletions
|
@ -39,8 +39,9 @@ DIGIT [0-9]
|
||||||
"while" {return WHILE;}
|
"while" {return WHILE;}
|
||||||
"print" {return PRINT;}
|
"print" {return PRINT;}
|
||||||
"input" {return INPUT;}
|
"input" {return INPUT;}
|
||||||
{DIGIT}*"."?{DIGIT}+ {yylval.value = make_node(VALUE, atof(yytext), ""); return VALUE;}
|
{DIGIT} {yylval.value = make_node(VALUE, make_value(LONG, atoi(yytext), 0), ""); return VALUE;}
|
||||||
[_a-zA-Z][_a-zA-Z0-9]* {yylval.value = make_node(IDENTIFIER, 0, strdup(yytext)); return IDENTIFIER;}
|
{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++;}
|
[\n] {linenum++;}
|
||||||
[ \t\r]+ {}
|
[ \t\r]+ {}
|
||||||
. {printf("Error: invlaid lexeme '%s'.\n", yytext); return 0;}
|
. {printf("Error: invlaid lexeme '%s'.\n", yytext); return 0;}
|
||||||
|
|
25
src/node.h
25
src/node.h
|
@ -6,13 +6,16 @@
|
||||||
#define STATEMENT 200
|
#define STATEMENT 200
|
||||||
#define MAX_VARIABLES 200
|
#define MAX_VARIABLES 200
|
||||||
|
|
||||||
|
#define DOUBLE 300
|
||||||
|
#define LONG 301
|
||||||
|
|
||||||
// Share the line number between files
|
// Share the line number between files
|
||||||
extern int linenum;
|
extern int linenum;
|
||||||
|
|
||||||
/* a tree node definition */
|
/* a tree node definition */
|
||||||
struct Node {
|
struct Node {
|
||||||
int type;
|
int type;
|
||||||
double value;
|
struct Value* value;
|
||||||
|
|
||||||
/* the id of the node (used for identifiers only) */
|
/* the id of the node (used for identifiers only) */
|
||||||
char id[ID_SIZE];
|
char id[ID_SIZE];
|
||||||
|
@ -23,7 +26,7 @@ struct Node {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract Syntax Tree Functions
|
// 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 attach_node(struct Node* parent, struct Node* child);
|
||||||
void print_tree(struct Node* node, int tabs);
|
void print_tree(struct Node* node, int tabs);
|
||||||
void delete_tree(struct Node* node);
|
void delete_tree(struct Node* node);
|
||||||
|
@ -31,7 +34,7 @@ void delete_tree(struct Node* node);
|
||||||
|
|
||||||
struct Variable {
|
struct Variable {
|
||||||
char id[ID_SIZE];
|
char id[ID_SIZE];
|
||||||
double value;
|
struct Value* value;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union typeval {
|
typedef union typeval {
|
||||||
|
@ -45,15 +48,17 @@ struct Value {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Value functions
|
// 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);
|
double get_double(struct Value* val);
|
||||||
void set_int(struct Value* val);
|
void set_long(struct Value* val, long num);
|
||||||
void set_double(struct Value* val);
|
void set_double(struct Value* val, double dec);
|
||||||
|
|
||||||
// Variable Functions
|
// Variable Functions
|
||||||
struct Variable* make_variable(char* id, double value);
|
struct Variable* make_variable(char* id, struct Value* value);
|
||||||
void set_value(struct Variable* var, double value);
|
void set_value(struct Variable* var, struct Value* value);
|
||||||
double get_value(struct Variable* var);
|
struct Value* get_value(struct Variable* var);
|
||||||
|
|
||||||
struct Environment {
|
struct Environment {
|
||||||
int num_vars;
|
int num_vars;
|
||||||
|
@ -69,6 +74,6 @@ void add_variable(struct Environment* env, struct Variable* var);
|
||||||
|
|
||||||
// Interpreting AST
|
// Interpreting AST
|
||||||
void eval_statement(struct Node* node, struct Environment* env);
|
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
|
#endif
|
||||||
|
|
419
src/parser.y
419
src/parser.y
|
@ -70,32 +70,32 @@ statement: assignment { $$ = $1; }
|
||||||
| statements { $$ = $1; }
|
| statements { $$ = $1; }
|
||||||
|
|
||||||
assignment: ident ASSIGN expression SEMICOLON {
|
assignment: ident ASSIGN expression SEMICOLON {
|
||||||
$$ = make_node(ASSIGN, 0, "");
|
$$ = make_node(ASSIGN, NULL, "");
|
||||||
attach_node($$, $1);
|
attach_node($$, $1);
|
||||||
attach_node($$, $3);
|
attach_node($$, $3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if-statement: IF expression THEN statement {
|
if-statement: IF expression THEN statement {
|
||||||
$$ = make_node(IF, 0, "");
|
$$ = make_node(IF, NULL, "");
|
||||||
attach_node($$, $2);
|
attach_node($$, $2);
|
||||||
attach_node($$, $4);
|
attach_node($$, $4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if-else-statement: IF expression THEN statement ELSE statement {
|
if-else-statement: IF expression THEN statement ELSE statement {
|
||||||
$$ = make_node(IF, 0, "");
|
$$ = make_node(IF, NULL, "");
|
||||||
attach_node($$, $2);
|
attach_node($$, $2);
|
||||||
attach_node($$, $4);
|
attach_node($$, $4);
|
||||||
attach_node($$, $6);
|
attach_node($$, $6);
|
||||||
}
|
}
|
||||||
|
|
||||||
while: WHILE expression DO statement {
|
while: WHILE expression DO statement {
|
||||||
$$ = make_node(WHILE, 0, "");
|
$$ = make_node(WHILE, NULL, "");
|
||||||
attach_node($$, $2);
|
attach_node($$, $2);
|
||||||
attach_node($$, $4);
|
attach_node($$, $4);
|
||||||
}
|
}
|
||||||
|
|
||||||
print: PRINT expression SEMICOLON {
|
print: PRINT expression SEMICOLON {
|
||||||
$$ = make_node(PRINT, 0, "");
|
$$ = make_node(PRINT, NULL, "");
|
||||||
attach_node($$, $2);
|
attach_node($$, $2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,31 +103,31 @@ print: PRINT expression SEMICOLON {
|
||||||
statements: BEGINTOK substatements END { $$ = $2; }
|
statements: BEGINTOK substatements END { $$ = $2; }
|
||||||
| BEGINTOK END {}
|
| BEGINTOK END {}
|
||||||
|
|
||||||
substatements: statement substatements {$$ = make_node(STATEMENT, 0, ""); attach_node($$, $1); attach_node($$, $2); }
|
substatements: statement substatements {$$ = make_node(STATEMENT, NULL, ""); attach_node($$, $1); attach_node($$, $2); }
|
||||||
| statement {$$ = make_node(STATEMENT, 0, ""); attach_node($$, $1); }
|
| statement {$$ = make_node(STATEMENT, NULL, ""); attach_node($$, $1); }
|
||||||
|
|
||||||
expression : expression OR subexpression { $$ = make_node(OR, 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, 0, ""); attach_node($$, $1); attach_node($$, $3);}
|
| expression AND subexpression { $$ = make_node(AND, NULL, ""); attach_node($$, $1); attach_node($$, $3);}
|
||||||
| subexpression { $$ = $1; }
|
| subexpression { $$ = $1; }
|
||||||
|
|
||||||
subexpression: subexpression LESS term { $$ = make_node(LESS, 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, 0, ""); 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, 0, ""); 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, 0, ""); 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, 0, ""); 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, 0, ""); attach_node($$, $1); attach_node($$, $3);}
|
| subexpression NEQUALS term { $$ = make_node(NEQUALS, NULL, ""); attach_node($$, $1); attach_node($$, $3);}
|
||||||
| term { $$ = $1; }
|
| term { $$ = $1; }
|
||||||
|
|
||||||
term : term PLUS subterm { $$ = make_node(PLUS, 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, 0, ""); attach_node($$, $1); attach_node($$, $3);}
|
| term MINUS subterm { $$ = make_node(MINUS, NULL, ""); attach_node($$, $1); attach_node($$, $3);}
|
||||||
| subterm { $$ = $1; }
|
| subterm { $$ = $1; }
|
||||||
|
|
||||||
subterm: subterm TIMES factor { $$ = make_node(TIMES, 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, 0, ""); attach_node($$, $1); attach_node($$, $3);}
|
| subterm DIVIDE factor { $$ = make_node(DIVIDE, NULL, ""); attach_node($$, $1); attach_node($$, $3);}
|
||||||
| factor { $$ = $1; }
|
| factor { $$ = $1; }
|
||||||
|
|
||||||
factor : MINUS factor { $$ = make_node(MINUS, 0, ""); attach_node($$, $2); }
|
factor : MINUS factor { $$ = make_node(MINUS, NULL, ""); attach_node($$, $2); }
|
||||||
| NOT factor { $$ = make_node(NOT, 0, ""); attach_node($$, $2); }
|
| NOT factor { $$ = make_node(NOT, NULL, ""); attach_node($$, $2); }
|
||||||
| atom { $$ = $1; }
|
| atom { $$ = $1; }
|
||||||
|
|
||||||
atom: OPENPAREM expression ENDPAREM { $$ = $2; }
|
atom: OPENPAREM expression ENDPAREM { $$ = $2; }
|
||||||
|
@ -137,7 +137,7 @@ ident: IDENTIFIER { $$ = $1; }
|
||||||
|
|
||||||
identvalue: IDENTIFIER { $$ = $1; }
|
identvalue: IDENTIFIER { $$ = $1; }
|
||||||
| VALUE { $$ = $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 */
|
/* 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;
|
int i;
|
||||||
|
|
||||||
/* allocate space */
|
/* allocate space */
|
||||||
|
@ -212,6 +212,7 @@ void attach_node(struct Node* parent, struct Node* child) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_tree(struct Node* node, int tabs) {
|
void print_tree(struct Node* node, int tabs) {
|
||||||
|
int i;
|
||||||
/* base case */
|
/* base case */
|
||||||
if(!node) {
|
if(!node) {
|
||||||
fprintf(stderr, "NO TREE STRUCTURE\n");
|
fprintf(stderr, "NO TREE STRUCTURE\n");
|
||||||
|
@ -219,13 +220,12 @@ void print_tree(struct Node* node, int tabs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print leading tabs */
|
/* print leading tabs */
|
||||||
for(int i = 0; i < tabs; i++) {
|
for(i = 0; i < tabs; i++) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(node->type) {
|
switch(node->type) {
|
||||||
case IDENTIFIER: printf("IDENTIFIER: %s\n", node->id); break;
|
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 PLUS: printf("PLUS:\n"); break;
|
||||||
case MINUS: printf("MINUS:\n"); break;
|
case MINUS: printf("MINUS:\n"); break;
|
||||||
case DIVIDE: printf("DIVIDE:\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 PRINT: printf("PRINT:\n"); break;
|
||||||
case INPUT: printf("INPUT:\n"); break;
|
case INPUT: printf("INPUT:\n"); break;
|
||||||
case STATEMENT: printf("STATEMENT:\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:
|
default:
|
||||||
printf("Error, %d not a valid node type.\n", node->type);
|
printf("Error, %d not a valid node type.\n", node->type);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -265,7 +272,7 @@ void delete_tree(struct Node* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* creates a new variable and returns it */
|
/* 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 */
|
/* allocate space */
|
||||||
struct Variable* var = malloc(sizeof(struct Variable));
|
struct Variable* var = malloc(sizeof(struct Variable));
|
||||||
|
|
||||||
|
@ -277,12 +284,12 @@ struct Variable* make_variable(char* id, double value) {
|
||||||
return var;
|
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; }
|
if (!var) { fprintf(stderr, "Error: Invalid Variable\n"); return; }
|
||||||
var->value = value;
|
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; }
|
if (!var) { fprintf(stderr, "Error: Invalid Variable\n"); return 0; }
|
||||||
return var->value;
|
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 */
|
/* base case */
|
||||||
if(!node) {
|
if(!node) {
|
||||||
fprintf(stderr, "Error: No tree structure to evaluate\n");
|
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;
|
struct Variable* var = NULL;
|
||||||
|
|
||||||
// Evaluate subexpressions if existent
|
// 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) {
|
if (node->num_children > 0) {
|
||||||
val1 = eval_expression(node->children[0], env);
|
val1 = eval_expression(node->children[0], env);
|
||||||
if (node->num_children > 1) {
|
if (node->num_children > 1) {
|
||||||
val2 = eval_expression(node->children[1], env);
|
val2 = eval_expression(node->children[1], env);
|
||||||
if (node->num_children > 2) {
|
if (node->num_children > 2) {
|
||||||
val3 = eval_expression(node->children[2], env);
|
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) {
|
switch(node->type) {
|
||||||
case PLUS:
|
case PLUS:
|
||||||
check_num_nodes(node, 2, "cannot add more than two expressions.");
|
check_num_nodes(node, 2, "cannot add more than two expressions.");
|
||||||
return val1 + val2;
|
return add(val1, val2);
|
||||||
|
// return val1 + val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case MINUS:
|
case MINUS:
|
||||||
check_num_nodes(node, 2, "cannot subtract more than two expressions.");
|
check_num_nodes(node, 2, "cannot subtract more than two expressions.");
|
||||||
return val1 - val2;
|
return subtract(val1, val2);
|
||||||
|
// return val1 - val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case DIVIDE:
|
case DIVIDE:
|
||||||
check_num_nodes(node, 2, "cannot divide more than two expressions.");
|
check_num_nodes(node, 2, "cannot divide more than two expressions.");
|
||||||
return val1 / val2;
|
return division(val1, val2);
|
||||||
|
// return val1 / val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case TIMES:
|
case TIMES:
|
||||||
check_num_nodes(node, 2, "cannot multiply more than two expressions.");
|
check_num_nodes(node, 2, "cannot multiply more than two expressions.");
|
||||||
return val1 * val2;
|
return multiplication(val1, val2);
|
||||||
|
// return val1 * val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case LESS:
|
case LESS:
|
||||||
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
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"); }
|
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;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case GREATER:
|
case GREATER:
|
||||||
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
||||||
return val1 > val2;
|
return greater(val1, val2);
|
||||||
|
// return val1 > val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case LESSEQ:
|
case LESSEQ:
|
||||||
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
||||||
return val1 <= val2;
|
return less_equal(val1, val2);
|
||||||
|
// return val1 <= val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case GREATEREQ:
|
case GREATEREQ:
|
||||||
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
||||||
return val1 >= val2;
|
return greater_equal(val1, val2);
|
||||||
|
// return val1 >= val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case EQUALS:
|
case EQUALS:
|
||||||
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
||||||
return val1 == val2;
|
return equals(val1, val2);
|
||||||
|
// return val1 == val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case NEQUALS:
|
case NEQUALS:
|
||||||
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
check_num_nodes(node, 2, "cannot compare more than two expressions.");
|
||||||
return val1 != val2;
|
return not_equals(val1, val2);
|
||||||
|
// return val1 != val2;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case AND:
|
case AND:
|
||||||
check_num_nodes(node, 2, "cannot perform logical operators on more than two expressions.");
|
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;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case OR:
|
case OR:
|
||||||
check_num_nodes(node, 2, "cannot perform logical operators on more than two expressions.");
|
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;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case NOT:
|
case NOT:
|
||||||
check_num_nodes(node, 1, "cannot negate more than one expressions.");
|
check_num_nodes(node, 1, "cannot negate more than one expressions.");
|
||||||
return !val1;
|
return not(val1);
|
||||||
|
// return !val1;
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case INPUT:
|
case INPUT: // We're only going to support reading in doubles
|
||||||
|
// Look into deleting possible values...?
|
||||||
scanf("%lf", &temp);
|
scanf("%lf", &temp);
|
||||||
return temp;
|
return make_value(DOUBLE, 0, temp);
|
||||||
break;
|
break;
|
||||||
//----------
|
//----------
|
||||||
case IDENTIFIER:
|
case IDENTIFIER:
|
||||||
|
@ -459,6 +757,7 @@ void eval_statement(struct Node* node, struct Environment* env) {
|
||||||
fprintf(stderr, "Error: No tree structure to evaluate\n");
|
fprintf(stderr, "Error: No tree structure to evaluate\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
struct Value* tempVal;
|
||||||
|
|
||||||
switch(node->type) {
|
switch(node->type) {
|
||||||
case ASSIGN:
|
case ASSIGN:
|
||||||
|
@ -472,23 +771,47 @@ void eval_statement(struct Node* node, struct Environment* env) {
|
||||||
if (node->num_children != 2 && node->num_children != 3) {
|
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");
|
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)) {
|
tempVal = eval_expression(node->children[0], env);
|
||||||
|
if (tempVal->type == LONG) {
|
||||||
|
if (get_long(tempVal)) {
|
||||||
eval_statement(node->children[1], env);
|
eval_statement(node->children[1], env);
|
||||||
} else if (node->num_children == 3) {
|
} else if (node->num_children == 3) {
|
||||||
eval_statement(node->children[2], env);
|
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;
|
break;
|
||||||
//------------
|
//------------
|
||||||
case WHILE:
|
case WHILE:
|
||||||
check_num_nodes(node, 2, "the format of a while statement is: while expression statement(s)");
|
check_num_nodes(node, 2, "the format of a while statement is: while expression statement(s)");
|
||||||
while (eval_expression(node->children[0], env)) {
|
tempVal = eval_expression(node->children[0], env);
|
||||||
|
if (tempVal->type == LONG) {
|
||||||
|
while (get_long(tempVal)) {
|
||||||
eval_statement(node->children[1], env);
|
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;
|
break;
|
||||||
//------------
|
//------------
|
||||||
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.");
|
||||||
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;
|
break;
|
||||||
//------------
|
//------------
|
||||||
case STATEMENT: // Can have a maximum of two children statement nodes
|
case STATEMENT: // Can have a maximum of two children statement nodes
|
||||||
|
|
Reference in a new issue