#include #include #include #include #include "memory.h" #include "parser.h" typedef enum Tokentype{ TT_NUM, TT_STR, TT_WORD, TT_SYM } Tokentype; typedef struct Token{ const char *str; int len; } Token; Token nexttoken(const char **sourcep){ const char *source=*sourcep; while(isspace(*source))source++; if(isdigit(*source)||(*source=='-'&&isdigit(source[1]))){ char *endp; strtod(source,&endp); assert(endp!=source); Token tok={source,endp-source}; return tok; } } int precedence(const char *op){ switch(op[0]){ case '!': return op[1]=='\0' ? 12 : op[1]=='='&&op[2]=='\0' ? 5 : -1; case '%': return op[1]=='\0' ? 11 : -1; case '&': return op[1]=='\0' ? 9 : op[1]=='&'&&op[2]=='\0' ? 4 : -1; case '*': return op[1]=='\0' ? 11 : op[1]=='*'&&op[2]=='\0' ? 14 : -1; case '+': return op[1]=='\0' ? 10 : -1; case '-': return op[1]=='\0' ? 10 : -1; case '/': return op[1]=='\0' ? 11 : op[1]=='/'&&op[2]=='\0' ? 11 : -1; case '<': return op[1]=='\0' ? 6 : op[1]=='='&&op[2]=='\0' ? 6 : -1; case '=': return op[1]=='\0' ? 1 : op[1]=='='&&op[2]=='\0' ? 5 : -1; case '>': return op[1]=='\0' ? 6 : op[1]=='='&&op[2]=='\0' ? 6 : -1; case '^': return op[1]=='\0' ? 8 : op[1]=='^'&&op[2]=='\0' ? 3 : -1; case '|': return op[1]=='\0' ? 7 : op[1]=='|'&&op[2]=='\0' ? 2 : -1; case '~': return op[1]=='\0' ? 12 : -1; default: return -1; } } int associativity(const char *op){ switch(op[0]){ case '!': return op[1]=='\0' ? AS_PREFIX : op[1]=='='&&op[2]=='\0' ? AS_NONASSOC : -1; case '%': return op[1]=='\0' ? AS_LEFT : -1; case '&': return op[1]=='\0' ? AS_LEFT : op[1]=='&'&&op[2]=='\0' ? AS_LEFT : -1; case '*': return op[1]=='\0' ? AS_LEFT : op[1]=='*'&&op[2]=='\0' ? AS_RIGHT : -1; case '+': return op[1]=='\0' ? AS_LEFT : -1; case '-': return op[1]=='\0' ? AS_LEFT : -1; case '/': return op[1]=='\0' ? AS_LEFT : op[1]=='/'&&op[2]=='\0' ? AS_LEFT : -1; case '<': return op[1]=='\0' ? AS_NONASSOC : op[1]=='='&&op[2]=='\0' ? AS_NONASSOC : -1; case '=': return op[1]=='\0' ? AS_RIGHT : op[1]=='='&&op[2]=='\0' ? AS_NONASSOC : -1; case '>': return op[1]=='\0' ? AS_NONASSOC : op[1]=='='&&op[2]=='\0' ? AS_NONASSOC : -1; case '^': return op[1]=='\0' ? AS_LEFT : op[1]=='^'&&op[2]=='\0' ? AS_LEFT : -1; case '|': return op[1]=='\0' ? AS_LEFT : op[1]=='|'&&op[2]=='\0' ? AS_LEFT : -1; case '~': return op[1]=='\0' ? AS_PREFIX : -1; default: return -1; } } static bool parsecomment(const char *source,int *reslen){ int cursor=0; if(source[cursor]!='#')return false; if(source[cursor+1]=='#'&&source[cursor+2]=='#'){ cursor+=3; while(source[cursor]&& (source[cursor]!='#'||source[cursor+1]!='#'||source[cursor+2]!='#')){ cursor++; } if(!source[cursor])return false; //unclosed block comment cursor+=2; } else { while(source[cursor]&&source[cursor]!='\n')cursor++; if(source[cursor])cursor++; } *reslen=cursor; return true; } static void parseintermediate(const char *source,int *reslen){ int cursor=0; bool acted; do { acted=false; while(source[cursor]&&isspace(source[cursor])){ cursor++; acted=true; } int partlen; if(parsecomment(source+cursor,&partlen)){ cursor+=partlen; acted=true; } } while(acted); *reslen=cursor; } static AST* parseexpr(const char *source,int *reslen,int minprec){ ; } static AST* parsestmt(const char *source,int *reslen){ return parseexpr(source,reslen,0); } ASTblock* parse(const char *source){ ASTblock *bl=malloc(sizeof(ASTblock)); int sz=32; bl->len=0; bl->exprs=calloc(sz,sizeof(AST*)); if(!bl->exprs)outofmem(); int reslen; int cursor=0; while(true){ if(bl->len==sz){ sz*=2; bl->exprs=realloc(bl->exprs,sz*sizeof(AST*)); if(!bl->exprs)outofmem(); } parseintermediate(source+cursor,&reslen); if(!source[cursor])break; AST *node=parsestmt(source+cursor,&reslen); if(!node){ ast_free((AST*)bl); return NULL; } bl->exprs[bl->len++]=node; cursor+=reslen; } return bl; } void ast_free(AST *ast_){ switch(ast_->type){ case AST_BLOCK:{ ASTblock *ast=(ASTblock*)ast_; for(int i=0;ilen;i++)if(ast->exprs[i])ast_free(ast->exprs[i]); free(ast->exprs); break; } case AST_OP:{ ASTop *ast=(ASTop*)ast_; if(ast->left)ast_free(ast->left); if(ast->right)ast_free(ast->right); break; } case AST_NUM: break; case AST_STR:{ ASTstr *ast=(ASTstr*)ast_; if(ast->str)free(ast->str); break; } case AST_VAR:{ ASTvar *ast=(ASTvar*)ast_; if(ast->name)free(ast->name); break; } case AST_CALL:{ ASTcall *ast=(ASTcall*)ast_; if(ast->func)free(ast->func); for(int i=0;inargs;i++)if(ast->args[i])ast_free(ast->args[i]); free(ast->args); break; } case AST_IF:{ ASTif *ast=(ASTif*)ast_; if(ast->cond)free(ast->cond); if(ast->thenb)free(ast->thenb); if(ast->elseb)free(ast->elseb); break; } case AST_WHILE:{ ASTwhile *ast=(ASTwhile*)ast_; if(ast->cond)free(ast->cond); if(ast->body)free(ast->body); break; } } free(ast_); }