#include <stdio.h>
#include "token_nums.h"
/* This is a nonsense grammar from a programming contest:
  the lowercase words are non-terminals, the uppercase characters
  are the terminals of this language.

  slurpy -> slimp slump
  slimp -> A rest_slimp 
  rest_slimp  -> H
  rest_slimp -> B slimp C
  rest_slimp -> slump C
  slump -> d_or_e F f_string end 
  d_or_e -> D
  d_or_e -> E
  f_string -> F f_string | lambda
  end -> slump
  end -> G 

Some strings in the language: AHDFG, ADFGCDFFFFFG, ABAEFGCCDFEFFFFFFG
Some strings NOT in the lanuage: AHDFGA, DFGAH, ABABCC
*/

int lookahead;
int error_found = 0;

main(int argc, char**argv) {
  /* number of input lines comes in on command line */
      lookahead = yylex();
      error_found = 0;
      slurp_file();
      if ((!error_found) & (lookahead == 0))
          printf("String accepted\n");
      else {
       printf("String rejected\n");
       /* throw away any extra input */
  }
}

error(char *where) {
  printf("Error found in function %s\n",where);
  error_found = 1;
}

match(int token) {
  if (token == lookahead) lookahead = yylex();
  else error("match");
}

slurp_file() {
  if (lookahead == A_TOKEN) {
    slurpy(); match(EOLN);slurp_file();
  } 
}

slurpy() {
  if (lookahead == A_TOKEN) {
     slimp(); slump();
  } else error("slurpy");
}

slimp() {
  if (lookahead == A_TOKEN) {
    match(A_TOKEN); rest(); 
  } else error("slimp");
}

rest() {
  switch (lookahead)  {
    case H_TOKEN: match(H_TOKEN); break;
    case B_TOKEN: match(B_TOKEN); slimp(); match(C_TOKEN); break;
    case D_TOKEN:
    case E_TOKEN: slump(); match(C_TOKEN); break;
    default: error("rest");
  }
}

slump() {
  if ((lookahead == D_TOKEN) | (lookahead == E_TOKEN)) {
     d_or_e(); match(F_TOKEN); f_str(); end();
  } else error("slump");
}

d_or_e() {
  if (lookahead == D_TOKEN) match(D_TOKEN);
  else if (lookahead == E_TOKEN) match(E_TOKEN);
  else error("d_or_e");
}

f_str() {
  switch(lookahead) {
    case F_TOKEN: match(F_TOKEN); f_str(); break;
    case D_TOKEN: case E_TOKEN: case G_TOKEN: break;
    default: error("f_str");
  }
}

end() {
  switch(lookahead) {
    case G_TOKEN: match(G_TOKEN); break;
    case D_TOKEN: case E_TOKEN: slump(); break;
    default: error("end");
  }
}


#include "lex.yy.c"

