Archived
1
0
Fork 0

Now you can define a single argument lambda expression and call it using the standard parenthesis notation

This commit is contained in:
Brandon Rozek 2018-09-24 16:43:53 -04:00
parent 82f7e21d3a
commit b0ec7c113c
3 changed files with 70 additions and 30 deletions

View file

@ -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]+ {}

View file

@ -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;

View file

@ -55,7 +55,7 @@ struct Node* result;
%token COLON
/* declare non-terminals */
%type <value> program statement assignment if-statement if-else-statement while print statements substatements callfunc expression subexpression term subterm factor atom identvalue ident
%type <value> 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("<LambdaExpression>\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("<LambdaExpression>\n");
}
break;
//------------