%{
#include <stdio.h>
#include <ctype.h>
#include "ick.h"
#include "y.tab.h"
#include "lose.h"

#ifdef MAIN
YYSTYPE	yylval;
#endif /* MAIN */

char *textlines[MAXLINES];
int politesse = 0;

static char linebuf[YYLMAX];
static char *lineptr = linebuf;

bool re_send_token = FALSE;

int lexer()
{
    static int tok = BADCHAR;

    if(re_send_token) {
	re_send_token = FALSE;
	return tok;
    }
    else {
	return (tok = yylex());
    }
}

int myatoi(text)
char *text;
{
#define MAXTEXT 100
    static char buf[MAXTEXT];
    register int i;

    for(buf[i = 0] = '\0';*text && i < MAXTEXT;text++) {
	if(isdigit(*text)) {
	    buf[i++] = *text;
	}
    }
    buf[i] = '\0';
    return atoi(buf);
}
	
/*
 * The spectacular ugliness of INTERCAL syntax requires that the lexical
 * analyzer have two levels. One, embedded in the getc() function, handles
 * logical-line continuation and the ! abbrev, and stashes each logical
 * line away in a buffer accessible to the code generator (this is necessary
 * for the * construct to be interpreted correctly). The upper level is
 * generated by lex(1) and does normal tokenizing.
 */

#undef getc
int getc(fp)
FILE	*fp;
{
    static bool bangflag = FALSE;
    static bool backflag = FALSE;

    if (bangflag)
    {
	bangflag = FALSE;
	/*	*lineptr++ = '!'; */
	return('.');
    }
    else if (backflag)	/* converting ctrl-H (backspace) to two chars "^H" */
    {
	backflag = FALSE;
	/*	*lineptr++ = '\010'; */
	return('H');
    }
    else
    {
	int c = fgetc(fp);

	if (feof(yyin))
	{
	    *lineptr = '\0';
	    return(EOF);
	}
#ifdef BACKSLASH_CONTINUATION
	else if (c == '\\')
	{
	    do {
		c = fgetc(fp);
	    } while
		(c != '\\' && isspace(c));
	}
#endif
	if (c == '!')
	{
	    *lineptr++ = '!';
	    bangflag = TRUE;
	    return(c = '\'');
	}
	else if (c == '\010')	/* convert ctrl-H (backspace) to
				   two chars "^" and "H" so lex can take it */
	{
	    *lineptr++ = '\010';
	    backflag = TRUE;
	    return(c = '^');
	}
	else if (c == '\n')
	{
	    extern char *strcpy(),*malloc();

	    *lineptr = '\0';
	    lineptr = linebuf;
	    textlines[yylineno] = strcpy(malloc(1+strlen(linebuf)),linebuf);
	    return('\n');
	}
	else
	{
	    if (islower(c))
		c = toupper(c);
	    return(*lineptr++ = c);
	}
    }
}

%}

W	[\ \t\n]*
D	[0-9][\ \t\n0-9]*

%%

{D}		{yylval.numval = myatoi(yytext); return(NUMBER);}
\.		{return(ONESPOT);}
\:		{return(TWOSPOT);}
\,		{return(TAIL);}
\;		{return(HYBRID);}
\#		{return(MESH);}

"C^H/"	|
\$		{return(MINGLE);}
\~		{return(SELECT);}

\&		{yylval.numval = AND; return(UNARY);}
V		{yylval.numval = OR; return(UNARY);}
"V^H-"		|
\?		{yylval.numval = XOR; return(UNARY);}
\^		{yylval.numval = FIN; return(UNARY);}
@		{yylval.numval = WHIRL; return(UNARY);}
[2-5]{W}@	{yylval.numval = WHIRL + myatoi(yytext) - 1; return(UNARY);}

\'		{return(SPARK);}
\"		{return(EARS);}

\({W}{D}\)	{yylval.numval = myatoi(yytext); return(LABEL);}

DO		{return(DO);}
PLEASE		{politesse++; return(DO);}
DO{W}PLEASE	{politesse++; return(DO);}
PLEASE{W}DO	{politesse++; return(DO);}
NOT		{return(NOT);}
N\'T		{return(NOT);}

\%{W}{D}	{yylval.numval = myatoi(yytext);
                 if (yylval.numval && yylval.numval < 100)
		   return(OHOHSEVEN);
		 else
		   lose(E017, yylineno, (char *)NULL);}
SUB		{return(SUB);}
BY		{return(BY);}

\<-		{return(GETS);}
CALCULATING	{yylval.numval = GETS; return(GERUND);}

NEXT		{return(NEXT);}
NEXTING		{yylval.numval = NEXT; return(GERUND);}
FORGET		{return(FORGET);}
FORGETTING	{yylval.numval = FORGET; return(GERUND);}
RESUME		{return(RESUME);}
RESUMING	{yylval.numval = RESUME; return(GERUND);}
STASH		{return(STASH);}
STASHING	{yylval.numval = STASH; return(GERUND);}
RETRIEVE	{return(RETRIEVE);}
RETRIEVING	{yylval.numval = RETRIEVE; return(GERUND);}
IGNORE		{return(IGNORE);}
IGNORING	{yylval.numval = IGNORE; return(GERUND);}
REMEMBER	{return(REMEMBER);}
REMEMBERING	{yylval.numval = REMEMBER; return(GERUND);}
ABSTAIN{W}FROM	{return(ABSTAIN);}
ABSTAINING	{yylval.numval = ABSTAIN; return(GERUND);}
REINSTATE	{return(REINSTATE);}
REINSTATING	{yylval.numval = REINSTATE; return(GERUND);}
\+		{return(INTERSECTION);}
GIVE{W}UP	{return(GIVE_UP);}
READ{W}OUT	{return(READ_OUT);}
WRITE{W}IN	{return(WRITE_IN);}
COME{W}FROM	{return(COME_FROM);}
COMING{W}FROM	{yylval.numval = COME_FROM; return(GERUND);}

{W}     	;
.		{yylval.numval = yytext[0]; return(BADCHAR);}


%%

#ifdef MAIN
int yyerror()
{
    (void) printf("lextest: lexer error.\n");
}

main()
{
	int	t;

	while ((t = yylex()) > 0)
	{
		(void) printf("%03d %09d\n", t, yylval.numval);
		yylval.numval = 0;
	}
}
#endif /* MAIN */

static int yywrap()
{
    return(EOF);
}

