diff options
author | tomsmeding <tom.smeding@gmail.com> | 2016-08-18 22:05:21 +0200 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2016-08-18 22:05:21 +0200 |
commit | 15fb03902ff5550b3a8c44bde3e08df876449f7a (patch) | |
tree | 3038093b4bc1fff20e3f713d2ed8c3e9f2a1cec8 | |
parent | 2c30522aa65126ebacfd52f7b38a2e24682d7065 (diff) |
Third
-rw-r--r-- | ast.c | 5 | ||||
-rw-r--r-- | ast.h | 10 | ||||
-rw-r--r-- | parser.c | 101 |
3 files changed, 113 insertions, 3 deletions
@@ -41,7 +41,9 @@ AST* ast_copy(const AST *ast){ assert(ast->l.nodes); AST **nodes=malloc(ast->l.len,AST*); for(int i=0;i<ast->l.len;i++)nodes[i]=ast_copy(ast->l.nodes[i]); - return ast_list(ast->l.len,nodes); + AST *l=ast_list(ast->l.len,nodes); + l->l.quoted=ast->l.quoted; + return l; } case AST_WORD: @@ -71,6 +73,7 @@ AST* ast_list(int len,AST **nodes){ ast->l.len=len; ast->l.nodes=malloc(len,AST*); memcpy(ast->l.nodes,nodes,len*sizeof(AST*)); + ast->l.quoted=false; return ast; } @@ -1,10 +1,13 @@ #pragma once +#include <stdbool.h> + typedef enum ASTtype{ AST_LIST, AST_WORD, AST_NUMBER, + AST_STRING, AST_SYMBOL, } ASTtype; @@ -14,6 +17,7 @@ typedef struct AST AST; typedef struct ASTlist{ int len; AST **nodes; + bool quoted; } ASTlist; typedef struct ASTword{ @@ -24,6 +28,11 @@ typedef struct ASTnumber{ double num; } ASTnumber; +typedef struct ASTstring{ + char *str; + int len; +} ASTstring; + typedef struct ASTsymbol{ char *name; int symid; @@ -38,6 +47,7 @@ struct AST{ ASTlist l; ASTword w; ASTnumber n; + ASTstring S; ASTsymbol s; }; }; @@ -15,7 +15,9 @@ typedef enum Tokentype{ TT_EOF, //str=NULL, len=-1 TT_SYMBOL, TT_WORD, + TT_QUOTEDWORD, TT_NUMBER, + TT_STRING, TT_ERR=-1 //str is an error description, len=-1 } Tokentype; @@ -71,6 +73,28 @@ static Token nexttoken(Cursor *cursor){ return tt_make(TT_NUMBER,cursor->s-len,len); } + if(*cursor->s=='"'){ + int i; + for(i=0;i<cursor->l;i++){ + if(cursor->s[i]=='"')break; + if(cursor->s[i]=='\\')i++; + } + if(i==cursor->l){ + return tt_err("Unclosed string in source"); + } + advance(cursor,i); + return tt_make(TT_STRING,cursor->s-i,i); + } + + bool isquoted=false; + if(*cursor->s=='\''){ + isquoted=true; + advance(cursor,1); + if(cursor->l==0||!iswordchar(*cursor->s)){ + return tt_err("Lone single quote in source"); + } + } + int i; for(i=0;i<cursor->l;i++){ if(!iswordchar(cursor->s[i]))break; @@ -79,12 +103,85 @@ static Token nexttoken(Cursor *cursor){ return tt_err("Unrecognised character while looking for next token"); } advance(cursor,i); - return tt_make(TT_WORD,cursor->s-i,i); + return tt_make(isquoted?TT_QUOTEDWORD:TT_WORD,cursor->s-i,i); +} + + +static ParseRet pr_ast(AST *ast){ + ParseRet pr={ast,NULL}; + return pr; +} + +static ParseRet pr_err(char *errstr){ + ParseRet pr={NULL,errstr}; + return pr; } +static ParseRet pr_err_c(const char *errstr){ + return pr_err(copystring(errstr)); +} static ParseRet parse_(Cursor *cursor){ - ; + Token tok=nexttoken(cursor); + switch(tok.type){ + case TT_EOF: + return pr_err_c("Unexpected end-of-file"); + + case TT_SYMBOL:{ + char closing; + if(tok.len!=1)assert(false); + if(tok.str[0]=='(')closing=')'; + else if(tok.str[0]=='[')closing=']'; + else if(tok.str[0]==')'||tok.str[0]==']'){ + return pr_err_c("Unexpected closing paren in source"); + } else assert(false); + + int sz=2,len=0; + AST **nodes=malloc(sz,AST*); + while(true){ + Cursor cur2v=*cursor,*cur2=&cur2v; + Token t=nexttoken(cur2); + if(t.type==TT_SYMBOL&&t.len==1&&t.str[0]==closing){ + *cursor=cur2v; + break; + } + if(t.type==TT_EOF){ + for(int i=0;i<len;i++)ast_free(nodes[i]); + free(nodes); + return pr_err_c("Unexpected end-of-file while parsing list"); + } + + ParseRet pr=parse_(cursor); + if(pr.errstr){ + for(int i=0;i<len;i++)ast_free(nodes[i]); + free(nodes); + return pr; + } + if(len==sz){ + sz*=2; + nodes=realloc(nodes,sz,AST*); + } + nodes[len++]=pr.ast; + } + return pr_ast(ast_list(len,nodes)); + break; + } + + case TT_WORD: + break; + + case TT_QUOTEDWORD: + break; + + case TT_NUMBER: + break; + + case TT_STRING: + break; + + case TT_ERR: + break; + } } |