You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
2.2 KiB
124 lines
2.2 KiB
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <libse.h>
|
|
#include <internal/exstring.h>
|
|
|
|
static void _addcar(list_t* out, exString* token)
|
|
{
|
|
#ifdef SE_PARSE_NIL
|
|
if(strcmp(EXS(token), "nil")==0)
|
|
out->ptr = NULL;
|
|
else {
|
|
#endif
|
|
out->ptr = strdup(EXS(token));
|
|
out->car.size = strlen(out->ptr);
|
|
out->car.alloced = 1;
|
|
exs_reset(token);
|
|
#ifdef SE_PARSE_NIL
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static list_t* _parse_list(const char* sexpr, int* lp)
|
|
{
|
|
list_t* out = malloc(sizeof(list_t));
|
|
memset(out,0,sizeof(list_t));
|
|
exString *token = exs_new(NULL);
|
|
|
|
while(*sexpr) {
|
|
if(*sexpr==' ') {
|
|
if(strlen(EXS(token))>0) {
|
|
_addcar(out, token);
|
|
|
|
if(*(sexpr+1))
|
|
out->cdr = _parse_list(sexpr, lp);
|
|
else out->cdr =NULL;
|
|
break;
|
|
}
|
|
}
|
|
else if(*sexpr == ')')
|
|
{
|
|
_addcar(out, token);
|
|
out->cdr=NULL;
|
|
(*lp)+=1;
|
|
break;
|
|
}
|
|
else if(*sexpr == '(')
|
|
{
|
|
int hp =0;
|
|
list_t* nc = _parse_list(sexpr+1, &hp);
|
|
out->ptr = nc;
|
|
out->car.alloced=1;
|
|
out->car.sexpr=1;
|
|
out->car.size = sizeof(list_t);
|
|
sexpr+= hp+1;
|
|
(*lp) += hp+1;
|
|
|
|
if(*(sexpr))
|
|
out->cdr = _parse_list(sexpr, lp);
|
|
else out->cdr =NULL;
|
|
break;
|
|
}
|
|
else
|
|
exs_nappend(token, sexpr, 1);
|
|
sexpr+=1;
|
|
(*lp)+=1;
|
|
}
|
|
|
|
if(strlen(EXS(token))>0)
|
|
_addcar(out, token);
|
|
else if(!out->ptr && !out->cdr) {
|
|
free(out);
|
|
out=NULL;
|
|
}
|
|
|
|
exs_free(token);
|
|
return out;
|
|
}
|
|
|
|
list_t* se_parse(const char* str)
|
|
{
|
|
int lp=0;
|
|
return _parse_list(str,&lp);
|
|
}
|
|
|
|
void _list_tostring(exString *out, const list_t* list)
|
|
{
|
|
if(!list->ptr)
|
|
exs_append(out, "nil");
|
|
else if(list->car.sexpr) {
|
|
exs_append(out, "(");
|
|
_list_tostring(out, (list_t*)list->ptr);
|
|
}
|
|
else exs_append(out,(char*)list->ptr);
|
|
|
|
if(list->cdr)
|
|
{
|
|
exString *wtf = exs_new(NULL);
|
|
_list_tostring(wtf, list->cdr);
|
|
if(EXS(wtf)[0]!=')')
|
|
exs_append(out, " ");
|
|
exs_append(out, EXS(wtf));
|
|
exs_free(wtf);
|
|
}
|
|
else exs_append(out, ")");
|
|
}
|
|
|
|
void se_print(FILE* fp, const list_t* list)
|
|
{
|
|
if(fp == NULL) fp = stdout;
|
|
exString* str = exs_new("(");
|
|
_list_tostring(str, list);
|
|
fprintf(fp, "%s", EXS(str));
|
|
exs_free(str);
|
|
}
|
|
|
|
void se_free(list_t* list)
|
|
{
|
|
if(list->cdr) se_free(list->cdr);
|
|
if(list->ptr && list->car.alloced)
|
|
free(list->ptr);
|
|
free(list);
|
|
}
|