#include #include enum t {Simple,Compound}; typedef struct S { enum t tag; union { char *Uvalue; struct S **Uelems; } u; } s; #define value u.Uvalue #define elems u.Uelems s *parse() { char buffer[1000],*cp=buffer,*tp; s *sp; int ch,offs=0; while ((ch=getchar())==' '||ch=='\t'||ch=='\n') ; switch (ch) { case '"': *cp++=ch; while ((ch=getchar())!='"') { *cp++=ch; if (ch=='\\') *cp++=getchar(); } *cp++=ch; break; default: *cp++=ch; while ((ch=getchar())>=0 && !isspace(ch) && ch!=')') *cp++=ch; if (ch==')') ungetc(ch,stdin); break; case -1: case ')': return 0; case '(': sp=malloc(sizeof(s)); sp->tag=Compound; sp->elems=malloc(sizeof(s*)); while ((sp->elems[offs]=parse())) sp->elems=realloc(sp->elems,sizeof(s*)*(++offs+1)); return sp; } *cp++=0; tp=malloc(cp-buffer); strcpy(tp,buffer); sp=malloc(sizeof(s)); sp->tag=Simple; sp->value=tp; return sp; } void print_spaces(int n) { while (--n>=0) putchar(' '); } void print(s *sp,int offs,int spaces,int top) { s **spp; int pos; int indent; print_spaces(spaces); switch (sp->tag) { case Simple: printf("%s",sp->value); break; case Compound: putchar('('); pos=0; indent=0; if (strcmp(sp->elems[0]->value,"if")==0) indent=1; for (spp=sp->elems;*spp;++spp) if ((*spp)->tag==Compound) indent=1; if (indent) indent=offs+(strcmp(sp->elems[0]->value,"define")==0 || strcmp(sp->elems[0]->value,"lambda")==0 ? 3 : strlen(sp->elems[0]->value)+2); else indent=offs; for (spp=sp->elems;*spp;++pos,++spp) { if (pos<=1 || indent==offs) print(*spp,indent,pos>0,0); else { putchar('\n'); print(*spp,indent,indent,0); } } putchar(')'); break; } if (top) putchar('\n'); } main() { s *sp; while ((sp=parse())) print(sp,0,0,1); return 0; }