%define parse.error verbose %{ #include "lambda.h" #include "lambda.tab.h" #include "lambda.yy.h" #include "mem.h" #include "print.h" #include "reduce.h" struct decllist *decls = NULL; extern int yylex(); int yydebug=1; void yyerror(const char *str) { fprintf(stderr, "parse error: %s\n", str); } int yywrap() { struct decllist *t; while(decls != NULL){ free(decls->ident); lambda_free(decls->value); t = decls->next; free(decls); decls = t; } return 1; } struct lambda *make_lambda() { return malloc(sizeof (struct lambda)); } struct lambda *make_ident(char *i) { struct lambda *r = make_lambda(); r->which = lambda_ident; r->data.identifier.ident = strdup(i); r->data.identifier.binding = NULL; return r; } void lambda_bind(struct lambda *tob, struct lambda *binding, char *ident) { switch(tob->which){ case lambda_ident: if(strcmp(ident, tob->data.identifier.ident) == 0 && tob->data.identifier.binding == NULL) tob->data.identifier.binding = binding; break; case lambda_abs: lambda_bind(tob->data.abstraction.expr, binding, ident); break; case lambda_app: lambda_bind(tob->data.application.expr1, binding, ident); lambda_bind(tob->data.application.expr2, binding, ident); break; } } struct lambda *make_abstraction(char *i, bool strict, struct lambda *t) { struct lambda *r = make_lambda(); r->which = lambda_abs; r->data.abstraction.ident = strdup(i); r->data.abstraction.strict = strict; r->data.abstraction.expr = t; lambda_bind(t, r, i); return r; } struct lambda *make_application(struct lambda *t1, struct lambda *t2) { struct lambda *r = make_lambda(); r->which = lambda_app; r->data.application.expr1 = t1; r->data.application.expr2 = t2; return r; } struct lambda *make_numeral(unsigned int i) { struct lambda *body = make_ident("x"); while(i-- > 0) body = make_application(make_ident("f"), body); return make_abstraction("f", false, make_abstraction("x", false, body)); } struct lambda *make_bool(bool b) { return make_abstraction("a", false, make_abstraction("b", false, make_ident(b ? "a" : "b"))); } void decls_prepend(char *ident, struct lambda *value) { struct decllist *head = malloc(sizeof (struct decllist)); head->next = decls; head->ident = strdup(ident); head->value = value; decls = head; } struct lambda *decls_lookup(char *ident) { for(struct decllist *c = decls; c != NULL; c = c->next) if(strcmp(c->ident, ident) == 0) return copy(c->value); return make_ident(ident); } int main() { int r = yyparse(); yylex_destroy(); return r; } %} %token LAMBDA DOT OBRACE CBRACE IDENT FUNC SEMICOLON ASSIGN LITERAL BANG %% program : | lambda SEMICOLON program lambda : FUNC func { decls_prepend($1->data.identifier.ident, $2); printf("%s = ", $1->data.identifier.ident); lambda_print($2, NULL); lambda_free($1); } | term { struct lambda *t = $1; printf(" "); for(unsigned int i = 0; i<999; i++) if(!lambda_reduce(&t, &t, false)) break; lambda_print(t, NULL); lambda_free(t); } func : ASSIGN term { $$ = $2; } | BANG IDENT func { $$ = make_abstraction($2->data.identifier.ident, true, $3); lambda_free($2); } | IDENT func { $$ = make_abstraction($1->data.identifier.ident, false, $2); lambda_free($1); } term : term appterm { $$ = make_application($1, $2); } | appterm { $$ = $1; } appterm : LITERAL { $$ = $1; } | FUNC { $$ = decls_lookup($1->data.identifier.ident); lambda_free($1); } | IDENT { $$ = $1; } | LAMBDA abstraction { $$ = $2; } | OBRACE term CBRACE { $$ = $2; } abstraction : BANG IDENT abstraction { $$ = make_abstraction($2->data.identifier.ident, true, $3); lambda_free($2); } | IDENT abstraction { $$ = make_abstraction($1->data.identifier.ident, false, $2); lambda_free($1); } | DOT term { $$ = $2; }