%{

#include "stdafx.h"
#include "token.h"
#include "ytab.h"
#include "helpdlg.h"

#pragma warning(disable : 4996)

#define	YY_NO_UNPUT
#undef	YY_INPUT
#define	YY_INPUT(b, r, s) (r=((*b = my_input()) != EOS))
#define	EOS	'\0'

#ifdef  DEBUG
#define DebOut(s)     {	MessageBox(NULL, #s , "Debug", MB_OK); return s;	}
#else
#define DebOut(s)	{	return s;			}
#endif

#undef	input
#undef	unput

static	char	*input_buffer = "";
static	int	input_index = 0;

static	int	my_input()
{
	return (input_buffer [ input_index ] != EOS) ?  input_buffer [ input_index++ ] : EOS;
}

static	void	unput(int ch)
{
	input_index--;
}

extern YYSTYPE yylval;

%}

%%

#.*			;
"//".*		;
";".*		;
[ \t]		;
"="		DebOut('=');
"<-"	DebOut('=');
">"		DebOut('>');
"<"		DebOut('<');
">="	DebOut(ELARGE);
"=>"	DebOut(ELARGE);
"<="	DebOut(ESMALL);
"=<"	DebOut(ESMALL);
"=="	DebOut(EEQUAL);
"==="	DebOut(EEEQUAL);
"!="	DebOut(NEQUAL);
"<>"	DebOut(NEQUAL);
"><"	DebOut(NEQUAL);
"!=="	DebOut(NEEQUAL);
"|"		DebOut('|');
"&"		DebOut('&');
"~"		DebOut('~');
"+"		DebOut('+');
"-"		DebOut('-');
"*"		DebOut('*');
"/"		DebOut('/');
"%"		DebOut('%');
"^"		DebOut('^');
">>"	DebOut(RSHIFT);
"<<"	DebOut(LSHIFT);
"|="	DebOut(E_OROP);
"&="	DebOut(E_ANDOP);
"+="	DebOut(E_ADDOP);
"-="	DebOut(E_SUBOP);
"*="	DebOut(E_MULOP);
"/="	DebOut(E_DIVOP);
"%="	DebOut(E_MODOP);
"^="	DebOut(E_XOROP);
">>="	DebOut(E_RSHIFT);
"<<="	DebOut(E_LSHIFT);
"++"	DebOut(INC);
"--"	DebOut(DEC);
"&&"	DebOut(ANDAND);
"||"	DebOut(OROR);
"("		DebOut('(');
")"		DebOut(')');
"["		DebOut('[');
"]"		DebOut(']');
"?"		DebOut('?');
":"		DebOut(':');
"!"		DebOut('!');
","		DebOut(',');
"."		DebOut('.');
[iI][fF]							DebOut(IF);
[gG][oO][tT][oO]					DebOut(GOTO);
[gG][oO][sS][uU][bB]				DebOut(GOSUB);
[rR][eE][tT][uU][rR][nN]			DebOut(RETURN);
[eE][xX][iI][tT]					DebOut(EXIT);
[aA][bB][oO][rR][tT]				DebOut(ABORT);
[eE][lL][sS][eE]					DebOut(ELSE);
[aA][rR][rR][aA][yY]				DebOut(ARRAY);
[rR][eE][sS][iI][zZ][eE]			DebOut(RESIZE);
[wW][hH][iI][lL][eE]				DebOut(WHILE);
[Ff][Oo][Rr]						DebOut(FOR);
[Ff]0[Rr]							DebOut(F0R);

"\n"	DebOut(EOL);

0[xX][0-9a-fA-F]+	{
			char	*p = yytext + strlen (yytext);
			yylval.dval = (int)strtoul(yytext + 2, &p, 16);
			DebOut(NUMBER);
		}
0[bB][01]+	{
			char	*p = yytext + strlen (yytext);
			yylval.dval = (int)strtoul(yytext + 2, &p, 2);
			DebOut(NUMBER);
		}
0|([1-9][0-9]*)	{
			yylval.dval = atou(yytext);
			DebOut(NUMBER);
		}

[A-Za-z_][A-Za-z0-9_]* {
			yylval.text = RM(_strdup(yytext));
			DebOut(NAME);
		}
[A-Za-z_][A-Za-z0-9_]*\$ {
			yylval.text = RM(_strdup(yytext));
			DebOut(NAME_D);
		}

@\"[^"]*[\"]	{
			yylval.text = RM(deldc_at(yytext));
			DebOut(STRING);
		}

@\'[^']*[\']	{
			yylval.text = RM(deldc_at(yytext));
			DebOut(STRING);
		}

\"([^"\\]+|\\.)*[\"] {
			yylval.text = RM(deldc(yytext));
			DebOut(STRING);
		}

\'([^'\\]+|\\.)*[\'] {
			yylval.text = RM(deldc(yytext));
			DebOut(STRING);
		}

.		;
%%

void	set_input_buffer (const char *ap)
{
	input_buffer = (char *)ap;
	input_index = 0;
}

char	*deldc(const char *text) // 文字の両端に付いている " または ' を取り除く(エスケープシーケンスの解析あり)
{
	// 文字列の両端についているダブル/シングルコーテーションを取り除く
    char *dtext = (char *)malloc(strlen(text));
    size_t i, n;

	for(i=0,n=1 ; text[n] != 0 && text[n] != text[0] ; i++,n++) {
		if (isKanji1(text, (int)n)) { // 漢字の第2バイト目としての \\ だった場合は、ふつうにそのまま処理
			dtext[i++] = text[n++];
			if (text[i] == 0) {
				break;
			}
		}
		else if (text[n] == '\\') {
			// エスケープシーケンス
			switch(text[n+1]) {
				case 'n':
				case 'N':
					dtext[i] = '\n';
					n++;
					continue;

				case 'x':
				case 'X':
					if (text[n+2] != 0 && text[n+3] != 0 && text[n+2] != text[0] && text[n+3] != text[0]) {
						char s[3];

						s[0] = text[n+2];
						s[1] = text[n+3];
						s[2] = 0;
						dtext[i] = (char)strtoul(&text[n+2],NULL,16);
						n+=2;
						continue;
					}

				case '\\':
					dtext[i] = '\\';
					n++;
					continue;

				case 't':
				case 'T':
					dtext[i] = '\t';
					n++;
					continue;

				case 'r':
				case 'R':
					dtext[i] = '\r';
					n++;
					continue;

				case 'a':
				case 'A':
					dtext[i] = '\a';
					n++;
					continue;

				case 'b':
				case 'B':
					dtext[i] = '\b';
					n++;
					continue;

				case 'v':
				case 'V':
					dtext[i] = '\v';
					n++;
					continue;

				case 'f':
				case 'F':
					dtext[i] = '\f';
					n++;
					continue;

				case '\'':
					dtext[i] = '\'';
					n++;
					continue;

				case '"':
					dtext[i] = '"';
					n++;
					continue;
			}	
		}
		dtext[i] = text[n];
	}
	
	dtext[i] = 0;
	return dtext;
}

char	*deldc_at(const char *text) // (@文字列版)文字の両端に付いている " または ' を取り除く(エスケープシーケンスの解析なし)
{
	// 文字列の両端についているダブル/シングルコーテーションを取り除く
    char *dtext = (char *)calloc(strlen(text)-2, 1);
	return strncpy(dtext, text+2, strlen(text)-3);
	// 注意:strncpyはlstrcpynに単純に置き換えられない(lstrcpynでは第3引数にnull文字分も長さも入れるため)
}
