%{
/*{{定型コード:y.tab.y(宣言部,%{〜%}内)======================================*/
#ifdef  PIECE
#include "app.h"
#else //PIECE
#include "winapp.h"
#pragma warning(default: 4131)	//{{2016/03/01追加:clipstd.hにてC4131の警告レベルを引き上げましたが、Bison/Flexの生成コードには旧スタイルの宣言が使われているので、Bison/Flexの生成コードのみ警告レベルを元に戻しました。}}
#endif//PIECE
/* パーサースタックの初期値を定義します。
 * sizeof(YYSTYPE)*YYINITDEPTH) がスタック上に確保されます。
 * デフォルトでは200と定義されており、P/ECEには大きすぎます。
 * P/ECEに適切な、小さなサイズ(16)に、再定義しました。
 * パーサースタックが不足した場合は、自動的に拡張されるので、問題ありません。
 */
#define YYINITDEPTH 16
///* エラー報告関数を定義します。 */	→{{2015/03/06:'-e'オプション対応のためにwinapp.cへ移動しました。}}
//void yyerror(const char* fmt, ...) {
//  fprintf(stderr, "### error at line %d : ", yylineno);
//  { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); }
//  fputc('\n', stderr); }
/*}}定型コード:y.tab.y(宣言部,%{〜%}内)======================================*/
%}

%union {
	int		v_num;
	double		v_dbl;
	char*		v_str;
	ST_Tex*		v_tex;
	ST_TexHdr*	v_texHdr;
	ST_TexBody*	v_texBody;
	ST_Spr*		v_spr;
	ST_Attr*	v_attr;			//{{2017/03/26追加:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。}}
	ST_AttrList*	v_attrList;		//{{2017/03/26追加:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。}}
}

%token	<v_num>		T_NUM
%token	<v_dbl>		T_DBL
%token	<v_str>		T_LAB
%token	<v_str>		T_STR
%token			T_EOL
%token			T_END
%token			T_GRID
%token			T_RESOURCE
//%token		T_LOOP			//{{2017/03/26削除:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。}}

%type	<v_num>		int_arg
%type	<v_num>		expr
%type	<v_dbl>		edbl
%type	<v_str>		estr
%type	<v_num>		x
%type	<v_num>		y
%type	<v_num>		p
%type	<v_str>		param
%type	<v_tex>		tex
%type	<v_texHdr>	texRow
%type	<v_texHdr>	texHdr
%type	<v_texBody>	texBody
%type	<v_spr>		spr
%type	<v_attr>	attr			//{{2017/03/26追加:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。}}
%type	<v_attrList>	attrList		//{{2017/03/26追加:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。}}

%left			'|'
%left			'^'
%left			'&'
%left			T_SHL T_SHR
%left			'+' '-'
%left			'*' '/' '%'
%nonassoc		'~' T_UPL T_UMI T_CAST_INT T_CAST_DBL

%%

all
		: pre_blank
		| all tex						{ addTex($2); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
		| all error										//全てのシンタクスエラーを報告するために継続する。
		;
pre_blank
		: /* empty */
		| pre_blank T_EOL
		;
eols
		:      T_EOL
		| eols T_EOL
		;
end
		: T_END eols
		;
int_arg
		: expr							/* use default action */
		| edbl							{ $$ =  cast_dbl_to_int($1); }
		;
expr
		: T_NUM							/* use default action */
		| '(' expr ')'						{ $$ =  $2; }
		| T_CAST_INT expr					{ $$ =  $2; }
		| T_CAST_INT edbl					{ $$ =  $2; }
		| '+' expr %prec T_UPL					{ $$ =  $2; }
		| '-' expr %prec T_UMI					{ $$ = -$2; }
		| '~' expr						{ $$ = ~$2; }
		| expr '+' expr						{ $$ = $1 + $3; }
		| expr '-' expr						{ $$ = $1 - $3; }
		| expr '*' expr						{ $$ = $1 * $3; }
		| expr '/' expr						{ if(!$3) { yyerror("division or modulo by zero"); yynerrs++; YYERROR; } $$ = $1 / $3; }
		| expr '%' expr						{ if(!$3) { yyerror("division or modulo by zero"); yynerrs++; YYERROR; } $$ = $1 % $3; }
		| expr '&' expr						{ $$ = $1 & $3; }
		| expr '^' expr						{ $$ = $1 ^ $3; }
		| expr '|' expr						{ $$ = $1 | $3; }
		| expr T_SHL expr					{ if((unsigned)$3 >= 32) { yyerror("shift count >= 32"); yynerrs++; YYERROR; } $$ = $1 << $3; }
		| expr T_SHR expr					{ if((unsigned)$3 >= 32) { yyerror("shift count >= 32"); yynerrs++; YYERROR; } $$ = $1 >> $3; }
		;
edbl
		: T_DBL
		| '(' edbl ')'						{ $$ =  $2; }
		| T_CAST_DBL expr					{ $$ =  $2; }
		| T_CAST_DBL edbl					{ $$ =  $2; }
		| '+' edbl %prec T_UPL					{ $$ =  $2; }
		| '-' edbl %prec T_UMI					{ $$ = -$2; }
		| edbl '+' edbl						{ $$ = $1 + $3; }
		| edbl '+' expr						{ $$ = $1 + $3; }
		| expr '+' edbl						{ $$ = $1 + $3; }
		| edbl '-' edbl						{ $$ = $1 - $3; }
		| edbl '-' expr						{ $$ = $1 - $3; }
		| expr '-' edbl						{ $$ = $1 - $3; }
		| edbl '*' edbl						{ $$ = $1 * $3; }
		| edbl '*' expr						{ $$ = $1 * $3; }
		| expr '*' edbl						{ $$ = $1 * $3; }
		| edbl '/' edbl						{ if(!$3) { yyerror("division or modulo by zero"); yynerrs++; YYERROR; } $$ = $1 / $3; }
		| edbl '/' expr						{ if(!$3) { yyerror("division or modulo by zero"); yynerrs++; YYERROR; } $$ = $1 / $3; }
		| expr '/' edbl						{ if(!$3) { yyerror("division or modulo by zero"); yynerrs++; YYERROR; } $$ = $1 / $3; }
		;
estr
		: T_STR
		| '(' estr ')'						{ $$ = $2; }
		| estr '+' estr						{ $$ = strconcat($1, $3, NULL); }
		;
		/*--------------------------------------------*/
x
		: int_arg ':' int_arg					{ $$ = ($1 * grid_w) + $3; }	//グリッド単位:ピクセル単位
		| int_arg						{ $$ = ($1 * grid_w)     ; }	//グリッド単位
		|         ':' int_arg					{ $$ =                 $2; }	//            :ピクセル単位
		;
		/*- - - - - - - - - - - - - - - - - - - - - - */
y
		: int_arg ':' int_arg					{ $$ = ($1 * grid_h) + $3; }	//グリッド単位:ピクセル単位
		| int_arg						{ $$ = ($1 * grid_h)     ; }	//グリッド単位
		|         ':' int_arg					{ $$ =                 $2; }	//            :ピクセル単位
		;
		/*- - - - - - - - - - - - - - - - - - - - - - */
p
	    //{{本当はこの↓ように書きたいのだが、'%'を一つ先読みした時点では'expr%expr'と'(expr->int_arg)%'が判断出来ず、'shift/reduce conflict'が発生してしまう。
	    //	: int_arg '%'						/* use default action */	//幅,又は,高さに対するパーセンテージ%
	    //↓止むを得ず、ここだけこの↓ように引数がexprである場合とedblである場合を明示的に分けて書く事にした。これで上記の'shift/reduce conflict'が回避出来た。
		: expr '%'						/* use default action */	//幅,又は,高さに対するパーセンテージ%
		| edbl '%'						{ $$ =  cast_dbl_to_int($1); }	//幅,又は,高さに対するパーセンテージ%
	    //}}根本的な原因はパーセンテージ指定を示す記号に剰余と同じ'%'を使用したのが問題なのだが、それ以外の記号では直観的ではないのでこのままにしたい。だからパーセンテージ指定を示す記号は変えずに上記のように回避する事にした。
		;
		/*- - - - - - - - - - - - - - - - - - - - - - */
param
		: estr							/* use default action */		//<例> "DRW_CLR(1,2)|DRW_REVX"	スクリプト自体をCプリプロセッサに掛けない場合は、文字列をそのまま出力し後で展開する。
		| int_arg						{ $$ = strdup_printf("%d", $1); }	//<例>  DRW_CLR(1,2)|DRW_REVX	スクリプト自体をCプリプロセッサに掛ける場合は、スクリプトコンパイル前に数値化出来る。
		;
		/*--------------------------------------------*/
tex
		: texRow						{ if(!($$ = Tex_new($1, TexBody_new(1,1/*ダミー*/)))) { YYERROR; } }	//スプライト定義無しの場合
		| texHdr texBody end					{ if(!($$ = Tex_new($1, $2))) { YYERROR; } }				//スプライト定義有りの場合
		;
texRow
	//{{2017/03/26変更:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。
	//	: T_LAB estr                              eols		{ if(!($$ = TexHdr_new(  $1,   $2, 0, 0))) { YYERROR; } }
	//	| T_LAB estr T_RESOURCE                   eols		{ if(!($$ = TexHdr_new(  $1,   $2, 1, 0))) { YYERROR; } }						//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。
	//	| T_LAB estr            T_LOOP            eols		{ if(!($$ = TexHdr_new(  $1,   $2, 0, 1))) { YYERROR; } }																					//ループフラグはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックを再生する時に参照する。
	//	| T_LAB estr T_RESOURCE T_LOOP            eols		{ if(!($$ = TexHdr_new(  $1,   $2, 1, 1))) { YYERROR; } }						//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//ループフラグはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックを再生する時に参照する。	//┬一応resourceとloopを同時に指定出来るようにしました。実際にはresourceはP/ECE用,loopはWindows用なので同時に指定する事は無いと思います。
	//	| T_LAB estr            T_LOOP T_RESOURCE eols		{ if(!($$ = TexHdr_new(  $1,   $2, 1, 1))) { YYERROR; } }						//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//ループフラグはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックを再生する時に参照する。	//┘
	//	|       estr                              eols		{ if(!($$ = TexHdr_new(NULL,   $1, 0, 0))) { YYERROR; } }	//ファイル名からラベルを自動生成する。
	//	|       estr T_RESOURCE                   eols		{ if(!($$ = TexHdr_new(NULL,   $1, 1, 0))) { YYERROR; } }	//ファイル名からラベルを自動生成する。	//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。
	//	|       estr            T_LOOP            eols		{ if(!($$ = TexHdr_new(NULL,   $1, 0, 1))) { YYERROR; } }	//ファイル名からラベルを自動生成する。																//ループフラグはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックを再生する時に参照する。
	//	|       estr T_RESOURCE T_LOOP            eols		{ if(!($$ = TexHdr_new(NULL,   $1, 1, 1))) { YYERROR; } }	//ファイル名からラベルを自動生成する。	//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//ループフラグはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックを再生する時に参照する。	//┬一応resourceとloopを同時に指定出来るようにしました。実際にはresourceはP/ECE用,loopはWindows用なので同時に指定する事は無いと思います。
	//	|       estr            T_LOOP T_RESOURCE eols		{ if(!($$ = TexHdr_new(NULL,   $1, 1, 1))) { YYERROR; } }	//ファイル名からラベルを自動生成する。	//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//ループフラグはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックを再生する時に参照する。	//┘
	//↓2017/03/26変更:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。
		: T_LAB estr                                eols	{ if(!($$ = TexHdr_new(  $1,   $2, 0, AttrList_NewBlank()))) { YYERROR; } }
		| T_LAB estr T_RESOURCE                     eols	{ if(!($$ = TexHdr_new(  $1,   $2, 1, AttrList_NewBlank()))) { YYERROR; } }						//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。
		| T_LAB estr            attrList            eols	{ if(!($$ = TexHdr_new(  $1,   $2, 0,                  $3))) { YYERROR; } }																					//属性リストはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックのループ設定やグラフィックの描画モードを設定する時等に参照する。
		| T_LAB estr T_RESOURCE attrList            eols	{ if(!($$ = TexHdr_new(  $1,   $2, 1,                  $4))) { YYERROR; } }						//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//属性リストはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックのループ設定やグラフィックの描画モードを設定する時等に参照する。	//┬一応resourceとattrListを同時に指定出来るようにしました。実際にはresourceはP/ECE用,attrListは主にWindows用なので同時に指定する事は無いと思います。
		| T_LAB estr            attrList T_RESOURCE eols	{ if(!($$ = TexHdr_new(  $1,   $2, 1,                  $3))) { YYERROR; } }						//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//属性リストはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックのループ設定やグラフィックの描画モードを設定する時等に参照する。	//┘
		|       estr                                eols	{ if(!($$ = TexHdr_new(NULL,   $1, 0, AttrList_NewBlank()))) { YYERROR; } }	//ファイル名からラベルを自動生成する。
		|       estr T_RESOURCE                     eols	{ if(!($$ = TexHdr_new(NULL,   $1, 1, AttrList_NewBlank()))) { YYERROR; } }	//ファイル名からラベルを自動生成する。	//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。
		|       estr            attrList            eols	{ if(!($$ = TexHdr_new(NULL,   $1, 0,                  $2))) { YYERROR; } }	//ファイル名からラベルを自動生成する。																//属性リストはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックのループ設定やグラフィックの描画モードを設定する時等に参照する。
		|       estr T_RESOURCE attrList            eols	{ if(!($$ = TexHdr_new(NULL,   $1, 1,                  $3))) { YYERROR; } }	//ファイル名からラベルを自動生成する。	//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//属性リストはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックのループ設定やグラフィックの描画モードを設定する時等に参照する。	//┬一応resourceとattrListを同時に指定出来るようにしました。実際にはresourceはP/ECE用,attrListは主にWindows用なので同時に指定する事は無いと思います。
		|       estr            attrList T_RESOURCE eols	{ if(!($$ = TexHdr_new(NULL,   $1, 1,                  $2))) { YYERROR; } }	//ファイル名からラベルを自動生成する。	//リソースフラグはP/ECE用のテクスチャ定義ヘッダだけに影響する。汎用の列挙定義,及び,レジストリスクリプトでは無視される。	//属性リストはレジストリスクリプトだけに出力する。Windowsでムービーグラフィックのループ設定やグラフィックの描画モードを設定する時等に参照する。	//┘
	//}}2017/03/26変更:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。
		;
texHdr
		: texRow						/* use default action */
	//{{2017/03/26変更:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。
	//	| T_LAB                eols				{ if(!($$ = TexHdr_new(  $1, NULL, 0, 0))) { YYERROR; } }	//ファイル名を別で設定する。
	//↓2017/03/26変更:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。
		| T_LAB                eols				{ if(!($$ = TexHdr_new(  $1, NULL, 0, AttrList_NewBlank()))) { YYERROR; } }	//ファイル名を別で設定する。
	//}}2017/03/26変更:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。
		;
texBody
		: T_GRID int_arg             eols			{ if(!($$ = TexBody_new($2, $2))) { YYERROR; } }	//正方形グリッドの場合
		| T_GRID int_arg ',' int_arg eols			{ if(!($$ = TexBody_new($2, $4))) { YYERROR; } }	//長方形グリッドの場合
		| texBody spr						{ if(!($$ = TexBody_addSpr($1, $2))) { YYERROR; } }
		;
		/*--------------------------------------------*/
spr
		: T_LAB x ',' y                                   eols	{ if(!($$ = Spr_new( $1, $2, $4, grid_w, grid_h,   0,   0, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標
		| T_LAB x ',' y ',' x ',' y                       eols	{ if(!($$ = Spr_new( $1, $2, $4,     $6,     $8,   0,   0, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ
		| T_LAB x ',' y ','   ','   ',' x ',' y           eols	{ if(!($$ = Spr_new( $1, $2, $4, grid_w, grid_h,  $8, $10, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標,  ,    ,X中心 ,Y中心
		| T_LAB x ',' y ',' x ',' y ',' x ',' y           eols	{ if(!($$ = Spr_new( $1, $2, $4,     $6,     $8, $10, $12, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ,X中心 ,Y中心
		| T_LAB x ',' y ','   ','   ','   ','   ',' param eols	{ if(!($$ = Spr_new( $1, $2, $4, grid_w, grid_h,   0,   0, $10))) { YYERROR; } }	//スプライト名,X座標,Y座標,  ,    ,      ,      ,パラメータ
		| T_LAB x ',' y ',' x ',' y ','   ','   ',' param eols	{ if(!($$ = Spr_new( $1, $2, $4,     $6,     $8,   0,   0, $12))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ,      ,      ,パラメータ
		| T_LAB x ',' y ','   ','   ',' x ',' y ',' param eols	{ if(!($$ = Spr_new( $1, $2, $4, grid_w, grid_h,  $8, $10, $12))) { YYERROR; } }	//スプライト名,X座標,Y座標,  ,    ,X中心 ,Y中心 ,パラメータ
		| T_LAB x ',' y ',' x ',' y ',' x ',' y ',' param eols	{ if(!($$ = Spr_new( $1, $2, $4,     $6,     $8, $10, $12, $14))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ,X中心 ,Y中心 ,パラメータ
		//
	//不要	: T_LAB x ',' y                                   eols	{ if(!($$ = Spr_newP($1, $2, $4, grid_w, grid_h,   0,   0, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標
	//不要	| T_LAB x ',' y ',' x ',' y                       eols	{ if(!($$ = Spr_newP($1, $2, $4,     $6,     $8,   0,   0, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ
		| T_LAB x ',' y ','   ','   ',' p ',' p           eols	{ if(!($$ = Spr_newP($1, $2, $4, grid_w, grid_h,  $8, $10, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標,  ,    ,X中心%,Y中心%
		| T_LAB x ',' y ',' x ',' y ',' p ',' p           eols	{ if(!($$ = Spr_newP($1, $2, $4,     $6,     $8, $10, $12, "0"))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ,X中心%,Y中心%
	//不要	| T_LAB x ',' y ','   ','   ','   ','   ',' param eols	{ if(!($$ = Spr_newP($1, $2, $4, grid_w, grid_h,   0,   0, $10))) { YYERROR; } }	//スプライト名,X座標,Y座標,  ,    ,      ,      ,パラメータ
	//不要	| T_LAB x ',' y ',' x ',' y ','   ','   ',' param eols	{ if(!($$ = Spr_newP($1, $2, $4,     $6,     $8,   0,   0, $12))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ,      ,      ,パラメータ
		| T_LAB x ',' y ','   ','   ',' p ',' p ',' param eols	{ if(!($$ = Spr_newP($1, $2, $4, grid_w, grid_h,  $8, $10, $12))) { YYERROR; } }	//スプライト名,X座標,Y座標,  ,    ,X中心%,Y中心%,パラメータ
		| T_LAB x ',' y ',' x ',' y ',' p ',' p ',' param eols	{ if(!($$ = Spr_newP($1, $2, $4,     $6,     $8, $10, $12, $14))) { YYERROR; } }	//スプライト名,X座標,Y座標,幅,高さ,X中心%,Y中心%,パラメータ
		;
		/*--------------------------------------------*/
	//{{2017/03/26追加:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。
attrList
		:          attr						{ if(!($$ = AttrList_New(        $1))) { YYERROR; } }
		| attrList attr						{ if(!($$ = AttrList_AddAttr($1, $2))) { YYERROR; } }	//同じ種類で同じ名前の属性が既に追加されていたらエラーとする。
		;
attr
		: T_LAB							{ if(!($$ = Attr_New($1, 0, (intptr_t)( 1)))) { YYERROR; } }	//省略記法。属性名だけが指定されて値が指定されなかった場合は、'=1'が指定されたのと同じと見なす事にします。主に互換性のためであり、今回(2017/03/26)変更したdTexDefC.exeで古いスクリプトをコンパイルした場合に、'loop'と書いてあっても以前と同じ結果を得る事が出来ます。互換性のためだけでなく、'loop'以外にもon/offでon時だけレジストリリプトに出力したいような属性を指定する場合にも便利に使えると思います。
		| T_LAB '=' int_arg					{ if(!($$ = Attr_New($1, 0, (intptr_t)($3)))) { YYERROR; } }
		| T_LAB '=' estr					{ if(!($$ = Attr_New($1, 1, (intptr_t)($3)))) { YYERROR; } }
		;
	//}}2017/03/26追加:テクスチャに汎用の属性リストを追加し、既存のループフラグも属性に含めました。

%%
