%{
/*{{定型コード: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_Arg*			v_arg;
	ST_Args*		v_args;
	GSList*			v_argList;
	//
	ST_Func*		v_func;
	//
	ST_Cond*		v_cond;
	ST_CondSubs*		v_condSubs;
	GSList*			v_condSubsList;
	//
	ST_ValueSubs*		v_valueSubs;
	GSList*			v_valueSubsList;
	//
	ST_SnrTbl*		v_snrTbl;
	ST_SnrTblBody*		v_snrTblBody;
	ST_SnrTblStmt*		v_snrTblStmt;
	//
	ST_SnrSeq*		v_snrSeq;
	ST_SnrSeqBody*		v_snrSeqBody;
	ST_SnrSeqStmt*		v_snrSeqStmt;
}

%token	<v_num>			T_NUM
%token	<v_dbl>			T_DBL
%token	<v_str>			T_G_LAB
%token	<v_str>			T_L_LAB
%token	<v_str>			T_STR
%token				T_EOL

//引数リストで使用されるトークン
%token				T_BIT
%token				T_BYTE
%token				T_HALF
%token				T_EXP10
%token				T_WORD
%token				T_BER		//{{2018/04/07追加:引数リストにBER圧縮整数も含められるようにしました。}}
%token				T_FP16
%token				T_FP32
%token				T_FP64
%token				T_FILE
%token				T_TABLE		//当ツール特有の型
%token				T_TRIG		//当ツール特有の型
%token				T_FUNC		//当ツール特有の型
//シナリオテーブルとシナリオシーケンスで使用されるトークン
%token				T_DEF
%token				T_END
%token				T_NOT
%token				T_GOTO
//シナリオテーブルで使用されるトークン
%token				T_ON
%token				T_UNLOCK
%token				T_EXEC
%token				T_LOCK
//シナリオシーケンスで使用されるトークン
%token				T_EXIT
%token				T_ESCAPE
%token				T_WAIT
%token				T_FOR
%token				T_FORK
%token				T_HIDE
%token				T_JOIN
%token				T_CALL
%token				T_ELSE
%token				T_IF
%token				T_ELIF
%token				T_CASE
%token				T_OF
%token				T_UNLESS
%token				T_REPEAT
%token				T_BREAK
%token				T_WHILE
%token				T_UNTIL
%token				T_ACT
%token				T_ENSURE

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

%type	<v_arg>			arg
%type	<v_args>		naked_args
%type	<v_argList>		naked_argList
%type	<v_args>		parenthesized_args
%type	<v_argList>		parenthesized_argList

%type	<v_func>		func
%type	<v_func>		naked_func

%type	<v_cond>		cond
%type	<v_num>			not

%type	<v_str>			gLabRow
%type	<v_str>			lLabRow
%type	<v_str>			labRef

%type	<v_snrTbl>		snrTbl
%type	<v_snrTblBody>		snrTblBody
%type	<v_snrTblStmt>		snrTblStmt
%type	<v_snrTblStmt>		onUnlockStmt
%type	<v_snrTblStmt>		onGotoStmt
%type	<v_snrTblStmt>		onExecStmt
%type	<v_num>			unlock
%type	<v_num>			lock

%type	<v_snrSeq>		snrSeq
%type	<v_snrSeqBody>		optSnrSeqBody
%type	<v_snrSeqBody>		snrSeqBody
%type	<v_snrSeqStmt>		snrSeqStmt
%type	<v_snrSeqStmt>		exitStmt
%type	<v_snrSeqStmt>		escapeStmt
%type	<v_snrSeqStmt>		waitStmt
%type	<v_num>			waitCnt
%type	<v_snrSeqStmt>		waitForStmt
%type	<v_snrSeqStmt>		forkStmt
%type	<v_snrSeqStmt>		hideStmt
%type	<v_snrSeqStmt>		joinStmt
%type	<v_snrSeqStmt>		gotoStmt
%type	<v_snrSeqStmt>		callStmt
%type	<v_snrSeqBody>		elseSubs
%type	<v_snrSeqStmt>		ifStmt
%type	<v_condSubs>		ifSubs
%type	<v_snrSeqStmt>		unlessStmt
%type	<v_condSubs>		unlessSubs
%type	<v_condSubs>		elifSubs
%type	<v_condSubsList>	elifSubsList
%type	<v_snrSeqStmt>		caseStmt
%type	<v_valueSubs>		ofSubs
%type	<v_valueSubsList>	ofSubsList
%type	<v_snrSeqStmt>		repeatStmt
%type	<v_num>			repeatCnt
%type	<v_snrSeqStmt>		breakStmt
%type	<v_num>			breakCnt
%type	<v_snrSeqStmt>		whileStmt
%type	<v_snrSeqStmt>		untilStmt
%type	<v_snrSeqStmt>		actStmt
%type	<v_num>			ensure

%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 snrTbl									{ addSnrTbl($2); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
				| all snrSeq									{ addSnrSeq($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); }
				;
dbl_arg
				: expr										{ $$ = $1; }
				| edbl										/* use default action */
				;
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); }
				;
				/*---------------------------------------------------------------------------*/
arg
				: T_BIT   int_arg								{ if(!($$ = Arg_NewBit(   $2))) { yynerrs++; YYERROR; } }
				| T_BYTE  int_arg								{ if(!($$ = Arg_NewByte(  $2))) { yynerrs++; YYERROR; } }
				|         int_arg								{ if(!($$ = Arg_NewByte(  $1))) { yynerrs++; YYERROR; } }	//省略記法
				| T_HALF  int_arg								{ if(!($$ = Arg_NewHalf(  $2))) { yynerrs++; YYERROR; } }
				| T_EXP10 int_arg								{ if(!($$ = Arg_NewExp10( $2))) { yynerrs++; YYERROR; } }
				| T_WORD  int_arg								{ if(!($$ = Arg_NewWord(  $2))) { yynerrs++; YYERROR; } }
				| T_BER   int_arg								{ if(!($$ = Arg_NewBer(   $2))) { yynerrs++; YYERROR; } }	//{{2018/04/07追加:引数リストにBER圧縮整数も含められるようにしました。}}
				| T_FP16  dbl_arg								{ if(!($$ = Arg_NewFp16(  $2))) { yynerrs++; YYERROR; } }
				| T_FP32  dbl_arg								{ if(!($$ = Arg_NewFp32(  $2))) { yynerrs++; YYERROR; } }
				| T_FP64  dbl_arg								{ if(!($$ = Arg_NewFp64(  $2))) { yynerrs++; YYERROR; } }
				|         estr									{ if(!($$ = Arg_NewString($1))) { yynerrs++; YYERROR; } }
				| T_FILE  estr									{ if(!($$ = Arg_NewFile(  $2))) { yynerrs++; YYERROR; } }
				| T_TABLE T_G_LAB								{ if(!($$ = Arg_NewTable( $2))) { yynerrs++; YYERROR; } }	//当ツール特有の型
			//不可	|         T_G_LAB								{ if(!($$ = Arg_NewTable( $1))) { yynerrs++; YYERROR; } }	//省略記法		この行を有効にすると、"on trg goto seq"の省略形"trg seq"と区別出来ずシフト還元衝突するので不可。
				| T_TRIG  T_G_LAB								{ if(!($$ = Arg_NewTrig(  $2))) { yynerrs++; YYERROR; } }	//当ツール特有の型
				| T_FUNC  T_G_LAB								{ if(!($$ = Arg_NewFunc(  $2))) { yynerrs++; YYERROR; } }	//当ツール特有の型
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
naked_args
				: /* empty */									{ if(!($$ = Args_New(NULL))) { yynerrs++; YYERROR; } }
				| naked_argList									{ if(!($$ = Args_New(  $1))) { yynerrs++; YYERROR; } }
				;
naked_argList
				:                        arg							{ if(!($$ = ArgList_AddArg(NULL, $1))) { yynerrs++; YYERROR; } }	//括弧で囲まれていない引数リストは、カンマの後でのみ改行可能。(引数の後で改行すると継続かどうか判断出来ないから)
				| naked_argList ',' xeol arg							{ if(!($$ = ArgList_AddArg(  $1, $4))) { yynerrs++; YYERROR; } }
				;
parenthesized_args
				: '(' xeol                       ')'						{ if(!($$ = Args_New(NULL))) { yynerrs++; YYERROR; } }
				| '(' xeol parenthesized_argList ')'						{ if(!($$ = Args_New(  $3))) { yynerrs++; YYERROR; } }
				;
parenthesized_argList
				:                                arg xeol					{ if(!($$ = ArgList_AddArg(NULL, $1))) { yynerrs++; YYERROR; } }	//括弧で囲まれている引数リストは、どこでも改行可能。(どこで改行しても閉じ括弧が現れるまでは継続と判断出来るから)
				| parenthesized_argList ',' xeol arg xeol					{ if(!($$ = ArgList_AddArg(  $1, $4))) { yynerrs++; YYERROR; } }
				;
xeol
				: /* empty */									/* no action */
				| xeol T_EOL									/* no action */
				;
				/*---------------------------------------------------------------------------*/
func
				: T_G_LAB parenthesized_args							{ if(!($$ = Func_New($1,             $2))) { yynerrs++; YYERROR; } }
				| T_G_LAB									{ if(!($$ = Func_New($1, Args_New(NULL)))) { yynerrs++; YYERROR; } }	//引数無しのfuncは'func()'でも'func'でも可
				;
naked_func
				: T_G_LAB naked_args								{ if(!($$ = Func_New($1,         $2))) { yynerrs++; YYERROR; } }
				;
				/*---------------------------------------------------------------------------*/
cond
				: not func									{ if(!($$ = Cond_New($1, $2))) { yynerrs++; YYERROR; } }
				;
not
				: /* empty */									{ $$ = 0; }
				| T_NOT										{ $$ = 1; }
				;
				/*---------------------------------------------------------------------------*/
gLabRow
				: T_DEF T_G_LAB eols								{ if(!($$ = LabDef_New($2))) { yynerrs++; YYERROR; } }
				|       T_G_LAB eols								{ if(!($$ = LabDef_New($1))) { yynerrs++; YYERROR; } }	//省略記法
				;
lLabRow
				: T_DEF T_L_LAB eols								{ if(!($$ = LabDef_New($2))) { yynerrs++; YYERROR; } }
				|       T_L_LAB eols								{ if(!($$ = LabDef_New($1))) { yynerrs++; YYERROR; } }	//省略記法
				;
labRef
				:       T_G_LAB									{ if(!($$ = LabRef_New($1))) { yynerrs++; YYERROR; } }
				|       T_L_LAB									{ if(!($$ = LabRef_New($1))) { yynerrs++; YYERROR; } }
				;
				/*---------------------------------------------------------------------------*/
snrTbl
				: gLabRow snrTblBody end							{ if(!($$ = SnrTbl_New($1, $2))) { yynerrs++; YYERROR; } }
				;
snrTblBody
				:            snrTblStmt								{ if(!($$ = SnrTblBody_AddSnrTblStmt(SnrTblBody_New(), $1))) { yynerrs++; YYERROR; } }
				| snrTblBody snrTblStmt								{ if(!($$ = SnrTblBody_AddSnrTblStmt(              $1, $2))) { yynerrs++; YYERROR; } }
				;
snrTblStmt
				: onUnlockStmt									/* use default action */
				| onGotoStmt									/* use default action */
				| onExecStmt									/* use default action */
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
onUnlockStmt
				: T_ON T_G_LAB T_UNLOCK eols							{ if(!($$ = OnUnlockStmt_New(    $2            ))) { yynerrs++; YYERROR; } }			//┬onは、gotoと同様の省略可能な非終端記号として表現する事は出来ない。yaccのLR(1)の先読み限界のために、T_G_LABを読んだ時点では、シナリオテーブルと見なして省略されたonに還元するか、シナリオシーケンスと見なしてonを生成しないかを判断出来ず、シフト還元衝突してしまうからです。
				|      T_G_LAB T_UNLOCK eols							{ if(!($$ = OnUnlockStmt_New(    $1            ))) { yynerrs++; YYERROR; } }	//省略記法	//┘
				;
onGotoStmt
				: T_ON T_G_LAB unlock goto   labRef lock eols					{ if(!($$ = OnGotoStmt_New(      $2, $3, $5, $6))) { yynerrs++; YYERROR; } }			//┬onは、gotoと同様の省略可能な非終端記号として表現する事は出来ない。yaccのLR(1)の先読み限界のために、T_G_LABを読んだ時点では、シナリオテーブルと見なして省略されたonに還元するか、シナリオシーケンスと見なしてonを生成しないかを判断出来ず、シフト還元衝突してしまうからです。
				|      T_G_LAB unlock goto   labRef lock eols					{ if(!($$ = OnGotoStmt_New(      $1, $2, $4, $5))) { yynerrs++; YYERROR; } }	//省略記法	//┘
				| T_ON T_G_LAB unlock T_GOTO        lock eols optSnrSeqBody end			{ if(!($$ = OnGotoStmt_NewInline($2, $3, $5, $7))) { yynerrs++; YYERROR; } }	//糖衣構文	//┬gotoは省略不可です。actStmtの省略記法やonUnlockStmtと区別出来ず、シフト還元衝突してしまうからです。
				|      T_G_LAB unlock T_GOTO        lock eols optSnrSeqBody end			{ if(!($$ = OnGotoStmt_NewInline($1, $2, $4, $6))) { yynerrs++; YYERROR; } }	//糖衣構文	//┘
				;
onExecStmt
				: T_ON T_G_LAB unlock T_EXEC labRef lock eols					{ if(!($$ = OnExecStmt_New(      $2, $3, $5, $6))) { yynerrs++; YYERROR; } }			//┬onは、gotoと同様の省略可能な非終端記号として表現する事は出来ない。yaccのLR(1)の先読み限界のために、T_G_LABを読んだ時点では、シナリオテーブルと見なして省略されたonに還元するか、シナリオシーケンスと見なしてonを生成しないかを判断出来ず、シフト還元衝突してしまうからです。
				|      T_G_LAB unlock T_EXEC labRef lock eols					{ if(!($$ = OnExecStmt_New(      $1, $2, $4, $5))) { yynerrs++; YYERROR; } }	//省略記法	//┘
				| T_ON T_G_LAB unlock T_EXEC        lock eols optSnrSeqBody end			{ if(!($$ = OnExecStmt_NewInline($2, $3, $5, $7))) { yynerrs++; YYERROR; } }	//糖衣構文
				|      T_G_LAB unlock T_EXEC        lock eols optSnrSeqBody end			{ if(!($$ = OnExecStmt_NewInline($1, $2, $4, $6))) { yynerrs++; YYERROR; } }	//糖衣構文
				;
unlock
				: /* empty */									{ $$ = 0; }
				| T_UNLOCK									{ $$ = 1; }
				;
goto
				: T_GOTO									/** no job **/
				| /* empty */									/** no job **/	//省略記法
				;
lock
				: /* empty */									{ $$ = 0/*ロック無し*/; }
				| T_LOCK int_arg								{ if(($$ = Lock_New($2)) == -1) { yynerrs++; YYERROR; } }
				|        int_arg								{ if(($$ = Lock_New($1)) == -1) { yynerrs++; YYERROR; } }	//省略記法
				;
				/*---------------------------------------------------------------------------*/
snrSeq
				: gLabRow            end							{ if(!($$ = SnrSeq_New($1, SnrSeqBody_New()))) { yynerrs++; YYERROR; } }	//┐
				| gLabRow snrSeqBody end							{ if(!($$ = SnrSeq_New($1,               $2))) { yynerrs++; YYERROR; } }	//┴optSnrSeqBodyは使用出来ないので明示的に2パターン書く必要が有る。yaccのLR(1)の先読み限界で判断出来ずエラーになってしまうからです。
				| lLabRow            end							{ if(!($$ = SnrSeq_New($1, SnrSeqBody_New()))) { yynerrs++; YYERROR; } }	//┐
				| lLabRow snrSeqBody end							{ if(!($$ = SnrSeq_New($1,               $2))) { yynerrs++; YYERROR; } }	//┴optSnrSeqBodyは使用出来ないので明示的に2パターン書く必要が有る。yaccのLR(1)の先読み限界で判断出来ずエラーになってしまうからです。
				;
optSnrSeqBody
				: /* empty */									{ if(!($$ = SnrSeqBody_New())) { yynerrs++; YYERROR; } }
				| snrSeqBody									/* use default action */
				;
snrSeqBody
				:            snrSeqStmt								{ if(!($$ = SnrSeqBody_AddSnrSeqStmt(SnrSeqBody_New(), $1))) { yynerrs++; YYERROR; } }
				| snrSeqBody snrSeqStmt								{ if(!($$ = SnrSeqBody_AddSnrSeqStmt(              $1, $2))) { yynerrs++; YYERROR; } }
				;
snrSeqStmt
				: exitStmt									/* use default action */
				| escapeStmt									/* use default action */
				| waitStmt									/* use default action */
				| waitForStmt									/* use default action */
				| forkStmt									/* use default action */
				| hideStmt									/* use default action */
				| joinStmt									/* use default action */
				| gotoStmt									/* use default action */
				| callStmt									/* use default action */
				| ifStmt									/* use default action */
				| caseStmt									/* use default action */
				| unlessStmt									/* use default action */
				| repeatStmt									/* use default action */
				| breakStmt									/* use default action */
				| whileStmt									/* use default action */
				| untilStmt									/* use default action */
				| actStmt									/* use default action */
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
exitStmt
				: T_EXIT eols									{ if(!($$ = ExitStmt_New())) { yynerrs++; YYERROR; } }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
escapeStmt
				: T_ESCAPE eols									{ if(!($$ = EscapeStmt_New())) { yynerrs++; YYERROR; } }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
waitStmt
				: T_WAIT waitCnt eols								{ if(!($$ = WaitStmt_New($2))) { yynerrs++; YYERROR; } }
				;
waitCnt
				: int_arg									{ if(($$ = WaitCnt_New($1)) == -1) { yynerrs++; YYERROR; } }
				| /* empty */									{ $$ = 1; }	//省略記法
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
waitForStmt
				: T_WAIT for cond eols								{ if(!($$ = WaitForStmt_New($3))) { yynerrs++; YYERROR; } }
				;
for
				: T_FOR										/** no job **/
				| /* empty */									/** no job **/	//省略記法
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
forkStmt
				: T_FORK eols optSnrSeqBody end							{ if(!($$ = ForkStmt_New($3))) { yynerrs++; YYERROR; } }
				;
hideStmt
				: T_HIDE eols									{ if(!($$ = HideStmt_New())) { yynerrs++; YYERROR; } }
				;
joinStmt
				: T_JOIN eols									{ if(!($$ = JoinStmt_New())) { yynerrs++; YYERROR; } }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
gotoStmt
				: T_GOTO labRef eols								{ if(!($$ = GotoStmt_New($2))) { yynerrs++; YYERROR; } }
				;
callStmt
				: T_CALL labRef eols								{ if(!($$ = CallStmt_New($2))) { yynerrs++; YYERROR; } }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
elseSubs
				: /* empty */									{ $$ = NULL; }
				| T_ELSE eols optSnrSeqBody							{ $$ = $3; }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
ifStmt
				: ifSubs elifSubsList elseSubs end						{ if(!($$ = IfStmt_New($1, $2, $3))) { yynerrs++; YYERROR; } }
				;
ifSubs
				: T_IF cond eols optSnrSeqBody							{ if(!($$ = IfSubs_New($2, $4))) { yynerrs++; YYERROR; } }
				;
unlessStmt
				: unlessSubs elseSubs end							{ if(!($$ = UnlessStmt_New($1, $2))) { yynerrs++; YYERROR; } }
				;
unlessSubs
				: T_UNLESS cond eols optSnrSeqBody						{ if(!($$ = UnlessSubs_New($2, $4))) { yynerrs++; YYERROR; } }
				;
elifSubs
				: T_ELIF cond eols optSnrSeqBody						{ if(!($$ = ElifSubs_New($2, $4))) { yynerrs++; YYERROR; } }
				;
elifSubsList
				: /* empty */									{ $$ = NULL; }
				| elifSubsList elifSubs								{ if(!($$ = CondSubsList_AddCondSubs($1, $2))) { yynerrs++; YYERROR; } }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
caseStmt
				: T_CASE func of eols ofSubsList elseSubs end					{ if(!($$ = CaseStmt_New($2, $5, $6))) { yynerrs++; YYERROR; } }
				;
of
				: T_OF										/** no job **/
				| /* empty */									/** no job **/	//省略記法
				;
ofSubs
				: int_arg eols optSnrSeqBody							{ if(!($$ = OfSubs_New($1, $3))) { yynerrs++; YYERROR; } }
				;
ofSubsList
				:            ofSubs								{ if(!($$ = ValueSubsList_AddValueSubs(NULL, $1))) { yynerrs++; YYERROR; } }
				| ofSubsList ofSubs								{ if(!($$ = ValueSubsList_AddValueSubs(  $1, $2))) { yynerrs++; YYERROR; } }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
repeatStmt
				: T_REPEAT repeatCnt eols optSnrSeqBody end					{ if(!($$ = RepeatStmt_New($2, $4))) { yynerrs++; YYERROR; } }
				;
repeatCnt
				: int_arg									{ if(($$ = RepeatCnt_New($1)) == -1) { yynerrs++; YYERROR; } }
				| /* empty */									{ $$ = UINT16_MAX/*無限*/; }
				;
breakStmt
				: T_BREAK breakCnt eols								{ if(!($$ = BreakStmt_New($2))) { yynerrs++; YYERROR; } }
				;
breakCnt
				: int_arg									{ if(($$ = BreakCnt_New($1)) == -1) { yynerrs++; YYERROR; } }
				| /* empty */									{ $$ = 1; }	//省略記法
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
whileStmt
				: T_WHILE cond eols optSnrSeqBody end						{ if(!($$ = WhileStmt_New($2, $4))) { yynerrs++; YYERROR; } }
				;
untilStmt
				: T_UNTIL cond eols optSnrSeqBody end						{ if(!($$ = UntilStmt_New($2, $4))) { yynerrs++; YYERROR; } }
				;
				/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
actStmt
				: T_ACT func ensure eols							{ if(!($$ = ActStmt_New($2, $3))) { yynerrs++; YYERROR; } }
				| naked_func ensure eols							{ if(!($$ = ActStmt_New($1, $2))) { yynerrs++; YYERROR; } }	//省略記法
				;
ensure
				: /* empty */									{ $$ = 0; }
				| T_ENSURE									{ $$ = 1; }
				;

%%
