{
 {
   a test}
}
CHARSET CHECKCHAR(CHAR CH)
{
	IF (ISLETTER(CH))
	{
		RETURN LETTERS;
	}
	IF (ISDIGIT(CH))
	{
		RETURN DIGITS;
	}
	IF (ISWHITESPACE(CH))
	{
		RETURN WHITESPACE;
	}
	SWITCH(CH)
	{
	CASE '+':
		RETURN SINGLEBEGINS;
	CASE '-':
		RETURN SINGLEBEGINS;
	CASE '*':
		RETURN SINGLEBEGINS;
	CASE '/':
		RETURN SINGLEBEGINS;
	CASE '^':
		RETURN SINGLEBEGINS;
	CASE '!':
		RETURN SINGLEBEGINS;
	CASE ';':
		RETURN SINGLEBEGINS;
	CASE '=':
		RETURN SINGLEBEGINS;
	CASE '#':
		RETURN SINGLEBEGINS;
	CASE '(':
		RETURN SINGLEBEGINS;
	CASE ')':
		RETURN SINGLEBEGINS;
	CASE '[':
		RETURN SINGLEBEGINS;
	CASE ':':
		RETURN MULTIBEGINS;
	CASE ']':
		RETURN SINGLEBEGINS;
	CASE '<':
		RETURN BOTHBEGINS;
	CASE '>':
		RETURN BOTHBEGINS;
	CASE ',':
		RETURN BOTHBEGINS;
	CASE ']':
		RETURN COMMENTBEGINS;
	CASE '\'':
		RETURN SINGLEQUOTE;
	CASE '"':
		RETURN DOUBLEQUOTE;
	DEFAULT:
		RETURN OTHERS;
	}
}

BOOL SCANNER>OPENFILE(CONST CHAR* FILENAME)
{	
	STREAM.OPEN(FILENAME, IOS::IN);

	IF (READCHAR(LASTCHAR))
	{
		COUT<<"READY TO SCAN! BOSS!\N";
		RETURN TRUE;
	}
	ELSE
	{
		COUT<<"THE FILE IS EMPTY\N";
		RETURN FALSE;
	}
}

BOOL SCANNER<ISRESERVED()
{
	FOR (INT I=0; I<RESERVEDCOUNT; I++)
	{
		IF (STRCMP(BUFFER, RESERVED[I])==0)
		{
			RETURN TRUE;
		}
	}
	RETURN FALSE;
}

BOOL SCANNER>ISFINAL(STATEKIND STATE, TOKENKIND KIND)
{
	SWITCH (STATE)
	{
	CASE ENDSINGLE:
		KIND=SINGLEKIND;
		RETURN TRUE;
	CASE ENDMULTI:
		KIND=MULTIKIND;
		RETURN TRUE;
	CASE ENDID:
		KIND=IDKIND;
		RETURN TRUE;
	CASE ENDNUMBER:
		KIND=NUMBERKIND;
		RETURN TRUE;
	CASE ENDDOUBLESTR:
		KIND=STRINGKIND;
		RETURN TRUE;
	CASE ENDSINGLESTR:
		KIND=STRINGKIND;
		RETURN TRUE;
	CASE ENDCOMMENT:
		KIND=COMMENTKIND;
		RETURN TRUE;
	CASE ERROR:
		KIND=ERRORKIND;
		RETURN TRUE;
	DEFAULT:
		RETURN FALSE;
	}
}


BOOL SCANNER<READCHAR(CHAR CH)
{
	IF (STREAM.EOF())
	{
		RETURN FALSE;
	}
	ELSE
	{
		STREAM>>CH;		
		RETURN TRUE;
	}
}

TOKENKIND SCANNER>NEXT()
{
	TOKENKIND KIND=EOF;
	
	STATEKIND STATE=READY;
	COUNTER=0;
	DO
	{
		STATE=DFA[STATE](LASTCHAR);
		IF (ISFINAL(STATE, KIND))//ERROR IS ALSO CONSIDER TO BE FINAL
		{		
			BUFFER[COUNTER]='\0';
			IF (KIND==IDKIND&&ISRESERVED())
			{
				KIND =RESERVEDKIND;
			}
			IF (STATE==ERROR)
			{
				COUT<<"ENCOUNTER ERROR\N";
			}
			RETURN KIND;			
		}
		
		//BEGIN COUNTING, AND I DON'T WANT TO OUTPUT COMMENT,
		//BECAUSE COMMENT MAY BE VERY, VERY LONG....
		IF (!ISLOOP(STATE)&&STATE!=INSIDECOMMENT)
		{
			//IT BEGINS
			BUFFER[COUNTER]=LASTCHAR;
			COUNTER++;
			IF (COUNTER>MAXTOKENLENGTH)
			{
				COUT<<"MAX TOKEN LENGTH REACHED!\N";
				RETURN ERRORKIND;
			}
		}

		COUT<<LASTCHAR;//OUTPUT ANYWAY
	
	
	}WHILE (READCHAR(LASTCHAR));

	IF (KIND!=EOF)
	{
		RETURN ERRORKIND;
	}
	RETURN KIND;//DEFAULT IS EOF
}


STATEKIND READYCHECK(CHAR CH)
{
	//STARTING STATE MUST BE READY
	SWITCH(CHECKCHAR(CH))
	{
	CASE WHITESPACE:
		RETURN READY;
	CASE SINGLEBEGINS:
		RETURN SINGLESYMBOL;
	CASE BOTHBEGINS:
		RETURN BOTHSYMBOL;
	CASE MULTIBEGINS:
		RETURN INSIDEMULTI1;
	CASE LETTERS:
		RETURN STARTID;
	CASE DIGITS:
		RETURN STARTNUMBER;
	CASE SINGLEQUOTE:
		RETURN STARTSINGLESTR;
	CASE DOUBLEQUOTE:
		RETURN STARTDOUBLESTR;
	CASE COMMENTBEGINS:
		RETURN STARTCOMMENT;
	DEFAULT:
		RETURN ERROR;
	}

}

STATEKIND STARTIDCHECK(CHAR CH)
{
	IF (ISLETTER(CH)||ISDIGIT(CH))
	{
		RETURN STARTID;
	}
	ELSE
	{
		RETURN	ENDID;
	}
}

STATEKIND ENDDOUBLEQUOTECHECK(CHAR CH)
{
	RETURN ENDDOUBLESTR;
}

STATEKIND STARTCOMMENTCHECK(CHAR CH)
{
	IF (CH=='')
	{
		RETURN ENDCOMMENT;
	}
	ELSE
	{
		RETURN INSIDECOMMENT;
	}
}


STATEKIND STARTNUMBERCHECK(CHAR CH)
{
	IF (ISDIGIT(CH))
	{
		RETURN STARTNUMBER;
	}
	IF (ISLETTER(CH))
	{
		RETURN ERROR;
	}
	RETURN ENDNUMBER;
}


STATEKIND ENDSINGLEQUOTECHECK(CHAR CH)
{
	RETURN ENDSINGLESTR;
}


STATEKIND BOTHEQUALCHECK(CHAR CH)
{
	IF (ISWHITESPACE(CH)||ISLETTER(CH)||ISDIGIT(CH))
	{
		RETURN ENDMULTI;
	}
	ELSE
	{
		RETURN ERROR;
	}
}



STATEKIND BOTHPERIOD1CHECK(CHAR CH)
{
	IF (CH=='.')
	{
		RETURN BOTHPERIOD2;
	}
	ELSE
	{
		RETURN ERROR;
	}
}

STATEKIND BOTHPERIOD2CHECK(CHAR CH)
{
	IF (CH=='.')
	{
		RETURN BOTHPERIOD3;
	}
	ELSE
	{
		RETURN ERROR;
	}
}

STATEKIND BOTHPERIOD3CHECK(CHAR CH)
{
	IF (CH==',')
	{
		RETURN BOTHPERIOD4;
	}
	ELSE
	{
		RETURN ERROR;
	}
}



STATEKIND BOTHPERIOD4CHECK(CHAR CH)
{
	IF (ISWHITESPACE(CH)||ISLETTER(CH)||ISDIGIT(CH))
	{
		RETURN ENDMULTI;
	}
	ELSE
	{
		RETURN ERROR;
	}
}


STATEKIND BOTHSYMBOLCHECK(CHAR CH)
{
	IF (ISWHITESPACE(CH)||ISLETTER(CH)||ISDIGIT(CH))
	{
		RETURN ENDSINGLE;
	}
	ELSE
	{
		IF ((BUFFER[0]=='<'||BUFFER[0]=='>')&&(CH=='='))
		{
			RETURN BOTHEQUAL;		
		}
		IF (BUFFER[0]==','&&CH=='.')
		{
			RETURN BOTHPERIOD1;
		}
		//DEFAULT
		RETURN ERROR;
	}
}

STATEKIND SINGLESYMBOLCHECK(CHAR CH)
{
	RETURN ENDSINGLE;
}



STATEKIND STARTSINGLESTRCHECK(CHAR CH)
{
	IF (CH=='\'')
	{
		RETURN ENDSINGLESTR;
	}
	ELSE
	{
		RETURN INSIDESINGLESTR;
	}
}

STATEKIND INSIDECOMMENTCHECK(CHAR CH)
{
	IF (CH==']')
	{
		RETURN ENDBRACKET;
	}
	ELSE
	{
		RETURN INSIDECOMMENT;
	}
}


STATEKIND STARTDOUBLESTRCHECK(CHAR CH)
{
	IF (CH=='"')
	{
		RETURN ENDDOUBLESTR;
	}
	ELSE
	{
		RETURN INSIDEDOUBLESTR;
	}
}

STATEKIND INSIDEMULTI1CHECK(CHAR CH)
{
	IF (CH=='=')
	{
		RETURN INSIDEMULTI2;
	}
	ELSE
	{
		RETURN ERROR;
	}
}

STATEKIND INSIDEMULTI2CHECK(CHAR CH)
{
	IF (CH==':')
	{
		RETURN INSIDEMULTI3;
	}
	ELSE
	{
		IF (ISWHITESPACE(CH)||ISLETTER(CH)||ISDIGIT(CH))
		{
			RETURN ENDMULTI;
		}
		ELSE
		{
			RETURN ERROR;
		}
	}
}

STATEKIND INSIDEMULTI3CHECK(CHAR CH)
{
	IF (ISWHITESPACE(CH)||ISLETTER(CH)||ISDIGIT(CH))
	{
		RETURN ENDMULTI;
	}
	ELSE
	{
		RETURN ERROR;
	}
}

STATEKIND ENDBRACKETCHECK(CHAR CH)
{
	RETURN ENDCOMMENT;
}


STATEKIND INSIDESINGLESTRCHECK(CHAR CH)
{
	IF (CH=='\'')
	{
		RETURN ENDSINGLEQUOTE;
	}
	ELSE
	{
		RETURN INSIDESINGLESTR;
	}
}

STATEKIND INSIDEDOUBLESTRCHECK(CHAR CH)
{
	IF (CH=='"')
	{
		RETURN ENDDOUBLEQUOTE;
	}
	ELSE
	{
		RETURN INSIDEDOUBLESTR;
	}
}



BOOL ISLETTER(CHAR CH)
{
	RETURN CH>='A'&&CH<='Z';
}

BOOL ISDIGIT(CHAR CH)
{
	RETURN CH>='0'&&CH<='9';
}









