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

%token			T_DEF
%token			T_END
%token			T_GOTO
%token			T_CALL
%token			T_REPEAT
%token			T_SPEED
%token			T_MOVE
%token			T_WAIT
%token			T_INIT
%token			T_STOP
%token			T_REL
%token			T_ABS
%token			T_USER
%token			T_DIRECT	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_IF		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_ON		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_OFF		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_ALWAYS	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_UNTIL		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_RISE		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_FALL		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token			T_EDGE		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%token	<v_num>		T_NUM
%token	<v_dbl>		T_DBL
%token	<v_lab>		T_LAB
%token			T_EOL

%type	<v_num>		int_arg
%type	<v_num>		expr
%type	<v_dbl>		edbl
%type	<v_num>		if_cond		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
%type	<v_num>		until_cond	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/

%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_GOTO T_LAB		{ inst_goto($2); }
	//
	| T_CALL T_LAB		{ inst_call($2); }
	//
	| T_REPEAT int_arg	{ inst_repeat($2); }
	| T_REPEAT		{ inst_repeat(0); }	/* 無限 */
	//
	| T_SPEED int_arg	{ inst_speed($2); }
	//
	| T_MOVE T_INIT		{ inst_move_init(); }
	|        T_INIT		{ inst_move_init(); }	/* 省略記法 */
	//
	| T_MOVE T_REL int_arg	{ inst_move_rel($3); }
	//
	| T_MOVE T_ABS int_arg	{ inst_move_abs($3); }
	| T_MOVE       int_arg	{ inst_move_abs($2); }	/* 省略記法 */
	//
	| T_MOVE T_STOP		{ inst_move_stop(); }
	|        T_STOP		{ inst_move_stop(); }	/* 省略記法 */
	//
	| T_WAIT T_REL int_arg	{ inst_wait_rel($3); }
	| T_WAIT       int_arg	{ inst_wait_rel($2); }	/* 省略記法 */
	//
	| T_WAIT T_ABS int_arg	{ inst_wait_abs($3); }
	//
	| T_WAIT T_STOP		{ inst_wait_stop(); }
	| T_WAIT		{ inst_wait_stop(); }	/* 省略記法 */
	//
	| T_USER int_arg	{ inst_user($2); }
	//
	| T_MOVE T_DIRECT int_arg if_cond		{ inst_move_direct($3,                  $4, RudCtlReq_When_Never); }	/* 省略記法 */	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_MOVE T_DIRECT int_arg			{ inst_move_direct($3, RudCtlReq_If_Always, RudCtlReq_When_Never); }	/* 省略記法 */	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_MOVE T_DIRECT int_arg if_cond until_cond	{ inst_move_direct($3,                  $4,                   $5); }			/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_MOVE T_DIRECT int_arg         until_cond	{ inst_move_direct($3, RudCtlReq_If_Always,                   $4); }	/* 省略記法 */	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	//
	| T_MOVE T_STOP T_DIRECT			{ inst_move_direct(0, RudCtlReq_If_Always, RudCtlReq_When_Never); }			/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	|        T_STOP T_DIRECT			{ inst_move_direct(0, RudCtlReq_If_Always, RudCtlReq_When_Never); }	/* 省略記法 */	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	//
	| T_IF T_ON		{ inst_if_on(); }	/*{{2014/12/12追加:条件分岐'if on','if off'を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_IF T_OFF		{ inst_if_off(); }	/*{{2014/12/12追加:条件分岐'if on','if off'を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	;
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; }
	;
if_cond
	: T_IF T_ON		{ $$ = RudCtlReq_If_SnsOn; }		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_IF T_OFF		{ $$ = RudCtlReq_If_SnsOff; }		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_ALWAYS		{ $$ = RudCtlReq_If_Always; }		/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	;
until_cond
	: T_UNTIL T_RISE	{ $$ = RudCtlReq_When_SnsRise; }	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_UNTIL T_FALL	{ $$ = RudCtlReq_When_SnsFall; }	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	| T_UNTIL T_EDGE	{ $$ = RudCtlReq_When_SnsEdge; }	/*{{2014/11/28追加:パルスモーターの直接制御を追加したことに伴い、シーケンサの命令セット,命令コード,命令コード定義用マクロを変更しました。}}*/
	;

%%
