%{
/*{{定型コード: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 {
	char*		v_str;
	ST_Map*		v_map;
	ST_MapHdr*	v_mapHdr;
	ST_MapBody*	v_mapBody;
	ST_State*	v_state;
	ST_StateBody*	v_stateBody;
	ST_Trans*	v_trans;
	ST_TransBody*	v_transBody;
	ST_Func*	v_func;
	ST_NextState*	v_nextState;
}

%token <v_str>		T_LAB
%token <v_str>		T_CODE
%token <v_str>		T_SOURCE
%token <v_str>		T_PROPERTY
%token			T_ENTRY
%token			T_EXIT
%token			T_SUSPEND
%token			T_RESUME
%token			T_PUSH
%token			T_POP
%token			T_END
%token			T_EOL
//{{2018/04/20削除:自己遷移を抑止する方法を変更しました。
//%token		T_NO_SELF_TRANSITION			//{{2017/01/15追加:自己遷移を抑止するGuard関数の省略記法を追加しました。}}
//}}2018/04/20削除:自己遷移を抑止する方法を変更しました。
%token			T_KEEP_TRANS_ORDER			//{{2018/04/18追加:「keep-trans-order」「sort-trans-order」を追加しました。}}
%token			T_SORT_TRANS_ORDER			//{{2018/04/18追加:「keep-trans-order」「sort-trans-order」を追加しました。}}

%type <v_str>		labRow
%type <v_func>		entRow
%type <v_func>		exiRow
%type <v_func>		susRow
%type <v_func>		resRow
%type <v_map>		map
%type <v_mapHdr>	mapHdr
%type <v_mapBody>	mapBody
%type <v_state>		state
%type <v_stateBody>	stateBody
%type <v_trans>		trans
%type <v_transBody>	transBody
%type <v_func>		notify
%type <v_func>		guard
%type <v_func>		act
%type <v_nextState>	nextState

%%

all
		: /* empty */
		| all T_EOL					/* no action */
		| all T_SOURCE					{ add_source($2); yyerrok; }					//┬error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
		| all T_PROPERTY				{ add_property($2); yyerrok; }					//│
		| all T_KEEP_TRANS_ORDER			{ g_keepTransOrder = 1; yyerrok; }				//│	//{{2018/04/18追加:「keep-trans-order」「sort-trans-order」を追加しました。}}
		| all T_SORT_TRANS_ORDER			{ g_keepTransOrder = 0; yyerrok; }				//│	//{{2018/04/18追加:「keep-trans-order」「sort-trans-order」を追加しました。}}
		| all map					{ add_map($2); yyerrok; }					//┘
		| all error													//全てのシンタクスエラーを報告するために継続する。
		;
map
		: mapHdr mapBody endRow				{ if(!($$ = Map_new($1, $2))) { YYERROR; } }			//状態が無いマップは作成できません。又は、遷移先状態が存在しません。シンタクスエラーを生成して、このstateを受け入れない。
		;
mapHdr
//{{2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、dFsmMapC.exeも変更後のレジストリ構造を出力するように変更しました。
//		: T_LAB T_LAB T_EOL				{ $$ = MapHdr_new($1, $2); }
//↓2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、dFsmMapC.exeも変更後のレジストリ構造を出力するように変更しました。
		: T_LAB     T_LAB     T_EOL			{ $$ = MapHdr_new($1, NULL, $2); }
		| T_LAB act T_LAB     T_EOL			{ $$ = MapHdr_new($1,   $2, $3); }				//┬初期化Act関数を指定する場合、初期状態の前に書いても後に書いても良い。どちらでも生成されるデータに違いは無い。
		| T_LAB     T_LAB act T_EOL			{ $$ = MapHdr_new($1,   $3, $2); }				//┘
//}}2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、dFsmMapC.exeも変更後のレジストリ構造を出力するように変更しました。
		;
mapBody
		: /* empty */					{ $$ = MapBody_new(); }
		| mapBody T_EOL					/* use default action */
		| mapBody entRow				{ $$ = MapBody_addEntry(   $1, $2); }
		| mapBody exiRow				{ $$ = MapBody_addExit(    $1, $2); }
		| mapBody susRow				{ $$ = MapBody_addSuspend( $1, $2); }
		| mapBody resRow				{ $$ = MapBody_addResume(  $1, $2); }
		| mapBody trans					{ $$ = MapBody_addTrans(   $1, $2); }
		| mapBody state					{ $$ = MapBody_addState(   $1, $2); }
		| mapBody T_PROPERTY				{ $$ = MapBody_addProperty($1, $2); }
		;
state
		: labRow stateBody endRow			{ if(!($$ = State_new($1, $2))) { YYERROR; } }			//空の状態は作成できません。シンタクスエラーを生成して、このstateを受け入れない。	⇒{{2018/04/12変更:空の状態も作成出来るようにしました。}}
		;
stateBody
		: /* empty */					{ $$ = StateBody_new(); }
		| stateBody T_EOL				/* use default action */
		| stateBody entRow				{ $$ = StateBody_addEntry(  $1, $2); }
		| stateBody exiRow				{ $$ = StateBody_addExit(   $1, $2); }
		| stateBody susRow				{ $$ = StateBody_addSuspend($1, $2); }
		| stateBody resRow				{ $$ = StateBody_addResume( $1, $2); }
		| stateBody trans				{ $$ = StateBody_addTrans(  $1, $2); }
		;
labRow
		: T_LAB T_EOL					{ $$ = $1; }
		;
entRow
		: T_ENTRY   notify T_EOL			{ $$ = $2; }
		;
exiRow
		: T_EXIT    notify T_EOL			{ $$ = $2; }
		;
susRow
		: T_SUSPEND notify T_EOL			{ $$ = $2; }
		;
resRow
		: T_RESUME  notify T_EOL			{ $$ = $2; }
		;
trans
		: T_LAB transBody T_EOL				{ if(!($$ = Trans_new($1, $2))) { YYERROR; } }			//Act関数も遷移先状態も無い遷移は作成できません。シンタクスエラーを生成して、このtransを受け入れない。		//{{2017/01/15コメント追記:遷移先状態が無かったり、遷移先状態がpop遷移である遷移には、自己遷移を抑止するGuard関数の省略記法を指定する事は出来ません。シンタクスエラーを生成して、このtransを受け入れない。詳細は、winapp.cのTrans_new()の、2017/01/15追加部分のコメントを参照して下さい。}}
		;
transBody
		:           guard				{ $$ = TransBody_newGuard(    $1); }
		|           act					{ $$ = TransBody_newAct(      $1); }
		|           nextState				{ $$ = TransBody_newState(    $1); }
		| transBody guard				{ $$ = TransBody_addGuard($1, $2); }
		| transBody act					{ $$ = TransBody_addAct(  $1, $2); }
		| transBody nextState				{ $$ = TransBody_addState($1, $2); }
		;
notify
		: '{'        '}'				{ $$ = Func_new(1, "", NULL); }
		| '{' T_LAB  '}'				{ $$ = Func_new(1, $2, NULL); }
		| '{' T_CODE '}'				{ $$ = Func_new(1, NULL, $2); }
		;
guard
		: '['        ']'				{ $$ = Func_new(2, "", NULL); }
		| '[' T_LAB  ']'				{ $$ = Func_new(2, $2, NULL); }
		| '[' T_CODE ']'				{ $$ = Func_new(2, NULL, $2); }
//{{2018/04/20削除:自己遷移を抑止する方法を変更しました。
//		| '[' T_NO_SELF_TRANSITION  ']'			{ $$ = Func_new(2, "no-self-transition", NULL); }		//{{2017/01/15追加:自己遷移を抑止するGuard関数の省略記法を追加しました。}}
//}}2018/04/20削除:自己遷移を抑止する方法を変更しました。
		;
act
		: '{'        '}'				{ $$ = Func_new(3, "", NULL); }
		| '{' T_LAB  '}'				{ $$ = Func_new(3, $2, NULL); }
		| '{' T_CODE '}'				{ $$ = Func_new(3, NULL, $2); }
		;
nextState
//{{2018/04/20変更:自己遷移を抑止する方法を変更しました。
//		:            T_LAB				{ $$ = NextState_new(1/*set*/,   $1); }
//		| T_PUSH '(' T_LAB ')'				{ $$ = NextState_new(2/*push*/,  $3); }
//		| T_POP						{ $$ = NextState_new(3/*pop*/, NULL); }
//↓2018/04/20変更:自己遷移を抑止する方法を変更しました。
		:            T_LAB				{ $$ = NextState_new(Fsm_TransType_set,   $1); }
		|            T_LAB '!'				{ $$ = NextState_new(Fsm_TransType_setx,  $1); }
		| T_PUSH '(' T_LAB ')'				{ $$ = NextState_new(Fsm_TransType_push,  $3); }
		| T_POP						{ $$ = NextState_new(Fsm_TransType_pop, NULL); }
//}}2018/04/20変更:自己遷移を抑止する方法を変更しました。
		;
endRow
		: T_END T_EOL					/* no action */
		;

%%
