%{
//{{定型コード:y.tab.y(宣言部,%{〜%}内)========================================
#include "app.h"
#pragma warning(default: 4131)	//{{2016/03/01追加:clipstd.hにてC4131の警告レベルを引き上げましたが、Bison/Flexの生成コードには旧スタイルの宣言が使われているので、Bison/Flexの生成コードのみ警告レベルを元に戻しました。}}
//パーサースタックの初期値を定義します。
//sizeof(YYSTYPE)*YYINITDEPTH) がスタック上に確保されます。
//デフォルトでは200と定義されており、P/ECEには大きすぎます。
//P/ECEに適切な、小さなサイズ(16)に、再定義しました。
//パーサースタックが不足した場合は、自動的に拡張されるので、問題ありません。
#define YYINITDEPTH 16
//エラー報告関数を定義します。
char err_path[MAX_PATH];	//'-e'オプションが指定されたら、エラーログファイル名を格納する。
void yyerror(const char* fmt, ...) {
	static FILE* fp_err;	//最初のエラーログを記録する時に、エラーログファイルを作成する。
	//'-e'オプションが指定されていて、最初のエラーログを記録する時ならば…
	if(*err_path && !fp_err) {
		//エラーログファイルを作成する。
		fp_err = fopen(err_path, "w");
		if(!fp_err) { die("%s が作成できません。\n", err_path); }
		//エラーログファイルの出力ストリームは、バッファリング無しとする。
		// - die()で終了した時(abort()時)に、バッファ分がフラッシュされないようなので、こうしておく必要が有る。
		//   別の案として、この下の処理で毎回fflush()する方法も有るが、バッファリング無しとする方が簡単だろう。
		setbuf(fp_err, NULL);
	}
	//エラーメッセージ(,及び,エラーログ)を出力する。
	             fprintf(stderr, "### error at line %d : ", yylineno);	//エラーメッセージ
	if(fp_err) { fprintf(fp_err, "### error at line %d : ", yylineno); }	//エラーログ
	{
		va_list ap;
		va_start(ap, fmt);
		             vfprintf(stderr, fmt, ap);		//エラーメッセージ
		if(fp_err) { vfprintf(fp_err, fmt, ap); }	//エラーログ
		va_end(ap);
	}
	             fputc('\n', stderr);	//エラーメッセージ
	if(fp_err) { fputc('\n', fp_err); }	//エラーログ
}
//}}定型コード:y.tab.y(宣言部,%{〜%}内)========================================
%}

%union {
	int		v_num;
	double		v_dbl;
	char*		v_lab;
	char*		v_str;
}
%token	<v_num>		T_NUM
%token	<v_dbl>		T_DBL
%token	<v_lab>		T_LAB
%token	<v_str>		T_STR
%token			T_EOL

%type	<v_num>		expr
%type	<v_dbl>		edbl

%left			'|'
%left			'^'
%left			'&'
%left			'<' '>'
%left			'+' '-'
%left			'*' '/'
%nonassoc		'~' T_UPL T_UMI T_CAST_INT T_CAST_DBL

%%

all
		: pre_blank
		| all expr eols			{ printf("expr: %d\n", $2); }
		| all edbl eols			{ printf("edbl: %f\n", $2); }
		| all T_LAB eols		{ printf("T_LAB: %s\n", $2); }
		| all T_STR eols		{ printf("T_STR: %s\n", $2); }
		;
pre_blank
		: /* empty */
		| pre_blank T_EOL		/* no action */
		;
eols
		:      T_EOL
		| eols T_EOL
		;
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			{ $$ = $1 / $3; }
		| expr '&' expr			{ $$ = $1 & $3; }
		| expr '^' expr			{ $$ = $1 ^ $3; }
		| expr '|' expr			{ $$ = $1 | $3; }
		| expr '<' expr			{ $$ = $1 << $3; }
		| expr '>' expr			{ $$ = $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			{ $$ = $1 / $3; }
		| edbl '/' expr			{ $$ = $1 / $3; }
		| expr '/' edbl			{ $$ = $1 / $3; }
		;

%%
