%{
/*{{定型コード: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 {
	int		v_num;			//0〜65536=数値,65537〜131071=TBL_LabRef[]へのインデクス	//{{抽選表idを自己参照できるように。}}
	char*		v_lab;
	//
	ST_Table*	v_table;
	ST_Blocks*	v_blocks;
	ST_Block*	v_block;
	ST_Header*	v_header;
	ST_Body*	v_body;
	ST_LabelRow*	v_labelRow;
	ST_HeaderRow*	v_headerRow;
	ST_BodyRow*	v_bodyRow;
	ST_Values*	v_values;
}
%token T_ID
%token <v_num> T_NUM
%token <v_lab> T_LAB
%token T_EOL

%left '|'
%left '^'
%left '&'
%left '<' '>'
%left '+' '-'
%left '*' '/'
%nonassoc T_UPL T_UMI
%type <v_num>       expr
%type <v_table>     table
%type <v_blocks>    blocks
%type <v_block>     block
%type <v_header>    header
%type <v_body>      body
%type <v_labelRow>  labelRow
%type <v_headerRow> headerRow
%type <v_bodyRow>   bodyRow
%type <v_values>    colIds
%type <v_values>    weights
%type <v_num>       colId
%type <v_num>       hitVal
%type <v_num>       weight
%type <v_lab>       labDef
%type <v_num>       labRef	//{{抽選表idを自己参照できるように。}}

%%

all
		: /* empty */			/* no action */
	    //{{2015/02/21修正:allの「all eols」とbodyRowの「hitVal ',' weights eols」が衝突していたので、前者を「eols」に変更して修正しました。
	    //	| all eols			/* no action */			//ファイルの最初に一行以上の空行が有った場合に読み飛ばすために必要。
	    //↓2015/02/21修正:allの「all eols」とbodyRowの「hitVal ',' weights eols」が衝突していたので、前者を「eols」に変更して修正しました。
		| eols				/* no action */			//ファイルの最初に一行以上の空行が有った場合に読み飛ばすために必要。
	    //}}2015/02/21修正:allの「all eols」とbodyRowの「hitVal ',' weights eols」が衝突していたので、前者を「eols」に変更して修正しました。
		| all table			{ add_table($2); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
		| all error							//全てのシンタクスエラーを報告するために継続する。
		;
table
		: labelRow blocks		{ $$ = Table_newBlocks($1, $2); }
		| labelRow body			{ $$ = Table_newBody(  $1, $2); }
		;
blocks
		:        block			{ $$ = Blocks_add(NULL, $1); }
		| blocks block			{ $$ = Blocks_add(  $1, $2); }
		;
block
		: header body			{ $$ = Block_new($1, $2); }
		;
header
		:        headerRow		{ $$ = Header_add(NULL, $1); }
		| header headerRow		{ $$ = Header_add(  $1, $2); }
		;
body
		:      bodyRow			{ $$ = Body_add(NULL, $1); }
		| body bodyRow			{ $$ = Body_add(  $1, $2); }
		;
eols
		:      T_EOL			/* no action */
		| eols T_EOL			/* no action */
		;
labelRow
		: ':' labDef eols		{ $$ = LabelRow_new($2); }
		;
headerRow
		: T_ID ',' colIds eols		{ $$ = HeaderRow_new($3); }
		;
bodyRow
		: hitVal ',' weights eols	{ $$ = BodyRow_new($1, $3); }
		;
colIds
		:            colId		{ $$ = Values_add(NULL, $1); }
		| colIds ',' colId		{ $$ = Values_add(  $1, $3); }
		;
weights
		:             weight		{ $$ = Values_add(NULL, $1); }
		| weights ',' weight		{ $$ = Values_add(  $1, $3); }
		;
colId
		: /* empty */			{ $$ = -1/*空白*/; }
		| expr				{ $$ = ColId_new($1); }
		| labRef			/* use default action */	//{{抽選表idを自己参照できるように。}}
		;
hitVal
		: expr				{ $$ = HitVal_new($1); }
		| labRef			/* use default action */	//{{抽選表idを自己参照できるように。}}
		;
weight
		: expr				{ $$ = Weight_new($1); }
		| labRef			/* use default action */	//{{抽選表idを自己参照できるように。}}
		;
labDef
		: T_LAB				{ if(!($$ = LabDef_new($1))    ) { YYERROR; } }		//ラベル定義が不正ならば、シンタクスエラーを生成して、このlabDefを受け入れない。
		;
labRef
		: T_LAB				{ if( ($$ = LabRef_new($1)) < 0) { YYERROR; } }		//ラベル参照が不正ならば、シンタクスエラーを生成して、このlabRefを受け入れない。	//{{抽選表idを自己参照できるように。}}
		;
expr
		: T_NUM				/* use default action */
		| '(' expr ')'			{ $$ =  $2; }
		| '+' expr %prec T_UPL		{ $$ =  $2; }
		| '-' expr %prec T_UMI		{ $$ = -$2; }
		| expr '+' expr			{ $$ = $1 + $3; }
		| expr '-' expr			{ $$ = $1 - $3; }
		| expr '*' expr			{ $$ = $1 * $3; }
		| expr '/' expr			{ $$ = $1 / $3; }
		| expr '&' expr			{ $$ = $1 & $3; }
		| expr '^' expr			{ $$ = $1 ^ $3; }
		| expr '|' expr			{ $$ = $1 | $3; }
		| expr '<' expr			{ $$ = $1 << $3; }
		| expr '>' expr			{ $$ = $1 >> $3; }
		;

%%
