// a table driven scanner

// The state table that drives it looks like

//     | l ( ) , backup
// ----+----------------
//  1  | 2 3 4 5
//     |
//  2  | 2 7 7 7    n
//     |
//  3  | 6 6 6 6    n
//  -  |
//  4  | 6 6 6 6    n
//  -  |
//  5  | 6 6 6 6    n
//  -  |
//  6  | 6 6 6 6     
//     |
//  7  | 6 6 6 6    y
//  -  |


ifstream * fin;
buf_index = 0;
state = 1;
while(1)
{
  in_char = fin->get();
  token_buffer[buf_index++] = in_char;
  state = table[state][in_char];
  if (accepting_state(state))
  {
    if (backup[state] == 'y')
    {
      fin->putback(in_char);
      buf_index--;
    }
    token_buffer[buf_index] = 0;
    return token_number(state);
  }
}

// A more direct simulation of the same DFA

int scanner(ifstream * fin)
{
  char in_char;
  buf_index = 0;
  state = 1;
  while(1)
  {
    in_char = fin->get();
    token_buffer[buf_index++] = in_char;
    switch(state)
    {
      case 1:
        switch(in_char)
        {
          case 'l': state = 2; break;
          case '(': state = 3; break;
          case ')': state = 4; break;
          case ',': state = 5; break;
        }
        break;
      case 2:
        if (in_char == 'l') state = 2;
        else state = 7;
        break;
      case 3:
        token_buffer[buf_index] = 0;
        return LPAREN;
      case 4:
        token_buffer[buf_index] = 0;
        return RPAREN;
      case 5:
        token_buffer[buf_index] = 0;
        return COMMA;
      case 7:
        fin -> putback(in_char);
        token_buffer[--buf_index] = 0;
        return ID;
    }
  }
}
