%{
/*{{定型コード:y.tab.y(宣言部,%{〜%}内)======================================*/
#ifdef  PIECE
#include "app.h"
#else //PIECE
#include "winapp.h"
#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_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			T_ENTER
%token			T_LEAVE
%token			T_PUSH
%token			T_POP
%token			T_END
%token			T_EOL

%type <v_str>		labRow
%type <v_func>		entRow
%type <v_func>		leaRow
%type <v_map>		map
%type <v_mapBody>	mapBody
%type <v_state>		state
%type <v_stateBody>	stateBody
%type <v_trans>		trans
%type <v_transBody>	transBody
%type <v_func>		entLea
%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 map					{ add_map(   $2); yyerrok; }					//┘
		| all error													//全てのシンタクスエラーを報告するために継続する。
		;
map
		: labRow mapBody endRow				{ if(!($$ = Map_new($1, $2))) { YYERROR; } }			//状態が無いマップは作成できません。又は、遷移先状態が存在しません。シンタクスエラーを生成して、このstateを受け入れない。
		;
mapBody
		: /* empty */					{ $$ = MapBody_new(); }
		| mapBody T_EOL					/* use default action */
		| mapBody entRow				{ $$ = MapBody_addEnter($1, $2); }
		| mapBody leaRow				{ $$ = MapBody_addLeave($1, $2); }
		| mapBody trans					{ $$ = MapBody_addTrans($1, $2); }
		| mapBody state					{ $$ = MapBody_addState($1, $2); }
		;
state
		: labRow stateBody endRow			{ if(!($$ = State_new($1, $2))) { YYERROR; } }			//空の状態は作成できません。シンタクスエラーを生成して、このstateを受け入れない。
		;
stateBody
		: /* empty */					{ $$ = StateBody_new(); }
		| stateBody T_EOL				/* use default action */
		| stateBody entRow				{ $$ = StateBody_addEnter($1, $2); }
		| stateBody leaRow				{ $$ = StateBody_addLeave($1, $2); }
		| stateBody trans				{ $$ = StateBody_addTrans($1, $2); }
		;
labRow
		: T_LAB T_EOL					{ $$ = $1; }
		;
entRow
		: T_ENTER entLea T_EOL				{ $$ = $2; }
		;
leaRow
		: T_LEAVE entLea T_EOL				{ $$ = $2; }
		;
trans
		: T_LAB transBody T_EOL				{ if(!($$ = Trans_new($1, $2))) { YYERROR; } }			//Act関数も遷移先状態も無い遷移は作成できません。シンタクスエラーを生成して、このtransを受け入れない。
		;
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); }
		;
entLea
		: '{'        '}'				{ $$ = 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); }
		;
act
		: '{'        '}'				{ $$ = Func_new(3, "", NULL); }
		| '{' T_LAB  '}'				{ $$ = Func_new(3, $2, NULL); }
		| '{' T_CODE '}'				{ $$ = Func_new(3, NULL, $2); }
		;
nextState
		:            T_LAB				{ $$ = NextState_new(1/*set*/,   $1); }
		| T_PUSH '(' T_LAB ')'				{ $$ = NextState_new(2/*push*/,  $3); }
		| T_POP						{ $$ = NextState_new(3/*pop*/, NULL); }
		;
endRow
		: T_END T_EOL					/* no action */
		;

%%
