summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-08-06 11:17:56 +0200
committertomsmeding <tom.smeding@gmail.com>2016-08-06 11:17:56 +0200
commit2696105687d9c889ec4cccd449846135f83af404 (patch)
tree032c4c114049631767b08df21bc165d0ccbdb8b9 /parser.c
parentf67988fbfde6ad8a91466ef5d4227dcf9e5db6ce (diff)
Fix (-) handling
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/parser.c b/parser.c
index 14fd47d..6cced13 100644
--- a/parser.c
+++ b/parser.c
@@ -79,7 +79,7 @@ static void skipintermediate(const char **sourcep){
*sourcep=source;
}
-static Token nexttoken(const char **sourcep){
+static Token nexttoken(const char **sourcep,bool expectop){
skipintermediate(sourcep);
const char *source=*sourcep;
if(*source=='\0'){
@@ -91,7 +91,7 @@ static Token nexttoken(const char **sourcep){
(*sourcep)++;
return tok;
}
- if(isdigit(*source)||(*source=='-'&&isdigit(source[1]))){
+ if(isdigit(*source)||(!expectop&&*source=='-'&&isdigit(source[1]))){
char *endp;
strtod(source,&endp);
assert(endp!=source);
@@ -161,9 +161,11 @@ static void printtoken(FILE *stream,Token tok,const char *msg){
}
+static AST* parseexpr(const char *source,int *reslen,int minprec);
+
static AST* parseterm(const char *source,int *reslen){
const char *origsource=source;
- const Token tok=nexttoken(&source);
+ const Token tok=nexttoken(&source,false);
printtoken(stderr,tok,"parseterm");
AST *node;
switch(tok.type){
@@ -229,7 +231,7 @@ static AST* parseterm(const char *source,int *reslen){
if(tok.len==2&&memcmp(tok.str,"if",2)==0)assert(NOT_IMPLEMENTED);
if(tok.len==5&&memcmp(tok.str,"while",2)==0)assert(NOT_IMPLEMENTED);
const char *tempsource=source;
- Token next=nexttoken(&source);
+ Token next=nexttoken(&source,false);
if(next.len==1&&next.str[0]=='(')assert(NOT_IMPLEMENTED);
source=tempsource;
node=malloc(sizeof(AST));
@@ -243,7 +245,21 @@ static AST* parseterm(const char *source,int *reslen){
}
case TT_SYM:
- assert(NOT_IMPLEMENTED);
+ if(tok.len==1&&tok.str[0]=='{'){
+ assert(NOT_IMPLEMENTED);
+ } else if(tok.len==1&&tok.str[0]=='('){
+ int len;
+ node=parseexpr(source,&len,0);
+ if(!node)return NULL;
+ source+=len;
+ Token aftertok=nexttoken(&source,false);
+ if(aftertok.type!=TT_SYM||aftertok.len!=1||aftertok.str[0]!=')'){
+ ast_free(node);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
break;
case TT_OP:{
@@ -287,12 +303,16 @@ static AST* parseexpr(const char *source,int *reslen,int minprec){
source+=len;
while(true){
const char *beforeop=source;
- Token tok=nexttoken(&source);
+ Token tok=nexttoken(&source,true);
printtoken(stderr,tok,"parseEXPR");
if(tok.type==TT_ENDSTMT){
source=beforeop;
break;
}
+ if(tok.type==TT_SYM&&tok.len==1&&tok.str[0]==')'){
+ source=beforeop;
+ break;
+ }
if(tok.type!=TT_OP){
ast_free(tree);
return NULL;
@@ -362,14 +382,14 @@ AST* parse(const char *source){
bl->b.exprs[bl->b.len++]=node;
cursor+=reslen;
const char *src=source+cursor;
- Token tok=nexttoken(&src);
+ Token tok=nexttoken(&src,false);
if(tok.type!=TT_ENDSTMT){
ast_free(bl);
return NULL;
}
cursor=src-source;
src=source+cursor;
- tok=nexttoken(&src);
+ tok=nexttoken(&src,false);
if(tok.type==TT_EOF)break;
}
return bl;
@@ -409,10 +429,11 @@ static void ast_debug_(FILE *stream,const AST *ast,int indent){
case AST_OP:{
bool leftp=ast->o.left&&ast->o.left->type==AST_OP&&precedence(ast->o.left->o.op)<=precedence(ast->o.op);
bool rightp=ast->o.right&&ast->o.right->type==AST_OP&&precedence(ast->o.right->o.op)<=precedence(ast->o.op);
+ bool spaces=ast->o.left&&ast->o.right;
//fprintf(stderr,"[[op='%s' p=%d lp=%d rp=%d]]",ast->o.op,precedence(ast->o.op),leftp,rightp);
if(leftp)fputc('(',stream);
if(ast->o.left)ast_debug_(stream,ast->o.left,indent);
- fprintf(stream,"%s%s%s",leftp?")":"",ast->o.op,rightp?"(":"");
+ fprintf(stream,"%s%s%s%s%s",leftp?")":"",spaces?" ":"",ast->o.op,spaces?" ":"",rightp?"(":"");
if(ast->o.right)ast_debug_(stream,ast->o.right,indent);
if(rightp)fputc(')',stream);
break;