%{
/*{{定型コード: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;
}

%token			T_DEF
%token			T_END
%token			T_JOIN		//{{2017/06/20追加:join命令を追加しました。}}
%token			T_HIDE		//{{2017/05/23追加:hide命令を追加しました。}}
%token			T_REPEAT
%token			T_WAIT
%token			T_CALL
%token			T_FORK		//{{2017/05/13追加:fork命令を追加しました。}}
%token			T_ACT
%token			T_FLUSH
%token			T_ON
%token			T_GOTO
%token			T_LOCK
%token			T_UNLOCK
%token			T_SET
%token			T_CLR
%token	<v_num>		T_NUM
%token	<v_dbl>		T_DBL
%token	<v_str>		T_LAB
%token	<v_str>		T_STR
%token			T_EOL

%type	<v_num>		int_arg
%type	<v_num>		expr
%type	<v_dbl>		edbl
%type	<v_str>		estr

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

%%

all
		: /* empty */
		| all line
		;
line
		:       T_EOL
		| inst  T_EOL
		| error T_EOL					{ yyerrok; }		//全てのシンタクスエラーを報告するために継続する。
		;
inst
		: T_DEF T_LAB					{ inst_def($2); }
		|       T_LAB					{ inst_def($1); }	//省略記法
		//
		| T_END						{ inst_end(); }
		//
		| T_JOIN					{ inst_join(); }	//{{2017/06/20追加:join命令を追加しました。}}
		//
		| T_HIDE					{ inst_hide(); }	//{{2017/05/23追加:hide命令を追加しました。}}
		//
		| T_REPEAT int_arg				{ inst_repeat($2); }
		| T_REPEAT					{ inst_repeat(255); }	//無限
		//
		| T_WAIT int_arg				{ inst_wait($2); }
		//
		| T_CALL T_LAB					{ inst_call($2); }
		//
		| T_FORK					{ inst_fork(); }	//{{2017/05/13追加:fork命令を追加しました。}}
		//
		| T_ACT int_arg					{ inst_act(0, $2); }
		| T_ACT int_arg T_FLUSH				{ inst_act(1, $2); }
	    //{{2016/09/10追加:actの引数として、演出番号の直接指定だけでなく、演出名も指定出来るようにしました。演出名に対する番号は、当ツールが自動的に割り振ります。
		| T_ACT T_LAB					{ inst_act_lab(0, $2); }
		| T_ACT T_LAB T_FLUSH				{ inst_act_lab(1, $2); }
	    //}}2016/09/10追加:actの引数として、演出番号の直接指定だけでなく、演出名も指定出来るようにしました。演出名に対する番号は、当ツールが自動的に割り振ります。
	    //{{2017/03/02追加:actの引数として、演出文字列も指定出来るようにしました。演出番号は当ツールが自動的に割り振り、演出番号と演出文字列の対応はレジストリスクリプトとして出力します。
		| T_ACT estr					{ inst_act_str(0, $2); }
		| T_ACT estr T_FLUSH				{ inst_act_str(1, $2); }
	    //}}2017/03/02追加:actの引数として、演出文字列も指定出来るようにしました。演出番号は当ツールが自動的に割り振り、演出番号と演出文字列の対応はレジストリスクリプトとして出力します。
		//
		| T_ON T_LAB          goto T_LAB		{ inst_on(0, $2, $4,  0); }
		| T_ON T_LAB          goto T_LAB lock int_arg	{ inst_on(0, $2, $4, $6); }
		| T_ON T_LAB T_UNLOCK goto T_LAB		{ inst_on(1, $2, $5,  0); }
		| T_ON T_LAB T_UNLOCK goto T_LAB lock int_arg	{ inst_on(1, $2, $5, $7); }
		;
goto
		: /* empty */
		| T_GOTO
		;
lock
		: /* empty */
		| T_LOCK
		;
		/*--------------------------------------------*/
int_arg
		: expr						/* use default action */
		| edbl						{ $$ =  cast_dbl_to_int($1); }
		;
expr
		: T_NUM
		| '(' 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); }
		;

%%
