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

#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);
}