summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-08-18 22:05:21 +0200
committertomsmeding <tom.smeding@gmail.com>2016-08-18 22:05:21 +0200
commit15fb03902ff5550b3a8c44bde3e08df876449f7a (patch)
tree3038093b4bc1fff20e3f713d2ed8c3e9f2a1cec8
parent2c30522aa65126ebacfd52f7b38a2e24682d7065 (diff)
Third
-rw-r--r--ast.c5
-rw-r--r--ast.h10
-rw-r--r--parser.c101
3 files changed, 113 insertions, 3 deletions
diff --git a/ast.c b/ast.c
index 3d84d97..8120feb 100644
--- a/ast.c
+++ b/ast.c
@@ -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;
}
diff --git a/ast.h b/ast.h
index 46c4b49..f55d798 100644
--- a/ast.h
+++ b/ast.h
@@ -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;
};
};
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;
+ }
}