%{
/*{{定型コード: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
/*}}定型コード:y.tab.y(宣言部,%{〜%}内)======================================*/
%}

%union {
	int				v_num;
	double				v_dbl;
	char*				v_lab;
	char*				v_str;
	//
	ST_KeyBody*			v_keyBody;
	ST_Key*				v_key;
	ST_NameRow*			v_nameRow;
	ST_ValueRow*			v_valueRow;
	ST_StringRow*			v_stringRow;
	ST_BlobRow*			v_blobRow;
	ST_Blob*			v_blob;
//{{2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
	ST_TypedValue*			v_typedValue;
	GSList/*<ST_TypedValue*>*/*	v_typedBlock;
//}}2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
}

%token					T_END
%token	<v_num>				T_NUM
%token	<v_dbl>				T_DBL
%token	<v_lab>				T_LAB
%token	<v_str>				T_STR
%token					T_EOL
%token					T_BIT
%token					T_BYTE
%token					T_HALF
%token					T_EXP10		//{{2017/02/16追加:BLOBのデータ定義に'exp10'のプレフィクス指定を追加しました。}}
%token					T_WORD
%token					T_BER		//{{2018/04/07追加:BLOBにBER圧縮整数も含められるようにしました。}}
%token					T_FP16
%token					T_FP32
%token					T_FP64
%token					T_FILE
%token					T_PREVENT_DELETION	//{{2018/04/12追加:「prevent-deletion」を追加しました。}}

%type	<v_keyBody>			keyBody
%type	<v_key>				key
%type	<v_nameRow>			nameRow
%type	<v_valueRow>			valueRow
%type	<v_stringRow>			stringRow
%type	<v_num>				name
%type	<v_num>				data
//{{2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//%type	<v_num>				bit
//%type	<v_num>				byte
//%type	<v_num>				half
//%type	<v_num>				word
//%type	<v_num>				ber		//{{2018/04/07追加:BLOBにBER圧縮整数も含められるようにしました。}}
//%type	<v_dbl>				fp16
//%type	<v_dbl>				fp32
//%type	<v_dbl>				fp64
//%type	<v_str>				file
//}}2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
%type	<v_num>				int_arg
%type	<v_dbl>				dbl_arg
%type	<v_num>				expr
%type	<v_dbl>				edbl
%type	<v_str>				estr
%type	<v_str>				string
%type	<v_blobRow>			blobRow
//{{2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//%type	<v_blob>			blobBody
//}}2018/04/08削除:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
%type	<v_blob>			blob
//{{2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
%type	<v_typedValue>			typedValue
%type	<v_typedValue>			bitValue
%type	<v_typedValue>			byteValue
%type	<v_typedValue>			halfValue
%type	<v_typedValue>			exp10Value
%type	<v_typedValue>			wordValue
%type	<v_typedValue>			berValue
%type	<v_typedValue>			fp16Value
%type	<v_typedValue>			fp32Value
%type	<v_typedValue>			fp64Value
%type	<v_typedValue>			strValue
%type	<v_typedValue>			fileValue
//
%type	<v_typedBlock>			typedBlock
%type	<v_typedBlock>			bitBlock
%type	<v_typedBlock>			byteBlock
%type	<v_typedBlock>			halfBlock
%type	<v_typedBlock>			exp10Block
%type	<v_typedBlock>			wordBlock
%type	<v_typedBlock>			berBlock
%type	<v_typedBlock>			fp16Block
%type	<v_typedBlock>			fp32Block
%type	<v_typedBlock>			fp64Block
%type	<v_typedBlock>			strBlock
%type	<v_typedBlock>			fileBlock
//
%type	<v_typedBlock>			bitBlockBody
%type	<v_typedBlock>			byteBlockBody
%type	<v_typedBlock>			halfBlockBody
%type	<v_typedBlock>			exp10BlockBody
%type	<v_typedBlock>			wordBlockBody
%type	<v_typedBlock>			berBlockBody
%type	<v_typedBlock>			fp16BlockBody
%type	<v_typedBlock>			fp32BlockBody
%type	<v_typedBlock>			fp64BlockBody
%type	<v_typedBlock>			strBlockBody
%type	<v_typedBlock>			fileBlockBody
//}}2018/04/08追加:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。

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

%%

all
		: keyBody					{ add_keyBody($1); }
		;
keyBody		: /* empty */					{ $$ = KeyBody_new(); }
		| keyBody T_EOL					/* use default action */
		| keyBody key					{ $$ = KeyBody_addKey(            $1, $2); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
		| keyBody valueRow				{ $$ = KeyBody_addValueRow(       $1, $2); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
		| keyBody stringRow				{ $$ = KeyBody_addStringRow(      $1, $2); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
		| keyBody blobRow				{ $$ = KeyBody_addBlobRow(        $1, $2); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。
		| keyBody preventDeletionRow			{ $$ = KeyBody_setPreventDeletion($1    ); yyerrok; }	//error記号の位置について『http://www.pwv.co.jp/~take/TakeWiki/index.php?Cコンパイラ設計(yacc・lexの応用)/第4章　エラー・リカバリ#dbd8d417』の【optional sequence】を参考にした。	//{{2018/04/12追加:「prevent-deletion」を追加しました。}}
		| keyBody error					/* no action */						//全てのシンタクスエラーを報告するために継続する。
		;
key
		: nameRow keyBody endRow			{ $$ = Key_new($1, $2); }
		;
nameRow
		: name T_EOL					{ $$ = NameRow_new($1); }
		;
valueRow
		: name '=' data T_EOL				{ $$ = ValueRow_new($1, $3); }
		;
stringRow
		: name '=' string T_EOL				{ $$ = StringRow_new($1, $3); }
		;
blobRow
		: name '=' blob T_EOL				{ $$ = BlobRow_new($1, $3); }
		;
//{{2018/04/12追加:「prevent-deletion」を追加しました。
preventDeletionRow
		: T_PREVENT_DELETION T_EOL			/* no action */
		;
//}}2018/04/12追加:「prevent-deletion」を追加しました。
endRow
		: T_END T_EOL					/* no action */
		;
name
		: int_arg					{ $$ = Name_newExpr($1); }
		| T_LAB						{ $$ = Name_newLabel($1); }
		;
data
		: int_arg					{ $$ = Data_newExpr($1); }
		| T_LAB						{ $$ = Data_newLabel($1); }
		;
string
		: estr						{ $$ = String_intern($1); }
		;
//{{2018/04/08変更:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//blob
//		: '{' xeol blobBody '}'				{ if(!($$ = Blob_intern($3))) { YYERROR; } }		//空のblobBodyならばエラーとする。	普通は、blobBodyの変換規則が空要素を認めていないから空のblobBodyが生成される事は無いのだが、唯一、file要素のみから成るblobBodyで,かつ,そのファイルが0バイトの時に空のblobBodyが生成されてしまう。そのようなケースはy.tab.yで検出出来ないので、Blob_intern()で検出してエラーとする事にした。
//		;
//↓2018/04/08変更:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
blob
		: typedBlock					{ if(!($$ = Blob_new(   $1))) { YYERROR; }		//空のblobBodyならばエラーとする。	普通は、blobBodyの変換規則が空要素を認めていないから空のblobBodyが生成される事は無いのだが、唯一、file要素のみから成るblobBodyで,かつ,そのファイルが0バイトの時に空のblobBodyが生成されてしまう。そのようなケースはy.tab.yで検出出来ないので、Blob_intern()で検出してエラーとする事にした。
								  if(!($$ = Blob_intern($$))) { YYERROR; } }
		;
//}}2018/04/08変更:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//{{2018/04/08変更:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
//blobBody
//		:                   bit  xeol			{ if(!($$ = Blob_newBit( $1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol bit  xeol			{ if(!($$ = Blob_addBit( $1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		|                   byte xeol			{ if(!($$ = Blob_newByte($1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol byte xeol			{ if(!($$ = Blob_addByte($1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		|                   half xeol			{ if(!($$ = Blob_newHalf($1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol half xeol			{ if(!($$ = Blob_addHalf($1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		|                   word xeol			{ if(!($$ = Blob_newWord($1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol word xeol			{ if(!($$ = Blob_addWord($1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//	//{{2018/04/07追加:BLOBにBER圧縮整数も含められるようにしました。
//		|                   ber  xeol			{ if(!($$ = Blob_newBer( $1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol ber  xeol			{ if(!($$ = Blob_addBer( $1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//	//}}2018/04/07追加:BLOBにBER圧縮整数も含められるようにしました。
//		|                   fp16 xeol			{ if(!($$ = Blob_newFp16($1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol fp16 xeol			{ if(!($$ = Blob_addFp16($1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		|                   fp32 xeol			{ if(!($$ = Blob_newFp32($1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol fp32 xeol			{ if(!($$ = Blob_addFp32($1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		|                   fp64 xeol			{ if(!($$ = Blob_newFp64($1    ))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//		| blobBody ',' xeol fp64 xeol			{ if(!($$ = Blob_addFp64($1, $4))) { YYERROR; } }	//現在の所エラーが発生する事は無い。
//	//{{2017/09/23追加:BLOBにヌル終端文字列も含められるようにしました。
//		|                   estr xeol			{ if(!($$ = Blob_newStr( $1    ))) { YYERROR; } }	//文字列が大き過ぎたらエラーとする。
//		| blobBody ',' xeol estr xeol			{ if(!($$ = Blob_addStr( $1, $4))) { YYERROR; } }	//文字列が大き過ぎたらエラーとする。
//	//}}2017/09/23追加:BLOBにヌル終端文字列も含められるようにしました。
//		|                   file xeol			{ if(!($$ = Blob_newFile($1    ))) { YYERROR; } }	//ファイルが存在しない,又は,ファイルが大き過ぎたらエラーとする。
//		| blobBody ',' xeol file xeol			{ if(!($$ = Blob_addFile($1, $4))) { YYERROR; } }	//ファイルが存在しない,又は,ファイルが大き過ぎたらエラーとする。
//		;
//bit
//		: T_BIT   int_arg				{ $$ = Bit_new( $2); }
//		;
//byte
//		:         int_arg				{ $$ = Byte_new($1); }		//省略記法
//		| T_BYTE  int_arg				{ $$ = Byte_new($2); }
//		;
//half
//		: T_HALF  int_arg				{ $$ = Half_new($2); }
//		| T_EXP10 int_arg				{ $$ = Exp10_new($2); }		//{{2017/02/16追加:BLOBのデータ定義に'exp10'のプレフィクス指定を追加しました。}}
//		;
//word
//		: T_WORD  int_arg				{ $$ = $2; }
//		;
//ber
//		: T_BER   int_arg				{ $$ = $2; }
//		;
//fp16
//		: T_FP16  dbl_arg				{ $$ = $2; }
//		;
//fp32
//		: T_FP32  dbl_arg				{ $$ = $2; }
//		;
//fp64
//		: T_FP64  dbl_arg				{ $$ = $2; }
//		;
//file
//		: T_FILE  estr					{ $$ = $2; }
//		;
//↓2018/04/08変更:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
typedValue
		: bitValue					/* use default action */
		| byteValue					/* use default action */
		| halfValue					/* use default action */
		| exp10Value					/* use default action */
		| wordValue					/* use default action */
		| berValue					/* use default action */
		| fp16Value					/* use default action */
		| fp32Value					/* use default action */
		| fp64Value					/* use default action */
		| strValue					/* use default action */
		| fileValue					/* use default action */
		;
bitValue
		: T_BIT   int_arg				{ if(!($$ = TypedValue_newBit(  $2))) { YYERROR; } }
		;
byteValue
		: T_BYTE  int_arg				{ if(!($$ = TypedValue_newByte( $2))) { YYERROR; } }
		;
halfValue
		: T_HALF  int_arg				{ if(!($$ = TypedValue_newHalf( $2))) { YYERROR; } }
		;
exp10Value
		: T_EXP10 int_arg				{ if(!($$ = TypedValue_newExp10($2))) { YYERROR; } }
		;
wordValue
		: T_WORD  int_arg				{ if(!($$ = TypedValue_newWord( $2))) { YYERROR; } }
		;
berValue
		: T_BER   int_arg				{ if(!($$ = TypedValue_newBer(  $2))) { YYERROR; } }
		;
fp16Value
		: T_FP16  dbl_arg				{ if(!($$ = TypedValue_newFp16( $2))) { YYERROR; } }
		;
fp32Value
		: T_FP32  dbl_arg				{ if(!($$ = TypedValue_newFp32( $2))) { YYERROR; } }
		;
fp64Value
		: T_FP64  dbl_arg				{ if(!($$ = TypedValue_newFp64( $2))) { YYERROR; } }
		;
strValue
		:         estr					{ if(!($$ = TypedValue_newStr(  $1))) { YYERROR; } }
		;
fileValue
		: T_FILE  estr					{ if(!($$ = TypedValue_newFile( $2))) { YYERROR; } }
		;
typedBlock
		: bitBlock					/* use default action */
		| byteBlock					/* use default action */
		| halfBlock					/* use default action */
		| exp10Block					/* use default action */
		| wordBlock					/* use default action */
		| berBlock					/* use default action */
		| fp16Block					/* use default action */
		| fp32Block					/* use default action */
		| fp64Block					/* use default action */
		| strBlock					/* use default action */
		| fileBlock					/* use default action */
		;
bitBlock
		: T_BIT   '{' xeol bitBlockBody   '}'		{ $$ = $4; }
		;
byteBlock
		: T_BYTE  '{' xeol byteBlockBody  '}'		{ $$ = $4; }
		;
halfBlock
		: T_HALF  '{' xeol halfBlockBody  '}'		{ $$ = $4; }
		;
exp10Block
		: T_EXP10 '{' xeol exp10BlockBody '}'		{ $$ = $4; }
		;
wordBlock
		: T_WORD  '{' xeol wordBlockBody  '}'		{ $$ = $4; }
		;
berBlock
		: T_BER   '{' xeol berBlockBody   '}'		{ $$ = $4; }
		;
fp16Block
		: T_FP16  '{' xeol fp16BlockBody  '}'		{ $$ = $4; }
		;
fp32Block
		: T_FP32  '{' xeol fp32BlockBody  '}'		{ $$ = $4; }
		;
fp64Block
		: T_FP64  '{' xeol fp64BlockBody  '}'		{ $$ = $4; }
		;
strBlock
		:         '{' xeol strBlockBody   '}'		{ $$ = $3; }	//省略記法
		;
fileBlock
		: T_FILE  '{' xeol fileBlockBody  '}'		{ $$ = $4; }
		;
bitBlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newBit(  $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//bit{〜}ブロック内の暗黙の数値はbitと見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| bitBlockBody   ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newBit(  $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//bit{〜}ブロック内の暗黙の数値はbitと見なす。
		| bitBlockBody   ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| bitBlockBody   ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
byteBlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newByte( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//byte{〜}ブロック内の暗黙の数値はbyteと見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| byteBlockBody  ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newByte( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//byte{〜}ブロック内の暗黙の数値はbyteと見なす。
		| byteBlockBody  ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| byteBlockBody  ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
halfBlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newHalf( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//half{〜}ブロック内の暗黙の数値はhalfと見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| halfBlockBody  ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newHalf( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//half{〜}ブロック内の暗黙の数値はhalfと見なす。
		| halfBlockBody  ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| halfBlockBody  ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
exp10BlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newExp10($1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//exp10{〜}ブロック内の暗黙の数値はexp10と見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| exp10BlockBody ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newExp10($4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//exp10{〜}ブロック内の暗黙の数値はexp10と見なす。
		| exp10BlockBody ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| exp10BlockBody ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
wordBlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newWord( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//word{〜}ブロック内の暗黙の数値はwordと見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| wordBlockBody  ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newWord( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//word{〜}ブロック内の暗黙の数値はwordと見なす。
		| wordBlockBody  ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| wordBlockBody  ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
berBlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newBer(  $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//ber{〜}ブロック内の暗黙の数値はberと見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| berBlockBody   ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newBer(  $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//ber{〜}ブロック内の暗黙の数値はberと見なす。
		| berBlockBody   ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| berBlockBody   ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
fp16BlockBody
		:                         dbl_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newFp16( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//fp16{〜}ブロック内の暗黙の数値はfp16と見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| fp16BlockBody  ',' xeol dbl_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newFp16( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//fp16{〜}ブロック内の暗黙の数値はfp16と見なす。
		| fp16BlockBody  ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| fp16BlockBody  ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
fp32BlockBody
		:                         dbl_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newFp32( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//fp32{〜}ブロック内の暗黙の数値はfp32と見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| fp32BlockBody  ',' xeol dbl_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newFp32( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//fp32{〜}ブロック内の暗黙の数値はfp32と見なす。
		| fp32BlockBody  ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| fp32BlockBody  ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
fp64BlockBody
		:                         dbl_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newFp64( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//fp64{〜}ブロック内の暗黙の数値はfp64と見なす。
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| fp64BlockBody  ',' xeol dbl_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newFp64( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//fp64{〜}ブロック内の暗黙の数値はfp64と見なす。
		| fp64BlockBody  ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| fp64BlockBody  ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
strBlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newByte( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }	//{〜}ブロック内の暗黙の数値はbyteと見なす。	省略記法
		|                         typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| strBlockBody   ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newByte( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//{〜}ブロック内の暗黙の数値はbyteと見なす。	省略記法
		| strBlockBody   ',' xeol typedValue xeol	{                                                                                   if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| strBlockBody   ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
fileBlockBody
		:                         int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newByte( $1); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL, typedValue))) { YYERROR; } }
		|                         typedValue xeol	{ if(($1->type == ValueType_str) && !($1 = TypedValue_newFile($1->s))) { YYERROR; } if(!($$ = TypedBlock_addValue(NULL,         $1))) { YYERROR; } }	//file{〜}ブロック内の文字列はfileと見なす。file{〜}ブロック内に直接文字列を含める方法は有りません。必要ならば子ブロックを作成して下さい。<例>「file{"ファイル名",{"文字列"}}」
		|                         typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(NULL,         $1))) { YYERROR; } }
		| fileBlockBody  ',' xeol int_arg    xeol	{ ST_TypedValue* typedValue = TypedValue_newByte( $4); if(!typedValue) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1, typedValue))) { YYERROR; } }	//file{〜}ブロック内の文字列はfileと見なす。file{〜}ブロック内に直接文字列を含める方法は有りません。必要ならば子ブロックを作成して下さい。<例>「file{"ファイル名",{"文字列"}}」
		| fileBlockBody  ',' xeol typedValue xeol	{ if(($4->type == ValueType_str) && !($4 = TypedValue_newFile($4->s))) { YYERROR; } if(!($$ = TypedBlock_addValue(  $1,         $4))) { YYERROR; } }
		| fileBlockBody  ',' xeol typedBlock xeol	{                                                                                   if(!($$ = TypedBlock_addBlock(  $1,         $4))) { YYERROR; } }
		;
//}}2018/04/08変更:BLOB内の型指定の無い数値と文字列に対して、デフォルトの型を指定出来るようにしました。
xeol
		: /* empty */					/* no action */
		| xeol T_EOL					/* no action */
		;
int_arg
		: expr						/* use default action */
		| edbl						{ $$ = cast_dbl_to_int($1); }
		;
dbl_arg
		: expr						{ $$ = $1; }
		| edbl						/* use default action */
		;
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					{ 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); }
		;

%%
