/* Problem 8--Recognizing S Expressions
   If you saw how to do it, it wasn't too bad.  The program that solves
   this problem is essentially a mini-compiler.  The idea is that in
   order to test if something is an s-expression, you use recursion to
   see whether the stuff on the inside is an s-expression. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE *in, *out;
int ERROR;

int main (int argc, char **argv);
void Process (char *s);
char *ParseS (char *s);
char *trim (char *s);

int main (int argc, char **argv) {

  int ct=1;
  char line[80], *s;

 in = fopen ("prob8.in","r");
 out = fopen ("prob8.out","w");
 while (1) {
  fgets (line,sizeof line,in);
  s = trim (line);
  if (s[0]==0) break;
  fprintf (out,"%d: %s\n",ct++,s);
  Process (s);
  if (!ERROR)
   fprintf (out,"   is an s-expression.\n\n");
  else /* as soon as we know something is not, we throw an */
   fprintf (out,"   is not an s-expression.\n\n");/* exception.*/
 }
 fclose (in);
 fclose (out);
 return EXIT_SUCCESS;
}

/* Process processes a string to see if it's valid. */
void Process (char *s) {

 ERROR = 0;
 s = ParseS (s);/*after parsing an S-expression, we make sure the line*/
 if (ERROR) return;
 if (s[0]!=0) ERROR=1;/*is empty.*/
}

/* This routine checks for validity, calling itself */
char *ParseS (char *s) {

 if ((s[0] >= 'A' && s[0] <= 'Z') || (s[0] >= 'a' && s[0] <= 'z'))
  return s+1;/*if it's a single letter return the rest of the string.*/
 if (s[0] != '(') {ERROR=1;return NULL;}/*it had better be a ( now.*/
 s = ParseS(s+1);if (ERROR) return NULL;
 if (s[0] != ',') {ERROR=1;return NULL;}/*A comma must separate them.*/
 s = ParseS(s+1);if (ERROR) return NULL;
 if (s[0] != ')') {ERROR=1;return NULL;}/*A ) must follow.*/
 return s+1;
}

/*This simply removes all leading and trailing spaces from a string.*/
char *trim (char *s) {

 int l = strlen(s)-2;
 for (; l >= 0; l--)
  if (s[l] != ' ') break;
 s[l+1] = 0;
 for (; s[0] != 0; s++)
  if (s[0]!= ' ') break;
 return s;
}
