summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-08-04 21:53:16 +0200
committertomsmeding <tom.smeding@gmail.com>2016-08-04 21:53:16 +0200
commite6bb770a52980ef3d85c2d4b93fb240c026ce7f7 (patch)
tree3fbfbad81222598292a6aaf70c7b7bd1f32272f8 /parser.c
parentf83ea28ae6a04f1121b8328f7bdc5dad94628328 (diff)
Advance parser
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c131
1 files changed, 120 insertions, 11 deletions
diff --git a/parser.c b/parser.c
index e099e98..96b9bf7 100644
--- a/parser.c
+++ b/parser.c
@@ -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_);
}