/* * flex tokenize.l * cc lex.yy.c -lfl */ %{ #include #include #include #include struct token; struct token { int type; union { char *str; int num; } v; struct token *next; }; struct ast; struct ast { int type; union { struct token *token; struct ast *list; } v; struct ast *next; }; enum asttype { AST_TOK = 400, AST_LIST = 401 }; enum yytokentype { NUM = 258, LPAR = 259, RPAR = 260, SYM = 261, STR = 262, EOL = 263 }; struct token *make_token(enum yytokentype, int, char*); int yylval; char *yystr; %} %% "(" { return LPAR; } ")" { return RPAR; } [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; } . { err(1, "invalid symbol: %s\n", yytext); } %% /* * Goal: write LISP read-eval-print Loop and support * @ Function * 0,1 boolean (nand 0 1) -> boolean * (eq 0 0) -> boolean * "str" Strings (streq str1 str2) -> boolean * abc Symboles (symeq s1 s2) -> boolean * 1234 Number/Integer [add,sub,div,mul,mod] -> number * [lt, numeq] -> boolean * [num2bool] -> boolean * * (def ..) ( )) * (if ) */ struct token* make_token(enum yytokentype type, int num, char* str) { struct token *t = (struct token*) calloc(1, sizeof(struct token)); if (t == NULL) err(1, "malloc failed"); t->type = type; if (type == NUM) t->v.num = num; else if (type == SYM || type == STR) t->v.str = strdup(str); return t; } struct ast* make_ast(enum asttype type, struct token *t) { struct ast *a = (struct ast*) calloc(1, sizeof(struct ast)); if (a == NULL) err(1, "malloc failed"); a->type = type; if (type == AST_TOK) a->v.token = t; /* else if (type == AST_LIST) */ /* a->v.list = n; */ return a; } struct token *next; struct ast* parse(struct token *t) { if (t == NULL) err(1, "Unexpected token: "); if (t->type == LPAR) { struct ast *head = make_ast(AST_LIST, NULL); struct ast *a, *p; t = t->next; while (t->type != RPAR) { assert (t != NULL); a = parse(t); if (a == NULL) err(1, "syntax error"); if (head->v.list == NULL) { p = head->v.list = a; } else { p->next = a; } p = a; t = next; /* skip all tokens that are processed */ assert(t != NULL); } fprintf(stderr, "a=%p, t=%p\n", a, t); assert(t->type == RPAR); t = t->next; next = t; return head; } else if (t->type == NUM) { printf("is a number %d\n", t->v.num); next = t->next; return make_ast(AST_TOK, t); } else if (t->type == SYM) { printf("is a sym: %s (%p)\n", t->v.str, t); next = t->next; return make_ast(AST_TOK, t); } else if (t->type == STR) { next = t->next; printf("is a str: %s\n", t->v.str); return make_ast(AST_TOK, t); } return NULL; } void debug_token(struct token *x, indent) { for (int i = 0; i < indent; i++) putc(' ', stderr); fprintf(stderr, "%d: (%p)", x->type, x); if (x->type == NUM) fprintf(stderr, "%d @ %p", x->v.num, x); if (x->type == STR || x->type == SYM) fprintf(stderr, "%s", x->v.str); putc('\n', stderr); } void debug_ast(struct ast *a, indent) { while (a) { for (int i = 0; i < indent; i++) putc(' ', stderr); fprintf(stderr, "AST: %s,a=%p,list=%p,token=%p,next=%p", (a->type == AST_TOK) ? "AST_TOK" : "AST_LIST", a, a->v.list, a->v.token, a->next); putc('\n', stderr); if (a->type == AST_LIST) { fprintf(stderr, "enter %p\n", a->v.list); fprintf(stderr, "==\n"); debug_ast(a->v.list, indent+4); fprintf(stderr, "==\n"); } else if(a->type == AST_TOK) debug_token(a->v.token, indent); a = a->next; } } struct ast * eval(struct ast *a) { if (a->type == AST_TOK) { if (a->v.token->type == NUM) { return make_ast(AST_TOK, a->v.token); } else if (a->v.token->type == SYM) { if (strcmp(a->v.token->v.str, "def") == 0) { printf("define: %s\n", a->next->v.token->v.str); /* x = eval a->next->next */ /* install: var:=x */ } } else if (a->v.token->type == STR) fprintf(stderr, "str\n"); } else if (a->type == AST_LIST) { eval(a->v.list); } else { fprintf(stderr, "%d\n", a->type); assert(0); } return NULL; } void pr(struct ast *a) { switch (a->type) { case AST_TOK: if (a->v.token->type == NUM) printf("%d\n", a->v.token->v.num); } } int main(void) { int tok; struct token *t, *u = NULL, *start = NULL; while(tok = yylex()) { /* read token and create list */ 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); */ eval(parse(start)); //debug_ast(tl, 1); /* start anew: */ start = NULL; } } } /* * Local Variables: * mode: c; * eval: (message "main()") * fill-column: 80 * comment-column: 40 * indent-tabs-mode: nil * tab-width: 2 * c-basic-offset: 2 * End: */