From 1d274cdb2fa2cfe33397898358b5e77fe818a2fc Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Fri, 12 Aug 2016 21:14:11 +0200 Subject: Functions --- code.txt | 38 +++++------ parser.c | 223 +++++++++++++++++++++++++++++++++++++++++++++------------------ parser.h | 54 +++++++++------- 3 files changed, 210 insertions(+), 105 deletions(-) diff --git a/code.txt b/code.txt index ce95b45..4a9abcf 100644 --- a/code.txt +++ b/code.txt @@ -1,21 +1,23 @@ -a = 1; -b = !2; -c = 1 + (- a - 3 + b > -1); -b += 1; -b = 3*(b//3-1); -x = 1 + 1 + 1 + 1; +def main(){ + a = 1; + b = !2; + c = 1 + (- a - 3 + b > -1); + b += 1; + b = 3*(b//3-1); + x = 1 + 1 + 1 + 1; -y = 1 > (1 > 1) == 1; -kaas(1,2,"goeiemorgen\x99",sqrt(3**2+4**2)); -1 + 1 + 1; -if (2 > 1) 1 - 1 - 1; -1 / 1 / 1; -1 ** 1 ** 1; + y = 1 > (1 > 1) == 1; + kaas(1,2,"goeiemorgen\x99",sqrt(3**2+4**2)); + 1 + 1 + 1; + if (2 > 1) 1 - 1 - 1; + 1 / 1 / 1; + 1 ** 1 ** 1; -if kaas - doe(dingen); -else if andere(kaas) { - doe(andere,dingen); -} else { - print("rip"); + if kaas + doe(dingen); + else if andere(kaas) { + doe(andere,dingen); + } else { + print("rip"); + } } diff --git a/parser.c b/parser.c index fa39168..6f2ce2d 100644 --- a/parser.c +++ b/parser.c @@ -42,6 +42,7 @@ static bool semicolon_needed_after(const AST *after){ case AST_BLOCK: case AST_IF: case AST_WHILE: + case AST_FUNC: DBGF("false\n"); return false; @@ -476,25 +477,25 @@ static AST* parseexpr_(const char *source,int *reslen,int minprec,int maxprec){ Token tok=nexttoken(&source,true); DBG(printtoken(stderr,tok,"parseEXPR")); if(tok.type==TT_ENDSTMT){ - DBGF(" (token undo)\n"); + DBGF(" (token undo :%d)\n",__LINE__); source=beforeop; break; } if(tok.type==TT_SYM&&tok.len==1&&(tok.str[0]==')'||tok.str[0]==',')){ - DBGF(" (token undo)\n"); + DBGF(" (token undo :%d)\n",__LINE__); source=beforeop; break; } if(tok.type!=TT_OP){ /*ast_free(tree); return NULL;*/ - DBGF(" (token undo)\n"); + DBGF(" (token undo :%d)\n",__LINE__); source=beforeop; break; } int prec=precedence_len(tok.str,tok.len); if(prec %p)\x1B[0m\n",depth,r); return r; } -static AST* parsestmt(const char *source,int *reslen){ - return parseexpr(source,reslen,0,INT_MAX); +static AST* parsefunction(const char *source,int *reslen){ + const char *origsource=source; + + Token tok=nexttoken(&source,false); + if(tok.type!=TT_WORD||tok.len!=3||memcmp(tok.str,"def",3)!=0){ + return NULL; + } + DBG(printtoken(stderr,tok,"func def ")); + tok=nexttoken(&source,false); + if(tok.type!=TT_WORD)return NULL; + DBG(printtoken(stderr,tok,"func name")); + + AST *func=malloc(sizeof(AST)); + if(!func)outofmem(); + func->type=AST_FUNC; + func->f.name=malloc(tok.len+1); + if(!func->f.name)outofmem(); + memcpy(func->f.name,tok.str,tok.len); + func->f.name[tok.len]='\0'; + func->f.nargs=0; + int argssz=2; + func->f.args=malloc(argssz*sizeof(char*)); + if(!func->f.args)outofmem(); + func->f.body=NULL; + + tok=nexttoken(&source,false); + if(tok.type!=TT_SYM||tok.len!=1||tok.str[0]!='('){ + ast_free(func); + return NULL; + } + DBG(printtoken(stderr,tok,"func(open")); + while(true){ + tok=nexttoken(&source,false); + if(tok.type==TT_SYM&&tok.len==1&&tok.str[0]==')'){ + DBG(printtoken(stderr,tok,"func)clse")); + break; + } + if(tok.type!=TT_WORD){ + ast_free(func); + return NULL; + } + DBG(printtoken(stderr,tok,"func arg ")); + + if(func->f.nargs==argssz){ + argssz*=2; + func->f.args=realloc(func->f.args,argssz*sizeof(char*)); + if(!func->f.args)outofmem(); + } + + char *arg=malloc(tok.len+1); + if(!arg)outofmem(); + memcpy(arg,tok.str,tok.len); + arg[tok.len]='\0'; + func->f.args[func->f.nargs++]=arg; + + tok=nexttoken(&source,false); + DBG(printtoken(stderr,tok,"func sep ")); + if(tok.type!=TT_SYM||tok.len!=1||(tok.str[0]!=','&&tok.str[0]!=')')){ + ast_free(func); + return NULL; + } + if(tok.str[0]==')')break; + } + + int len; + func->f.body=parseexpr(source,&len,0,INT_MAX); + if(!func->f.body){ + ast_free(func); + return NULL; + } + source+=len; + + *reslen=source-origsource; + return func; +} + +static AST* parseprogram(const char *source,int *reslen){ + const char *origsource=source; + AST *prog=malloc(sizeof(AST)); + if(!prog)outofmem(); + prog->type=AST_PROGRAM; + prog->p.nfuncs=0; + int sz=2; + prog->p.funcs=malloc(sz*sizeof(AST*)); + if(!prog->p.funcs)outofmem(); + while(true){ + const char *src=source; + Token tok=nexttoken(&src,false); + if(tok.type==TT_EOF)break; + int len; + AST *func=parsefunction(source,&len); + if(!func){ + ast_free(prog); + return NULL; + } + prog->p.funcs[prog->p.nfuncs++]=func; + source+=len; + } + *reslen=source-origsource; + return prog; } static char* reportparseerror(const char *source){ @@ -583,45 +682,18 @@ static char* reportparseerror(const char *source){ } AST* parse(const char *source,char **errmsg){ - AST *bl=malloc(sizeof(AST)); - if(!bl)outofmem(); - bl->type=AST_BLOCK; - int sz=32; - bl->b.len=0; - bl->b.exprs=calloc(sz,sizeof(AST*)); - if(!bl->b.exprs)outofmem(); + *errmsg=NULL; int reslen; - int cursor=0; - while(true){ - if(bl->b.len==sz){ - sz*=2; - bl->b.exprs=realloc(bl->b.exprs,sz*sizeof(AST*)); - if(!bl->b.exprs)outofmem(); - } - AST *node=parsestmt(source+cursor,&reslen); - if(!node){ - ast_free(bl); - *errmsg=reportparseerror(source); - return NULL; - } - bl->b.exprs[bl->b.len++]=node; - cursor+=reslen; - if(semicolon_needed_after(node)){ - const char *src=source+cursor; - Token tok=nexttoken(&src,false); - DBG(printtoken(stderr,tok,"parse ")); - if(tok.type!=TT_ENDSTMT){ - ast_free(bl); - *errmsg=reportparseerror(source); - return NULL; - } - cursor=src-source; - } - const char *src=source+cursor; - Token tok=nexttoken(&src,false); - if(tok.type==TT_EOF)break; + AST *pr=parseprogram(source,&reslen); + source+=reslen; + Token next=nexttoken(&source,false); + DBG(printtoken(stderr,next,"afterparse")); + if(next.type!=TT_EOF||!pr){ + *errmsg=reportparseerror(source); + if(pr)ast_free(pr); + return NULL; } - return bl; + return pr; } static const char* charblock(char c,int n){ @@ -719,6 +791,26 @@ static void ast_debug_(FILE *stream,const AST *ast,int indent){ assert(NOT_IMPLEMENTED); break; + case AST_FUNC: + fprintf(stream,"def %s(",ast->f.name); + for(int j=0;jf.nargs;j++){ + if(j!=0)fputc(',',stream); + fprintf(stream,"%s",ast->f.args[j]); + } + fprintf(stream,") "); + ast_debug_(stream,ast->f.body,indent); + break; + + case AST_PROGRAM: + for(int i=0;ip.nfuncs;i++){ + if(i!=0){ + fputc('\n',stream); + INDENT + } + ast_debug_(stream,ast->p.funcs[i],indent); + } + break; + default: fprintf(stream,"AST_(??\?)"); break; @@ -732,50 +824,55 @@ void ast_debug(FILE *stream,const AST *ast){ void ast_free(AST *ast){ switch(ast->type){ - case AST_BLOCK:{ + case AST_BLOCK: for(int i=0;ib.len;i++)if(ast->b.exprs[i])ast_free(ast->b.exprs[i]); free(ast->b.exprs); break; - } - case AST_OP:{ + case AST_OP: if(ast->o.left)ast_free(ast->o.left); if(ast->o.right)ast_free(ast->o.right); break; - } case AST_NUM: break; - case AST_STR:{ + case AST_STR: if(ast->s.str)free(ast->s.str); break; - } - case AST_VAR:{ + case AST_VAR: if(ast->v.name)free(ast->v.name); break; - } - case AST_CALL:{ + case AST_CALL: if(ast->c.func)free(ast->c.func); for(int i=0;ic.nargs;i++)if(ast->c.args[i])ast_free(ast->c.args[i]); free(ast->c.args); break; - } - case AST_IF:{ - if(ast->i.cond)free(ast->i.cond); - if(ast->i.thenb)free(ast->i.thenb); - if(ast->i.elseb)free(ast->i.elseb); + case AST_IF: + if(ast->i.cond)ast_free(ast->i.cond); + if(ast->i.thenb)ast_free(ast->i.thenb); + if(ast->i.elseb)ast_free(ast->i.elseb); break; - } - case AST_WHILE:{ - if(ast->w.cond)free(ast->w.cond); - if(ast->w.body)free(ast->w.body); + case AST_WHILE: + if(ast->w.cond)ast_free(ast->w.cond); + if(ast->w.body)ast_free(ast->w.body); + break; + + case AST_FUNC: + if(ast->f.name)free(ast->f.name); + for(int i=0;if.nargs;i++)if(ast->f.args[i])free(ast->f.args[i]); + free(ast->f.args); + if(ast->f.body)ast_free(ast->f.body); + break; + + case AST_PROGRAM: + for(int i=0;ip.nfuncs;i++)if(ast->p.funcs[i])ast_free(ast->p.funcs[i]); + free(ast->p.funcs); break; - } } free(ast); } diff --git a/parser.h b/parser.h index dd378ae..caafe25 100644 --- a/parser.h +++ b/parser.h @@ -13,55 +13,59 @@ typedef enum ASTtype{ AST_CALL, AST_IF, AST_WHILE, + AST_FUNC, + AST_PROGRAM, } ASTtype; typedef struct AST AST; -typedef struct ASTblock ASTblock; -typedef struct ASTop ASTop; -typedef struct ASTnum ASTnum; -typedef struct ASTstr ASTstr; -typedef struct ASTvar ASTvar; -typedef struct ASTcall ASTcall; -typedef struct ASTif ASTif; -typedef struct ASTwhile ASTwhile; -struct ASTblock{ +typedef struct ASTblock{ int len; AST **exprs; -}; -struct ASTop{ +} ASTblock; +typedef struct ASTop{ const char *op; // Constant string, does not need to be freed AST *left,*right; -}; -struct ASTnum{ +} ASTop; +typedef struct ASTnum{ bool isint; union { int64_t i; double d; }; -}; -struct ASTstr{ +} ASTnum; +typedef struct ASTstr{ int len; // Excludes terminating null char char *str; // May contain null chars before terminating null char -}; -struct ASTvar{ +} ASTstr; +typedef struct ASTvar{ char *name; -}; -struct ASTcall{ +} ASTvar; +typedef struct ASTcall{ char *func; int nargs; AST **args; -}; -struct ASTif{ +} ASTcall; +typedef struct ASTif{ AST *cond; AST *thenb,*elseb; -}; -struct ASTwhile{ +} ASTif; +typedef struct ASTwhile{ AST *cond; AST *body; -}; +} ASTwhile; +typedef struct ASTfunc{ + char *name; + int nargs; + char **args; + AST *body; +} ASTfunc; +typedef struct ASTprogram{ + int nfuncs; + AST **funcs; +} ASTprogram; typedef struct AST{ ASTtype type; @@ -74,6 +78,8 @@ typedef struct AST{ ASTcall c; ASTif i; ASTwhile w; + ASTfunc f; + ASTprogram p; }; } AST; -- cgit v1.2.3