summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-08-06 11:51:11 +0200
committertomsmeding <tom.smeding@gmail.com>2016-08-06 11:51:11 +0200
commit6eb5ea040f9ebc1a99953ff72c48ebe9f97f7f3c (patch)
tree8cfe5e013cf551053ebb4faceaa514c435a7e3c6
parent2696105687d9c889ec4cccd449846135f83af404 (diff)
Ditch suffix; make prefix work better
-rw-r--r--LANGUAGE.txt5
-rw-r--r--code.txt2
-rw-r--r--opfuncs.c34
-rw-r--r--parser.c15
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()
diff --git a/code.txt b/code.txt
index ae7ef31..544e5d1 100644
--- a/code.txt
+++ b/code.txt
@@ -1,5 +1,5 @@
a = 1;
-b = 2;
+b = !2;
c = 1 + (- a - 3 + b > -1);
b += 1;
b = 3*(b//3-1);
diff --git a/opfuncs.c b/opfuncs.c
index a5607ae..174b1d6 100644
--- a/opfuncs.c
+++ b/opfuncs.c
@@ -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;
}
}
diff --git a/parser.c b/parser.c
index 6cced13..b2bd68b 100644
--- a/parser.c
+++ b/parser.c
@@ -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;