From 7f362af8416934c184e1a49f687d6c37becd4877 Mon Sep 17 00:00:00 2001 From: Christian Barthel Date: Sat, 29 Jun 2019 13:20:05 +0200 Subject: [PATCH] add NAND, add boolean type, read form - this commit adds the boolean type with the NAND operation (which is complete and other operations can be built by using NAND) - read from now reads until an entire form has been entered. line breaks, whitespace and tabs are allowed. --- tokenize.l | 110 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 32 deletions(-) diff --git a/tokenize.l b/tokenize.l index fb238ee..0e23c61 100644 --- a/tokenize.l +++ b/tokenize.l @@ -48,7 +48,7 @@ enum yytokentype { SYM = 261, STR = 262, EOL = 263, - QUOTE = 264 + BOOL = 264 }; struct token* make_token(enum yytokentype, int, char*); @@ -60,8 +60,9 @@ char *yystr; %% "(" { return LPAR; } ")" { return RPAR; } +t { yylval = 1; return BOOL;} +nil { yylval = 0; return BOOL; } [0-9]+ { yylval = atoi(yytext); return NUM; } -\n { return EOL; } [ \t\n] { /* ignore white space */ } \".*\" { return STR; } [a-zA-Z][a-zA-Z0-9]* { return SYM; } @@ -70,14 +71,13 @@ char *yystr; /* * Goal: write LISP read-eval-print Loop and support - * @ Function - * 0,1 boolean (nand 0 1) -> boolean - * (eq 0 0) -> boolean + * @ Functions + * t,nil boolean (nand 0 1) -> boolean * "str" Strings (streq str1 str2) -> boolean - * abc Symboles (symeq s1 s2) -> boolean - * 1234 Number/Integer [add,sub,div,mul,mod] -> num - * [lt, numeq] -> boolean - * [num2bool] -> boolean + * abc Symboles (symeq s1 s2) -> boolean + * 1234 Number/Integer [add,inv] -> num + * [lt] -> boolean + * [num-to-bool] -> boolean * * (def ..) ( )) @@ -123,7 +123,7 @@ make_token(enum yytokentype type, int num, char* str) if (t == NULL) err(1, "malloc failed"); t->type = type; - if (type == NUM) + if (type == NUM || type == BOOL) t->v.num = num; else if (type == SYM || type == STR) t->v.str = strdup(str); @@ -160,6 +160,7 @@ make_env(char *name, struct ast *a) int token_is_num(struct token *t) {return t->type == NUM;} int token_is_sym(struct token *t) {return t->type == SYM;} int token_is_str(struct token *t) {return t->type == STR;} +int token_is_bool(struct token *t) {return t->type == BOOL;} /* upon parsing a list of tokens like: * "(" -> "def" -> "(" -> "b" -> ")" -> "c" -> ")" @@ -199,6 +200,9 @@ parse(struct token *t) } else if (t->type == NUM) { next = t->next; return make_ast(AST_TOK, t); + } else if (t->type == BOOL) { + next = t->next; + return make_ast(AST_TOK, t); } else if (t->type == SYM) { next = t->next; return make_ast(AST_TOK, t); @@ -237,6 +241,8 @@ eval_def(struct ast *a, struct env *e) a = a->next; /* skrip `def` */ assert((a->next->type == AST_TOK && a->next->v.token->type== STR) || + (a->next->type == AST_TOK && + a->next->v.token->type == BOOL) || (a->next->type == AST_TOK && a->next->v.token->type == NUM) || (a->next->type == AST_LIST) || @@ -249,7 +255,33 @@ eval_def(struct ast *a, struct env *e) return NULL; } -/* (add */ +/* (nand ) -> BOOL */ +struct ast * +eval_nand(struct ast *a, struct env *e) +{ + assert (a != NULL && + a->next != NULL && + a->next->next != NULL && + a->next->next->next == NULL); + + struct ast *op1 = eval(a->next, e); + struct ast *op2 = eval(a->next->next, e); + + assert (op1 != NULL && + op1->type == AST_TOK && + op1->v.token->type == BOOL && + op2 != NULL && + op2->type == AST_TOK && + op2->v.token->type == BOOL ); + return make_ast(AST_TOK, + make_token(BOOL, + !( + op1->v.token->v.num & + op2->v.token->v.num) , + NULL)); +} + +/* (add ) -> NUM */ struct ast * eval_add(struct ast *a, struct env *e) { @@ -274,16 +306,18 @@ eval_add(struct ast *a, struct env *e) NULL)); } -/* inv */ +/* (inv ) -> NUM */ struct ast * eval_inv(struct ast *a, struct env *e) { assert(a != NULL && - a->next != NULL); + a->next != NULL && + a->next->next == NULL); struct ast *op = eval(a->next, e); assert(op != NULL && op->type == AST_TOK && - op->v.token->type == NUM); + op->v.token->type == NUM && + op->next == NULL); return make_ast(AST_TOK, make_token(NUM, 0 - @@ -302,6 +336,8 @@ eval_sym(struct ast *a, struct env *e) return eval_inv(a, e); } else if (strcmp(a->v.token->v.str, "add") == 0) { return eval_add(a, e); + } else if (strcmp(a->v.token->v.str, "nand") == 0) { + return eval_nand(a, e); } else if (strcmp(a->v.token->v.str, "q") == 0) { //return make_ast(AST_QUOTE, a->next); return a->next; @@ -330,6 +366,8 @@ eval(struct ast *a, struct env *e) return eval_sym(a, e); else if (token_is_str(a->v.token)) return make_ast(AST_TOK, a->v.token); + else if (token_is_bool(a->v.token)) + return make_ast(AST_TOK, a->v.token); case AST_LIST: return eval(a->v.list, e); default: @@ -354,39 +392,47 @@ pr(struct ast *a) printf("%s\n", a->v.token->v.str); else if (a->v.token->type == SYM) printf("%s\n", a->v.token->v.str); + else if (a->v.token->type == BOOL) { + if (a->v.token->v.num) + printf("t\n"); + else + printf("nil\n"); + } } } -int main(void) +struct token* +read_form() { - int tok; + int tok, open = 0; struct token *t, *u = NULL, *start = NULL; - struct env default_env = { 0 }, *env; - env = &default_env; - env->name = ""; while((tok = yylex())) { - /* read token and create list */ + if (tok == LPAR) open++; + else if (tok == RPAR) open--; + t = make_token(tok, yylval, yytext); if (start == NULL) start = t; if (u == NULL) u = t; else u->next = t; u = t; - /* if EOL is reached, parse and evaluate form: */ - if (t->type == EOL) { - struct token *x = start; - // while (x != NULL) {debug_token(x, 0); x = x->next;} - - /* struct ast *tl = parse(start); */ - /* eval(tl); */ - pr(eval(parse(start), env)); - //debug_ast(tl, 1); - - /* start anew: */ - start = NULL; + if (!open) { + return start; } } + exit(0); +} + +int main(void) +{ + struct env default_env = { 0 }, *env; + env = &default_env; + env->name = "__dummy"; + + while (1) + pr(eval(parse(read_form()), env)); + return 0; }