diff options
| -rw-r--r-- | LANGUAGE.txt | 5 | ||||
| -rw-r--r-- | code.txt | 2 | ||||
| -rw-r--r-- | opfuncs.c | 34 | ||||
| -rw-r--r-- | parser.c | 15 | 
4 files changed, 31 insertions, 25 deletions
| diff --git a/LANGUAGE.txt b/LANGUAGE.txt index 3259182..48dcb95 100644 --- a/LANGUAGE.txt +++ b/LANGUAGE.txt @@ -16,9 +16,8 @@ The usual infix expression rules apply, with the following precedence table:      &               9           Left      + -            10           Left   * / // %          11           Left -  (-) ! ~          12          Prefix (unary) -    (!)            13          Suffix (unary) -    **             14           Right + (-) (!) (~)       12          Prefix (unary) +    **             13           Right  break and continue get parsed to calls to the __break() and __continue() @@ -1,5 +1,5 @@  a = 1; -b = 2; +b = !2;  c = 1 + (- a - 3 + b > -1);  b += 1;  b = 3*(b//3-1); @@ -5,11 +5,11 @@  int precedence(const char *op){  	switch(op[0]){ -		case '!': return op[1]=='='&&!op[2]? 5:!op[1]?12:-1; +		case '!': return op[1]=='='&&!op[2]? 5:-1;  		case '%': return op[1]=='='&&!op[2]? 1:!op[1]?11:-1;  		case '&': return op[1]=='='&&!op[2]? 1:op[1]=='&'&&!op[2]? 4:!op[1]? 9:-1; -		case '(': return op[1]=='-'&&op[2]==')'&&!op[3]?12:op[1]=='!'&&op[2]==')'&&!op[3]?13:-1; -		case '*': return op[1]=='*'&&op[2]=='='&&!op[3]? 1:op[1]=='='&&!op[2]? 1:op[1]=='*'&&!op[2]?14:!op[1]?11:-1; +		case '(': return op[1]=='-'&&op[2]==')'&&!op[3]?12:op[1]=='!'&&op[2]==')'&&!op[3]?12:op[1]=='~'&&op[2]==')'&&!op[3]?12:-1; +		case '*': return op[1]=='*'&&op[2]=='='&&!op[3]? 1:op[1]=='='&&!op[2]? 1:op[1]=='*'&&!op[2]?13:!op[1]?11:-1;  		case '+': return op[1]=='='&&!op[2]? 1:!op[1]?10:-1;  		case '-': return op[1]=='='&&!op[2]? 1:!op[1]?10:-1;  		case '/': return op[1]=='/'&&op[2]=='='&&!op[3]? 1:op[1]=='='&&!op[2]? 1:op[1]=='/'&&!op[2]?11:!op[1]?11:-1; @@ -18,7 +18,6 @@ int precedence(const char *op){  		case '>': return op[1]=='='&&!op[2]? 6:!op[1]? 6:-1;  		case '^': return op[1]=='='&&!op[2]? 1:op[1]=='^'&&!op[2]? 3:!op[1]? 8:-1;  		case '|': return op[1]=='='&&!op[2]? 1:op[1]=='|'&&!op[2]? 2:!op[1]? 7:-1; -		case '~': return !op[1]?12:-1;  		default: return -1;  	}  } @@ -26,11 +25,11 @@ int precedence(const char *op){  int precedence_len(const char *op,const int len){  	if(len<=0)return -1;  	switch(op[0]){ -		case '!': return len==2&&op[1]=='='? 5:len==1?12:-1; +		case '!': return len==2&&op[1]=='='? 5:-1;  		case '%': return len==2&&op[1]=='='? 1:len==1?11:-1;  		case '&': return len==2&&op[1]=='='? 1:len==2&&op[1]=='&'? 4:len==1? 9:-1; -		case '(': return len==3&&op[1]=='-'&&op[2]==')'?12:len==3&&op[1]=='!'&&op[2]==')'?13:-1; -		case '*': return len==3&&op[1]=='*'&&op[2]=='='? 1:len==2&&op[1]=='='? 1:len==2&&op[1]=='*'?14:len==1?11:-1; +		case '(': return len==3&&op[1]=='-'&&op[2]==')'?12:len==3&&op[1]=='!'&&op[2]==')'?12:len==3&&op[1]=='~'&&op[2]==')'?12:-1; +		case '*': return len==3&&op[1]=='*'&&op[2]=='='? 1:len==2&&op[1]=='='? 1:len==2&&op[1]=='*'?13:len==1?11:-1;  		case '+': return len==2&&op[1]=='='? 1:len==1?10:-1;  		case '-': return len==2&&op[1]=='='? 1:len==1?10:-1;  		case '/': return len==3&&op[1]=='/'&&op[2]=='='? 1:len==2&&op[1]=='='? 1:len==2&&op[1]=='/'?11:len==1?11:-1; @@ -39,17 +38,16 @@ int precedence_len(const char *op,const int len){  		case '>': return len==2&&op[1]=='='? 6:len==1? 6:-1;  		case '^': return len==2&&op[1]=='='? 1:len==2&&op[1]=='^'? 3:len==1? 8:-1;  		case '|': return len==2&&op[1]=='='? 1:len==2&&op[1]=='|'? 2:len==1? 7:-1; -		case '~': return len==1?12:-1;  		default: return -1;  	}  }  int associativity(const char *op){  	switch(op[0]){ -		case '!': return op[1]=='='&&!op[2]?AS_NONASSOC:!op[1]?AS_PREFIX  :-1; +		case '!': return op[1]=='='&&!op[2]?AS_NONASSOC:-1;  		case '%': return op[1]=='='&&!op[2]?AS_RIGHT   :!op[1]?AS_LEFT    :-1;  		case '&': return op[1]=='='&&!op[2]?AS_RIGHT   :op[1]=='&'&&!op[2]?AS_LEFT    :!op[1]?AS_LEFT    :-1; -		case '(': return op[1]=='-'&&op[2]==')'&&!op[3]?AS_PREFIX  :op[1]=='!'&&op[2]==')'&&!op[3]?AS_SUFFIX  :-1; +		case '(': return op[1]=='-'&&op[2]==')'&&!op[3]?AS_PREFIX  :op[1]=='!'&&op[2]==')'&&!op[3]?AS_PREFIX  :op[1]=='~'&&op[2]==')'&&!op[3]?AS_PREFIX  :-1;  		case '*': return op[1]=='*'&&op[2]=='='&&!op[3]?AS_RIGHT   :op[1]=='='&&!op[2]?AS_RIGHT   :op[1]=='*'&&!op[2]?AS_RIGHT   :!op[1]?AS_LEFT    :-1;  		case '+': return op[1]=='='&&!op[2]?AS_RIGHT   :!op[1]?AS_LEFT    :-1;  		case '-': return op[1]=='='&&!op[2]?AS_RIGHT   :!op[1]?AS_LEFT    :-1; @@ -59,7 +57,6 @@ int associativity(const char *op){  		case '>': return op[1]=='='&&!op[2]?AS_NONASSOC:!op[1]?AS_NONASSOC:-1;  		case '^': return op[1]=='='&&!op[2]?AS_RIGHT   :op[1]=='^'&&!op[2]?AS_LEFT    :!op[1]?AS_LEFT    :-1;  		case '|': return op[1]=='='&&!op[2]?AS_RIGHT   :op[1]=='|'&&!op[2]?AS_LEFT    :!op[1]?AS_LEFT    :-1; -		case '~': return !op[1]?AS_PREFIX  :-1;  		default: return -1;  	}  } @@ -67,10 +64,10 @@ int associativity(const char *op){  int associativity_len(const char *op,const int len){  	if(len<=0)return -1;  	switch(op[0]){ -		case '!': return len==2&&op[1]=='='?AS_NONASSOC:len==1?AS_PREFIX  :-1; +		case '!': return len==2&&op[1]=='='?AS_NONASSOC:-1;  		case '%': return len==2&&op[1]=='='?AS_RIGHT   :len==1?AS_LEFT    :-1;  		case '&': return len==2&&op[1]=='='?AS_RIGHT   :len==2&&op[1]=='&'?AS_LEFT    :len==1?AS_LEFT    :-1; -		case '(': return len==3&&op[1]=='-'&&op[2]==')'?AS_PREFIX  :len==3&&op[1]=='!'&&op[2]==')'?AS_SUFFIX  :-1; +		case '(': return len==3&&op[1]=='-'&&op[2]==')'?AS_PREFIX  :len==3&&op[1]=='!'&&op[2]==')'?AS_PREFIX  :len==3&&op[1]=='~'&&op[2]==')'?AS_PREFIX  :-1;  		case '*': return len==3&&op[1]=='*'&&op[2]=='='?AS_RIGHT   :len==2&&op[1]=='='?AS_RIGHT   :len==2&&op[1]=='*'?AS_RIGHT   :len==1?AS_LEFT    :-1;  		case '+': return len==2&&op[1]=='='?AS_RIGHT   :len==1?AS_LEFT    :-1;  		case '-': return len==2&&op[1]=='='?AS_RIGHT   :len==1?AS_LEFT    :-1; @@ -80,17 +77,16 @@ int associativity_len(const char *op,const int len){  		case '>': return len==2&&op[1]=='='?AS_NONASSOC:len==1?AS_NONASSOC:-1;  		case '^': return len==2&&op[1]=='='?AS_RIGHT   :len==2&&op[1]=='^'?AS_LEFT    :len==1?AS_LEFT    :-1;  		case '|': return len==2&&op[1]=='='?AS_RIGHT   :len==2&&op[1]=='|'?AS_LEFT    :len==1?AS_LEFT    :-1; -		case '~': return len==1?AS_PREFIX  :-1;  		default: return -1;  	}  }  int parseoplength(const char *op){  	switch(op[0]){ -		case '!': return op[1]=='='?2:1; +		case '!': return op[1]=='='?2:-1;  		case '%': return op[1]=='='?2:1;  		case '&': return op[1]=='='?2:op[1]=='&'?2:1; -		case '(': return op[1]=='-'&&op[2]==')'?3:op[1]=='!'&&op[2]==')'?3:-1; +		case '(': return op[1]=='-'&&op[2]==')'?3:op[1]=='!'&&op[2]==')'?3:op[1]=='~'&&op[2]==')'?3:-1;  		case '*': return op[1]=='*'&&op[2]=='='?3:op[1]=='='?2:op[1]=='*'?2:1;  		case '+': return op[1]=='='?2:1;  		case '-': return op[1]=='='?2:1; @@ -100,7 +96,6 @@ int parseoplength(const char *op){  		case '>': return op[1]=='='?2:1;  		case '^': return op[1]=='='?2:op[1]=='^'?2:1;  		case '|': return op[1]=='='?2:op[1]=='|'?2:1; -		case '~': return 1;  		default: return -1;  	}  } @@ -108,10 +103,10 @@ int parseoplength(const char *op){  const char* opconststring_len(const char *op,const int len){  	if(len<=0)return NULL;  	switch(op[0]){ -		case '!': return len==2&&op[1]=='='?"!=":len==1?"!":NULL; +		case '!': return len==2&&op[1]=='='?"!=":NULL;  		case '%': return len==2&&op[1]=='='?"%=":len==1?"%":NULL;  		case '&': return len==2&&op[1]=='='?"&=":len==2&&op[1]=='&'?"&&":len==1?"&":NULL; -		case '(': return len==3&&op[1]=='-'&&op[2]==')'?"(-)":len==3&&op[1]=='!'&&op[2]==')'?"(!)":NULL; +		case '(': return len==3&&op[1]=='-'&&op[2]==')'?"(-)":len==3&&op[1]=='!'&&op[2]==')'?"(!)":len==3&&op[1]=='~'&&op[2]==')'?"(~)":NULL;  		case '*': return len==3&&op[1]=='*'&&op[2]=='='?"**=":len==2&&op[1]=='='?"*=":len==2&&op[1]=='*'?"**":len==1?"*":NULL;  		case '+': return len==2&&op[1]=='='?"+=":len==1?"+":NULL;  		case '-': return len==2&&op[1]=='='?"-=":len==1?"-":NULL; @@ -121,7 +116,6 @@ const char* opconststring_len(const char *op,const int len){  		case '>': return len==2&&op[1]=='='?">=":len==1?">":NULL;  		case '^': return len==2&&op[1]=='='?"^=":len==2&&op[1]=='^'?"^^":len==1?"^":NULL;  		case '|': return len==2&&op[1]=='='?"|=":len==2&&op[1]=='|'?"||":len==1?"|":NULL; -		case '~': return len==1?"~":NULL;  		default: return NULL;  	}  } @@ -118,6 +118,14 @@ static Token nexttoken(const char **sourcep,bool expectop){  		*sourcep+=oplen;  		return tok;  	} +	if(!expectop){ +		char buf[4]={'(',*source,')','\0'}; +		if(precedence(buf)!=-1){ +			Token tok={TT_OP,source,1}; +			(*sourcep)++; +			return tok; +		} +	}  	if(strchr("(){}",*source)!=NULL){  		Token tok={TT_SYM,source,1};  		(*sourcep)++; @@ -275,7 +283,7 @@ static AST* parseterm(const char *source,int *reslen){  				node->o.op=opconststring_len(buf,tok.len+2);  				node->o.left=NULL;  				int len; -				node->o.right=parseterm(source,&len); +				node->o.right=parseexpr(source,&len,precedence(buf));  				if(!node->o.right){  					free(node);  					return NULL; @@ -290,6 +298,7 @@ static AST* parseterm(const char *source,int *reslen){  		case TT_ERR:  			return NULL;  	} +  	*reslen=source-origsource;  	return node;  } @@ -306,10 +315,12 @@ static AST* parseexpr(const char *source,int *reslen,int minprec){  		Token tok=nexttoken(&source,true);  		printtoken(stderr,tok,"parseEXPR");  		if(tok.type==TT_ENDSTMT){ +			fprintf(stderr,"  (token undo)\n");  			source=beforeop;  			break;  		}  		if(tok.type==TT_SYM&&tok.len==1&&tok.str[0]==')'){ +			fprintf(stderr,"  (token undo)\n");  			source=beforeop;  			break;  		} @@ -319,6 +330,7 @@ static AST* parseexpr(const char *source,int *reslen,int minprec){  		}  		int prec=precedence_len(tok.str,tok.len);  		if(prec<minprec){ +			fprintf(stderr,"  (token undo)\n");  			source=beforeop;  			break;  		} @@ -383,6 +395,7 @@ AST* parse(const char *source){  		cursor+=reslen;  		const char *src=source+cursor;  		Token tok=nexttoken(&src,false); +		printtoken(stderr,tok,"parse    ");  		if(tok.type!=TT_ENDSTMT){  			ast_free(bl);  			return NULL; | 
