summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c101
1 files changed, 99 insertions, 2 deletions
diff --git a/parser.c b/parser.c
index 7e7a1c2..5069904 100644
--- a/parser.c
+++ b/parser.c
@@ -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;
+ }
}