/* lparse.c: parse s-expressions, * conv to internal form and print. * grammar: sexpr ---> alphanum | "(" tail * tail ---> ")" | sexpr tail */ #include #include typedef enum {l, a} Stype; /* type of Scell */ typedef struct scell* Sp; /* pointer to an S-expr */ typedef struct scell { /* S-expr declaration */ Stype celltype; /* tag, what kind of S-expr? */ struct { Sp first; /* pointer to car */ Sp rest; /* pointer to cdr */ } lcell; char alf; /* alpha S-expr */ } Scell; Sp getsexpr(void); Sp sexpr(void); Sp tail (void); Sp cons(Sp, Sp); Sp car(Sp); Sp cdr(Sp); void writesexpr(Sp); Sp err(int); Sp newalfatom(char); Stype ctype(Sp); char gettoken(void); void wsexpr(Sp ); void wtail(Sp ); char tok; void main(void) { Sp s; s = getsexpr(); writesexpr(s); printf("\n"); } /* getsexpr: fetch next S-expression */ Sp getsexpr (void) { tok = gettoken(); return(sexpr()); } /* sexpr: recognize and return an S-expression */ Sp sexpr (void) { if (isalnum(tok)) return(newalfatom(tok)); if (tok == '(') return(tail()); return(err(0)); } /* tail: recognize tail end of S-expression */ Sp tail (void) { Sp s, t; tok = gettoken(); if (tok == ')') return(NULL); s = sexpr(); t = tail(); return(cons(s, t)); } /* cons: tack two S-expressions together */ Sp cons (Sp s, Sp t) { Sp r = (Sp) malloc(sizeof(Scell)); r -> celltype = l; r -> lcell.first = s; r -> lcell.rest = t; return(r); } /* car: chase the first pointer of an S-expression */ Sp car (Sp s) { if (s == NULL) return(err(1)); if (s -> celltype == l) return(s -> lcell.first); return(err(2)); } /* cdr: chase the second pointer of an S-expression */ Sp cdr (Sp s) { if (s == NULL) return(err(3)); if (s -> celltype == l) return(s -> lcell.rest); return(err(4)); } /* newalfatom: create a new alpha S-expression */ static Sp newalfatom (char alfa) { Sp r = (Sp) malloc(sizeof(Scell)); r -> celltype = a; r -> alf = alfa; return(r); } /* ctype: what type is an S-expression? */ Stype ctype (Sp s) { return(s -> celltype); } /* writesexpr: write an entire S-expression */ void writesexpr(Sp s) { wsexpr(s); printf("\n"); } /* wsexpr: write S-expression, calls tail */ static void wsexpr(Sp s) { if (s == NULL) { printf("("); printf(")"); return; } if (ctype(s) == a) { printf("%c", s -> alf); return; } printf("("); wtail(s); } /* wtail: write tail of S-expression */ static void wtail(Sp s) { if (s == NULL) { printf(")"); return; } wsexpr(car(s)); printf(" "); wtail(cdr(s)); } /* err: error message */ Sp err(int i) { printf("Error number: %ld\n", i); return(NULL); } /* gettoken: fetch next token (here just a char) */ char gettoken(void) { char ch; while (isspace(ch = getchar()) && ch != EOF) ; return ch; } four06% cc -o lparse lparse.c four06% lparse a a four06% lparse () () four06% lparse (a) (a ) four06% lparse (a b) (a b ) four06% lparse (ab) (a b ) four06% lparse (a b c) (a b c ) four06% lparse (a b (c d (e ) f ) g h ) (a b (c d (e ) f ) g h )