diff options
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 131 |
1 files changed, 120 insertions, 11 deletions
@@ -7,6 +7,115 @@ #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; @@ -21,7 +130,7 @@ ASTblock* parse(const char *source){ bl->exprs=realloc(bl->exprs,sz*sizeof(AST*)); if(!bl->exprs)outofmem(); } - while(source[cursor]&isspace(source[cursor]))cursor++; + parseintermediate(source+cursor,&reslen); if(!source[cursor])break; AST *node=parsestmt(source+cursor,&reslen); if(!node){ @@ -34,15 +143,15 @@ ASTblock* parse(const char *source){ return bl; } -void ast_free(AST *ast){ - switch(ast->type){ - case AST_BLOCK:{ ASTblock *ast=ast; +void ast_free(AST *ast_){ + switch(ast_->type){ + case AST_BLOCK:{ ASTblock *ast=(ASTblock*)ast_; for(int i=0;i<ast->len;i++)if(ast->exprs[i])ast_free(ast->exprs[i]); free(ast->exprs); break; } - case AST_OP:{ ASTop *ast=ast; + case AST_OP:{ ASTop *ast=(ASTop*)ast_; if(ast->left)ast_free(ast->left); if(ast->right)ast_free(ast->right); break; @@ -51,35 +160,35 @@ void ast_free(AST *ast){ case AST_NUM: break; - case AST_STR:{ ASTstr *ast=ast; + case AST_STR:{ ASTstr *ast=(ASTstr*)ast_; if(ast->str)free(ast->str); break; } - case AST_VAR:{ ASTvar *ast=ast; + case AST_VAR:{ ASTvar *ast=(ASTvar*)ast_; if(ast->name)free(ast->name); break; } - case AST_CALL:{ ASTcall *ast=ast; + case AST_CALL:{ ASTcall *ast=(ASTcall*)ast_; if(ast->func)free(ast->func); for(int i=0;i<ast->nargs;i++)if(ast->args[i])ast_free(ast->args[i]); free(ast->args); break; } - case AST_IF:{ ASTif *ast=ast; + 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=ast; + case AST_WHILE:{ ASTwhile *ast=(ASTwhile*)ast_; if(ast->cond)free(ast->cond); if(ast->body)free(ast->body); break; } } - free(ast); + free(ast_); } |