+%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 lambda *result;
+struct decllist *decls = NULL;
extern int yylex();
int yydebug=1;
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 *r = make_lambda();
r->which = lambda_ident;
- r->data.identifier = strdup(i);
+ r->data.identifier.ident = strdup(i);
+ r->data.identifier.binding = NULL;
return r;
}
-struct lambda *make_abstraction(char *i, struct lambda *t)
+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;
}
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 I K S T F
+%token LAMBDA DOT OBRACE CBRACE IDENT FUNC SEMICOLON ASSIGN LITERAL BANG
%%
+program
+ :
+ | lambda SEMICOLON program
lambda
- : term
- { result = $$; }
-term
- : term appterm
+ : FUNC func
{
- $$ = make_application($1, $2);
+ 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
- : IDENT
+ : LITERAL
+ { $$ = $1; }
+ | FUNC
{
- $$ = make_ident($1->data.identifier);
+ $$ = decls_lookup($1->data.identifier.ident);
lambda_free($1);
}
- | LAMBDA IDENT DOT term
+ | IDENT
+ { $$ = $1; }
+ | LAMBDA abstraction
+ { $$ = $2; }
+ | OBRACE term CBRACE
+ { $$ = $2; }
+abstraction
+ : BANG IDENT abstraction
{
- $$ = make_abstraction($2->data.identifier, $4);
+ $$ = make_abstraction($2->data.identifier.ident, true, $3);
lambda_free($2);
}
- | OBRACE term CBRACE
- { $$ = $2; }
- | I
- { $$ = make_abstraction("x", make_ident("x")); }
- | K
- { $$ = make_abstraction("x", make_abstraction("y", make_ident("x"))); }
- | S
- { $$ = make_abstraction("x", make_abstraction("y", make_abstraction("z",
- make_application(make_application(make_ident("x"), make_ident("y")),
- make_application(make_ident("y"), make_ident("z"))))));
+ | IDENT abstraction
+ {
+ $$ = make_abstraction($1->data.identifier.ident, false, $2);
+ lambda_free($1);
}
- | T
- { $$ = make_abstraction("x", make_abstraction("y", make_ident("x"))); }
- | F
- { $$ = make_abstraction("x", make_abstraction("y", make_ident("y"))); }
+ | DOT term
+ { $$ = $2; }