new and improved
#include<stdio.h>
#include<ctype.h>
#define DECL(ret, name, ...) \
struct name { \
ret (*f)(struct name *,__VA_ARGS__); \
void *p; \
}
#define CALL(closure, ...) closure.f(&closure,__VA_ARGS__)
DECL(int,ii,int);
int nothing(int c){
return 0;
}
struct callf{
int (*f)(int);
};
int callf(struct ii *closure, int c){
struct callf *p=closure->p;
return p->f(c);
}
struct addspace{
int flag;
struct ii act;
};
int addspace(struct ii *closure, int c){
struct addspace *p=closure->p;
if(p->flag){
p->flag=0;
CALL(p->act,' ');
}
return CALL(p->act,c);
}
const struct ii myisdigit={callf,&(struct callf){isdigit}};
const struct ii myisspace={callf,&(struct callf){isspace}};
const struct ii mynothing={callf,&(struct callf){nothing}};
int satisfy(struct ii check, struct ii act){
int c;
int i=0;
while((c=getchar())!=EOF)
if(!CALL(check,c)){
ungetc(c,stdin);
break;
}else{
++i;
CALL(act,c);
}
return i;
}
int expect1(int x){
int c=getchar();
if (x==c)
return 1;
else{
ungetc(c, stdin);
return 0;
}
}
int elementloop(struct ii act1, struct ii act2);
int element(struct ii act1, struct ii act2){
if(expect1(')')){
CALL(act1,')');
return 0;
} else if(expect1('(')){
CALL(act2,'(');
satisfy(myisspace,mynothing);
return elementloop(act1,act2);
} else
satisfy(myisdigit,act2);
return 1;
}
int elementloop(struct ii act1, struct ii act2){
struct addspace addspaceinfo={1,act2};
struct ii myaddspace={addspace,&addspaceinfo};
if(element(act1,act2))
do{
satisfy(myisspace,mynothing);
addspaceinfo.flag=1;
}while(element(act1,myaddspace));
return 1;
}
int main(int argc, char *argv[]){
int status;
const struct ii myputchar={callf,&(struct callf){putchar}};
argv[1]++; /* c */
expect1('(');
while(*argv[1]!='r'){
satisfy(myisspace,mynothing);
switch(*argv[1]++){
case 'd':
element(mynothing,mynothing);
status=0;
break;
case 'a':
if(expect1('('))
status=1;
else{
satisfy(myisdigit,myputchar);
status=2;
}
}
}
if(!status){
satisfy(myisspace,mynothing);
putchar('(');
elementloop(myputchar,myputchar);
}
else if(status==1){
ungetc('(',stdin);
element(myputchar,myputchar);
}
putchar('\n');
}
Edited on 28/03/2021 05:01.
Body is too long to be processed.
Original Body:
New and improved
#include<stdio.h>
#include<ctype.h>
#define DECL(ret, name, ...) \
struct name { \
ret (*f)(struct name *,__VA_ARGS__); \
void *p; \
}
#define CALL(closure, ...) closure.f(&closure,__VA_ARGS__)
DECL(int, ii, int);
int nothing(int c){
return 0;
}
struct callf {
int (*f)(int);
};
int callf(struct ii *closure, int c){
struct callf *p = closure->p;
return p->f(c);
}
struct addspace {
int flag;
struct ii act;
};
int addspace(struct ii *closure, int c){
struct addspace *p = closure->p;
if(p->flag){
p->flag=0;
CALL(p->act,' ');
}
return CALL(p->act,c);
}
const struct ii myisdigit = {callf, &(struct callf){isdigit}};
const struct ii myisspace = {callf, &(struct callf){isspace}};
const struct ii mynothing = {callf, &(struct callf){nothing}};
int satisfy(struct ii check, struct ii act){
int c;
int i=0;
while((c=getchar())!=EOF)
if(!CALL(check,c)){
ungetc(c,stdin);
break;
}else{
++i;
CALL(act,c);
}
return i;
}
int expect1(int x){
int c=getchar();
if (x==c)
return 1;
else{
ungetc(c, stdin);
return 0;
}
}
int element(struct ii act1, struct ii act2){
if(expect1(')')){
CALL(act1,')');
return 0;
} else if(expect1('(')){
struct addspace addspaceinfo = {1, act2};
struct ii myaddspace = {addspace, &addspaceinfo};
CALL(act2,'(');
satisfy(myisspace,mynothing);
if(element(act1,act2))
do{
satisfy(myisspace,mynothing);
addspaceinfo.flag = 1;
}while(element(act1,myaddspace));
} else
satisfy(myisdigit,act2);
return 1;
}
int main(int argc, char *argv[]){
int status;
const struct ii myputchar = {callf, &(struct callf){putchar}};
argv[1]++; /* c */
expect1('(');
while(*argv[1]!='r'){
satisfy(myisspace,mynothing);
switch(*argv[1]++){
case 'd':
element(mynothing,mynothing);
status=0;
break;
case 'a':
if(expect1('('))
status=1;
else{
satisfy(myisdigit,myputchar);
status=2;
}
}
}
if(!status){
satisfy(myisspace,mynothing);
putchar('(');
if(element(myputchar,myputchar)){
struct addspace addspaceinfo = {1, myputchar};
struct ii myaddspace = {addspace, &addspaceinfo};
do{
satisfy(myisspace,mynothing);
addspaceinfo.flag = 1;
}while(element(myputchar, myaddspace));
}
}
else if(status == 1){
ungetc('(',stdin);
element(myputchar, myputchar);
}
putchar('\n');
}