summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-08-08 21:18:52 +0200
committertomsmeding <tom.smeding@gmail.com>2016-08-08 21:18:52 +0200
commit77263f95bbbc9d8c91ab77726f02f445a1e3f367 (patch)
treead1856db5ae23838750e189760441e9c542eaeb6
parent392fb37ed0ff986d2c6440a3e759bb9360e1b902 (diff)
Basic if statements
-rw-r--r--code.txt9
-rw-r--r--parser.c66
2 files changed, 66 insertions, 9 deletions
diff --git a/code.txt b/code.txt
index 07e132d..783d1b5 100644
--- a/code.txt
+++ b/code.txt
@@ -8,6 +8,13 @@ x = 1 + 1 + 1 + 1;
y = 1 > (1 > 1) == 1;
kaas(1,2,"goeiemorgen\x99",sqrt(3**2+4**2));
1 + 1 + 1;
-1 - 1 - 1;
+if (2 > 1) 1 - 1 - 1;
1 / 1 / 1;
1 ** 1 ** 1;
+
+if kaas
+ doe(dingen)
+else if andere(kaas)
+ doe(andere,dingen)
+else
+ print("rip");
diff --git a/parser.c b/parser.c
index 857b11d..7ed64a6 100644
--- a/parser.c
+++ b/parser.c
@@ -11,7 +11,7 @@
#include "parser.h"
-#undef DEBUG
+#define DEBUG
#ifdef DEBUG
#define DBG(...) __VA_ARGS__
@@ -51,7 +51,7 @@ typedef enum Tokentype{
typedef struct Token{
Tokentype type;
- const char *str; //Part of another string; not null-terminated, and do not free
+ const char *str; //Pointer into source string, or NULL if TT_EOF
int len;
} Token;
@@ -253,7 +253,39 @@ static AST* parseterm(const char *source,int *reslen){
}
case TT_WORD:{
- if(tok.len==2&&memcmp(tok.str,"if",2)==0)assert(NOT_IMPLEMENTED);
+ if(tok.len==2&&memcmp(tok.str,"if",2)==0){
+ int len;
+ AST *cond=parseexpr(source,&len,0,INT_MAX);
+ if(!cond)return NULL;
+ source+=len;
+ AST *thenbody=parseexpr(source,&len,0,INT_MAX);
+ if(!thenbody){
+ ast_free(cond);
+ return NULL;
+ }
+ source+=len;
+ AST *elsebody=NULL;
+ const char *src=source;
+ Token elsetok=nexttoken(&src,false);
+ if(elsetok.type==TT_WORD&&elsetok.len==4&&memcmp(elsetok.str,"else",4)==0){
+ DBG(printtoken(stderr,elsetok,"if else "));
+ source=src;
+ elsebody=parseexpr(source,&len,0,INT_MAX);
+ if(!elsebody){
+ ast_free(cond);
+ ast_free(thenbody);
+ return NULL;
+ }
+ source+=len;
+ }
+ node=malloc(sizeof(AST));
+ if(!node)outofmem();
+ node->type=AST_IF;
+ node->i.cond=cond;
+ node->i.thenb=thenbody;
+ node->i.elseb=elsebody;
+ break;
+ }
if(tok.len==5&&memcmp(tok.str,"while",2)==0)assert(NOT_IMPLEMENTED);
const char *tempsource=source;
Token next=nexttoken(&source,false);
@@ -381,8 +413,11 @@ static AST* parseexpr_(const char *source,int *reslen,int minprec,int maxprec){
break;
}
if(tok.type!=TT_OP){
- ast_free(tree);
- return NULL;
+ /*ast_free(tree);
+ return NULL;*/
+ DBGF(" (token undo)\n");
+ source=beforeop;
+ break;
}
int prec=precedence_len(tok.str,tok.len);
if(prec<minprec){
@@ -538,7 +573,7 @@ static void ast_debug_(FILE *stream,const AST *ast,int indent){
for(int i=0;i<ast->b.len;i++){
INDENT
ast_debug_(stream,ast->b.exprs[i],indent);
- fputc('\n',stream);
+ fprintf(stream,";\n");
}
indent--;
INDENT
@@ -580,14 +615,29 @@ static void ast_debug_(FILE *stream,const AST *ast,int indent){
case AST_CALL:
fprintf(stream,"%s(",ast->c.func);
for(int i=0;i<ast->c.nargs;i++){
- if(i!=0)fputc(',',stream);
+ if(i!=0)fprintf(stream,", ");
ast_debug_(stream,ast->c.args[i],indent);
}
fputc(')',stream);
break;
case AST_IF:
- assert(NOT_IMPLEMENTED);
+ fprintf(stream,"if (");
+ ast_debug_(stream,ast->i.cond,indent);
+ fprintf(stream,")\n");
+ indent++;
+ INDENT
+ ast_debug_(stream,ast->i.thenb,indent);
+ indent--;
+ if(ast->i.elseb){
+ fputc('\n',stream);
+ INDENT
+ fprintf(stream,"else\n");
+ indent++;
+ INDENT
+ ast_debug_(stream,ast->i.elseb,indent);
+ indent--;
+ }
break;
case AST_WHILE: