diff --git a/src/lexer.l b/src/lexer.l index f369d48..33026f8 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -41,10 +41,10 @@ DIGIT [0-9] "input" {return INPUT;} "lambda" {return LAMBDA;} ":" {return COLON;} -"true" {yylval.value = make_node(VALUE, make_value(BOOLEAN, 1, 0), ""); return VALUE;} -"false" {yylval.value = make_node(VALUE, make_value(BOOLEAN, 0, 0), ""); return VALUE;} -{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;} +"true" {yylval.value = make_node(VALUE, make_true(), ""); return VALUE;} +"false" {yylval.value = make_node(VALUE, make_false(), ""); return VALUE;} +{DIGIT} {yylval.value = make_node(VALUE, make_long(atoi(yytext)), ""); return VALUE;} +{DIGIT}*"."?{DIGIT}+ {yylval.value = make_node(VALUE, make_double(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]+ {} diff --git a/src/node.h b/src/node.h index f1bdb6e..8c4838b 100644 --- a/src/node.h +++ b/src/node.h @@ -40,6 +40,7 @@ struct Variable { typedef union typeval { long num; double dec; + struct Node* expr; } TypeVal; struct Value { @@ -48,7 +49,7 @@ struct Value { }; // Value functions -struct Value* make_value(int type, long num, double dec); +struct Value* make_value(int type, long num, double dec, struct Node* expr); struct Value* make_long(long num); struct Value* make_double(double dec); struct Value* make_true(); @@ -57,13 +58,21 @@ struct Value* make_false(); void delete_value(struct Value* val); long get_long(struct Value* val); double get_double(struct Value* val); +struct Node* get_expression(struct Value* val); 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); // Variable Functions 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 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 Environment { int num_vars; diff --git a/src/parser.y b/src/parser.y index 2baf386..6b805d7 100644 --- a/src/parser.y +++ b/src/parser.y @@ -55,7 +55,7 @@ struct Node* result; %token COLON /* declare non-terminals */ -%type program statement assignment if-statement if-else-statement while print statements substatements callfunc expression subexpression term subterm factor atom identvalue ident +%type program statement assignment if-statement if-else-statement while print statements substatements callfunc exprlambda expression subexpression term subterm factor atom identvalue ident /* give us more detailed errors */ %error-verbose @@ -71,7 +71,7 @@ statement: assignment { $$ = $1; } | print { $$ = $1; } | statements { $$ = $1; } -assignment: ident ASSIGN expression SEMICOLON { +assignment: ident ASSIGN exprlambda SEMICOLON { $$ = make_node(ASSIGN, NULL, ""); attach_node($$, $1); attach_node($$, $3); @@ -96,7 +96,7 @@ while: WHILE expression DO statement { attach_node($$, $4); } -print: PRINT expression SEMICOLON { +print: PRINT exprlambda SEMICOLON { $$ = make_node(PRINT, NULL, ""); attach_node($$, $2); } @@ -108,7 +108,14 @@ statements: BEGINTOK substatements END { $$ = $2; } 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, NULL, ""); attach_node($$, $1); attach_node($$, $3);} +exprlambda: LAMBDA ident COLON expression { + // Only supports one argument functions for now + $$ = make_node(LAMBDA, NULL, ""); + attach_node($$, $2); + attach_node($$, $4); } + | expression { $$ = $1; } + +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; } @@ -132,22 +139,18 @@ factor : MINUS factor { $$ = make_node(MINUS, NULL, ""); attach_node($$, $2); } | NOT factor { $$ = make_node(NOT, NULL, ""); attach_node($$, $2); } | atom { $$ = $1; } +callfunc: ident OPENPAREM expression ENDPAREM { $$ = make_node(CALLFUNC, NULL, ""); attach_node($$, $1); attach_node($$, $3); } + atom: OPENPAREM expression ENDPAREM { $$ = $2; } + | callfunc { $$ = $1; } | identvalue { $$ = $1; } ident: IDENTIFIER { $$ = $1; } -callfunc: ident OPENPAREM ident ENDPAREM { $$ = make_node(CALLFUNC, NULL, 0); attach_node($$, $1); attach_node($$, $3); } - -identvalue: callfunc { $$ = $1; } - | ident { $$ = $1; } +identvalue: ident { $$ = $1; } | VALUE { $$ = $1; } | INPUT { $$ = make_node(INPUT, NULL , ""); } - | LAMBDA ident COLON expression { - // Only supports one argument functions for now - $$ = make_node(LAMBDA, NULL, ""); - attach_node($$, $2); - attach_node($$, $4); } + @@ -255,6 +258,7 @@ void print_tree(struct Node* node, int tabs) { case PRINT: printf("PRINT:\n"); break; case INPUT: printf("INPUT:\n"); break; case LAMBDA: printf("LAMBDA:\n"); break; + case CALLFUNC: printf("FUNCTIONCALL:\n"); break; case STATEMENT: printf("STATEMENT:\n"); break; case VALUE: if (node->value->type == BOOLEAN) { @@ -361,7 +365,7 @@ void check_num_nodes(struct Node* node, int num_children, char* error) { } } -struct Value* make_value(int type, long num, double dec) { +struct Value* make_value(int type, long num, double dec, struct Node* expr) { /* allocate space */ struct Value* val = malloc(sizeof(struct Value)); @@ -369,8 +373,10 @@ struct Value* make_value(int type, long num, double dec) { val->type = type; if (type == LONG || type == BOOLEAN) { val->value.num = num; - } else { // Assume DOUBLE + } else if (type == DOUBLE){ // Assume DOUBLE val->value.dec = dec; + } else { // Assume lambda expression + val->value.expr = expr; } /* return new variable */ @@ -378,34 +384,38 @@ struct Value* make_value(int type, long num, double dec) { } struct Value* make_long(long num) { - return make_value(LONG, num, 0); + return make_value(LONG, num, 0, NULL); } - struct Value* make_double(double dec) { - return make_value(DOUBLE, 0, dec); + return make_value(DOUBLE, 0, dec, NULL); } - struct Value* make_true() { - return make_value(BOOLEAN, 1, 0); + return make_value(BOOLEAN, 1, 0, NULL); } - struct Value* make_false() { - return make_value(BOOLEAN, 0, 0); + return make_value(BOOLEAN, 0, 0, NULL); } - struct Value* make_boolean(int x) { return (x)? make_true() : make_false(); } +struct Value* make_expression(struct Node* expr) { + return make_value(LAMBDA, 0, 0, expr); +} 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; } +struct Node* get_expression(struct Value* val) { + return val->value.expr; +} + void set_long(struct Value* val, long num) { val->type = LONG; val->value.num = num; @@ -414,6 +424,10 @@ void set_double(struct Value* val, double dec) { val->type = DOUBLE; val->value.dec = dec; } +void set_expression(struct Value* val, struct Node* expr) { + val->type = LAMBDA; + val->value.expr = expr; +} struct Value* add(struct Value* x, struct Value* y) { if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in add.\n"); } @@ -652,6 +666,9 @@ struct Value* eval_expression(struct Node* node, struct Environment* env) { // Needed if we are going to take input from the user double temp; struct Variable* var = NULL; + struct Environment* local_env = NULL; + struct Node* tempNode = NULL; + struct Value* tempVal = NULL; // Evaluate subexpressions if existent and node is not a lambda expression struct Value* val1 = NULL; @@ -669,7 +686,18 @@ struct Value* eval_expression(struct Node* node, struct Environment* env) { } switch(node->type) { - case LAMBDA: printf("\n"); return make_long(0); break; + case LAMBDA: return make_expression(node); break; + case CALLFUNC: + check_num_nodes(node, 2, "cannot have more than two nodes for a function call."); + tempNode = get_expression(get_value(find_variable(env, node->children[0]->id))); + local_env = create_environment(); + add_variable(local_env, + make_variable(tempNode->children[0]->id, // Get the name of the variable needed for the lambda expression + eval_expression(node->children[1], env))); + tempVal = eval_expression(tempNode->children[1], local_env); + delete_environment(local_env); + return tempVal; + break; case PLUS: check_num_nodes(node, 2, "cannot add more than two expressions."); return add(val1, val2); @@ -782,6 +810,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) { @@ -833,8 +862,10 @@ void eval_statement(struct Node* node, struct Environment* env) { } } else if (tempVal->type == LONG) { printf("%li\n", get_long(tempVal)); - } else { + } else if (tempVal ->type == DOUBLE) { printf("%lf\n", get_double(tempVal)); + } else { // Assume lambda expression + printf("\n"); } break; //------------