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

%union {
	int   v_num;
	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;
}
%token T_END
%token <v_num> T_NUM
%token <v_lab> T_LAB
%token <v_str> T_STR
%token T_EOL

%left '|'
%left '^'
%left '&'
%left '<' '>'
%left '+' '-'
%left '*' '/'
%nonassoc T_UPL T_UMI
%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
%type <v_num>       expr
%type <v_str>       string

%%

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 error									//全てのシンタクスエラーを報告するために継続する。
		;
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); }
		;
endRow
		: T_END T_EOL			/* no action */
		;
name
		: expr				{ $$ = Name_newExpr($1); }
		| T_LAB				{ $$ = Name_newLabel($1); }
		;
data
		: expr				{ $$ = Data_newExpr($1); }
		| T_LAB				{ $$ = Data_newLabel($1); }
		;
string
		: T_STR				{ $$ = String_intern($1); }
		;
expr
		: T_NUM
		| '(' 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; }
		;

%%
