/*
 再帰的下降構文解析プログラム
 */
#include <stdio.h>
#include <stdlib.h>   /* exit()用 */
#include <ctype.h>    /* isdigit()用 */

/* 大域変数の宣言 */
int token;	/* 入力の先頭のトークンを表す */
int yylval;	/* tokenの属性 */

/* 終端記号に対応するマクロの定義 */
#define ID  256
#define EOL 257

/* 簡易字句解析ルーチン */
int yylex(void) {   
  int c;
  
  do {
    c = getchar ();
  } while (c == ' ' || c == '\t'); /* 空白は読み飛ばす */

  if (isalpha(c)) { /* IDは一文字のアルファベット */
    yylval = c;
    return ID;
  }

  if (c == '\n') {
    return EOL;  /* 行末が $（入力の終わり）に対応する */
  }
  
  if (c == EOF) { /* ファイルの終 */
    exit(0); 
  }
  /* 上のどの条件にも合わなければ、文字をそのまま返す。*/
  return c;   /* '(', ')', '*'など */
}

/* token（終端記号）を消費して、次の tokenを読む */
void eat(int t) {	
  if (token == t) {
    token = yylex();
    return;
  } else {
    if (t < 256) {
      printf("%c is expected here.\n", t);
    } else {
      printf("token %d is expected here.\n", t);
    }
    exit (0);
  }
}

/* 関数プロトタイプ宣言 */
void E(void);
void E1(void);    /* 'は Cの関数名に使えないので代わりに 1を使う */
                  /* E'は左再帰を除去する時に導入した非終端記号  */
void X(void);
void X1(void);

/* 
   再帰的構文解析関数群
   文法の各非終端記号に対応する関数
 */

/***********************************************************************
 ここに E(), E1(), X(), X1()を定義してください 
 ***********************************************************************/

/* 各行の処理 */
void ProcessLine() {
  E();
  if (token==EOL) { /* 入力がブロックしないように改行は特別扱い */
    printf("Correct!\n");   /* eat(EOL)の前に出力しておく */
  }
  eat(EOL);
}

/* main関数 */
int main(void) {
  printf("Ctrl-cで終了します。\n");
  token = yylex(); /* 最初のトークンを読む */
  while (1 /* 無限ループ */) {
    ProcessLine();  /* 各行を処理する */
  }
}
