/*
 * parser.c    Tim McLarnan 10/29/1999
 * Interprets infix arithmetic expressions in which
 * every variable is a 2.
 */

#include <stdio.h>

char current_char;

int nextchar(void);
int expression(void);
int ebar(void);
int term(void);
int tbar(void);
int factor(void);
int variable(void);

int nextchar(void) {
  while (((current_char = getchar()) != EOF) && (current_char == ' '))
    ;
  return current_char;
}

void error(char *pname) {
  int c;
  fprintf(stderr, "Error in function ");
  fprintf(stderr, pname);
  fprintf(stderr, ": \n  current_char = ");
  putc(current_char, stderr);
  fprintf(stderr, "\n  string remaining = ");
  while (((c = getchar()) != EOF) && (c != '\n'))
    putc(c, stderr);
  fprintf(stderr, "\n\n");
}

int expression(void) {
  int termvalue, ebarvalue;
  switch (current_char) {
  case '2':
  case '(':
    termvalue = term();
    ebarvalue = ebar();
    return (termvalue + ebarvalue);
  default:
    error("expression");
  }
}

int ebar(void) {
  switch (current_char) {
  case '+':
    nextchar();
    return expression();
  case ')':
  case '\n':
    return 0;
  default:
    error("ebar");
  }
}

int term(void) {
  int factorvalue, tbarvalue;
  switch (current_char) {
  case '2':
  case '(':
    factorvalue = factor();
    tbarvalue = tbar();
    return (factorvalue * tbarvalue);
  default:
    error("term");
  }
}

int tbar(void) {
  int fatorvalue, tbarvalue;
  switch (current_char) {
  case '*':
    nextchar();
    return term();
  case '+':
  case ')':
  case '\n':
    return 1;
  default:
    error("tbar");
  }
}

int factor(void) {
  int expressionvalue;
  switch (current_char) {
  case '2':
    return variable();
  case '(':
    nextchar();
    expressionvalue = expression();
    if (current_char == ')') {
      nextchar();
      return expressionvalue;
    } else {
      error("factor");
    }
    break;
  default:
    error("factor");
  }
}

int variable(void) {
  switch (current_char) {
  case '2':
    nextchar();
    return 2;
  default:
    error("variable");
  }
}

int main(void) {
  do {
    printf("> ");
    if (nextchar() != EOF)
      printf("%d\n\n", expression());
  } while (current_char != EOF);
  return 0;
}

