/* scanner for Shrdlu blocks world (i.e., English language) */

%{
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "shrdparse.tab.h"
#include "tree.h"
tree build_number(int i);
int matchword(const char *text);
void unknown(void);
%}

%%
[ \r]           ;
0               {yylval = (int)build_number(0); return NUMBER;}
[1-9][0-9]*     {yylval = (int)build_number(atoi(yytext)); return NUMBER;}
[A-Za-z]+       {return matchword(yytext);}
\n              {return EOL_;}
\.              {return C_;}
!               {return C_;}
\?              {return Q_;}
.               {unknown(); return UNKNOWN;}
%%
int yywrap()
{
    return 1;
}

int matchword(const char *text)
{
    int i;
#define match(x) if (steqi(text, #x)) return x;
    match(PUT); match(DESCRIBE);
    if (steqi(text, "EXAMINE")) return DESCRIBE;
    match(QUIT);
    match(A); match(THE); match(ANOTHER);
    match(ON);
    match(BLOCK); match(TABLE);
    match(RED); match(GREEN); match(BLUE);
    match(YOU); match(YOURSELF);
    match(IT); match (ITSELF);
    match(WHY); match(DID);
    match(EVERYTHING);

    printf("I DIDN'T UNDERSTAND THE WORD \"");
    for (i=0; text[i] != '\0'; ++i)
      printf("%c", toupper((unsigned char)text[i]));
    puts("\".\n");
    puts("THE ONLY WORDS I KNOW ARE");
    puts("  PUT DESCRIBE EXAMINE");
    puts("  BLOCK TABLE EVERYTHING RED GREEN BLUE");
    puts("  A THE ANOTHER          ON");
    puts("  YOU YOURSELF           IT ITSELF");
    puts("  WHY DID                QUIT");

    return UNKNOWN;
}

void unknown(void)
{
    puts("I DIDN'T UNDERSTAND SOMETHING IN THAT LINE.");
    puts("THE ONLY WORDS I KNOW ARE");
    puts("  PUT DESCRIBE EXAMINE");
    puts("  BLOCK TABLE CUBE PYRAMID EVERYTHING");
    puts("  A THE ANOTHER          ON");
    puts("  YOU YOURSELF           IT ITSELF");
    puts("  WHY DID                QUIT");
}

int steqi(const char *p, const char *q)
{
    int i;
    for (i=0; p[i]; ++i) {
        if (tolower(p[i]) != tolower(q[i]))
          return 0;
    }
    return (p[i] == q[i]);
}