/*****************************************************************************
 * Bison/Flexプログラム部分をテストするための、Windowsアプリケーションの雛型 *
 * □ビルド・実行方法:                                                       *
 * ┃"C:\Program Files (x86)\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT"  *
 * ┃make -f winapp.mk run                                                   *
 *****************************************************************************/
#ifndef __WINAPP_H__
#define __WINAPP_H__
/*{{定型コード:winapp.h======================================================*/
#include <clip.h>
/* y.tab.y */
extern int yynerrs;
#if     (YYDEBUG!=0)
extern int yydebug;
#endif/*(YYDEBUG!=0)*/
int yyparse();
void yyerror(const char* fmt, ...);
/* lex.yy.l */
extern FILE* yyin;
extern FILE* yyout;
extern int yylineno;
int yylex();
void yylex_init(FILE* input_file);
/*}}定型コード:winapp.h======================================================*/
//-----------------------------------------------------------------------------
//構造体定義
//-----------------------------------------------------------------------------
//状態マップ
typedef struct _ST_Map {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	char*			name;		//状態マップの名前					必須
	struct _ST_MapBody*	mapBody;	//状態マップのボディ					必須
} ST_Map;
//状態マップのボディ
typedef struct _ST_MapBody {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	struct _ST_Func*	enter;		//Enter関数						Enter関数が無ければNULL
	struct _ST_Func*	leave;		//Leave関数						Leave関数が無ければNULL
	ght_hash_table_t*	ht_transSet;	//遷移セットのハッシュテーブル				要素数(0)も許可				遷移名をキーとする。
	ght_hash_table_t*	ht_state;	//状態のハッシュテーブル				要素数(0)は不可			y.tab.yでは判断出来ないので、winapp.cで判断せよ。
} ST_MapBody;
//状態
typedef struct _ST_State {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	char*			name;		//状態の名前						必須
	struct _ST_StateBody*	stateBody;	//状態のボディ						必須
} ST_State;
//状態のボディ
typedef struct _ST_StateBody {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	struct _ST_Func*	enter;		//Enter関数						Enter関数が無ければNULL		┐
	struct _ST_Func*	leave;		//Leave関数						Leave関数が無ければNULL		├どれか一つは必須。y.tab.yでは判断出来ないので、winapp.cで判断せよ。
	ght_hash_table_t*	ht_transSet;	//遷移セットのハッシュテーブル				要素数(0)も許可			┘	遷移名をキーとする。
} ST_StateBody;
//遷移セット
typedef struct _ST_TransSet {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	char*			name;		//遷移の名前						必須
	ght_hash_table_t*	ht_trans;	//遷移のハッシュテーブル				要素数(0)には成り得ない。		ガード名をキーとする。ガードが無い遷移は長さ(0)のキーを持つ。ガード名が空文字の遷移は終端文字のみの長さ(1)のキーを持つので区別できる。
} ST_TransSet;
//遷移
typedef struct _ST_Trans {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	char*			name;		//遷移の名前						必須
	struct _ST_TransBody*	transBody;	//遷移のボディ						必須
} ST_Trans;
//遷移のボディ
typedef struct _ST_TransBody {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	struct _ST_Func* 	guard;		//Guard関数						Guard関数が無ければNULL
	struct _ST_Func*	act;		//Act関数						Act関数が無ければNULL		┬何れか一方は必須。y.tab.yでは判断出来ないので、winapp.cで判断せよ。
	struct _ST_NextState*	nextState;	//遷移先状態						遷移先状態が無ければNULL	┘
} ST_TransBody;
//関数
typedef struct _ST_Func {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	char*			name;		//ガード条件の名前					必須。命名をツールに任せる指定([],{})ならば、ツールが命名するまで""となる。
	char*			code;		//ガード条件のコード					コードが無ければNULL
	int			op;		//関数の種類						1=(void(*)(ST_FsmObj*)),2=(int(*)(ST_FsmObj*,int,void*)),3=(void(*)(ST_FsmObj*,int,void*))	1はEnter/Leave関数,2はGuard関数,3はAct関数に相当する。
} ST_Func;
//遷移先状態
typedef struct _ST_NextState {
	int			line;		//行番号。エラーメッセージのためだけに使用する。
	int			op;		//1=set,2=push,3=pop					必須
	char*			state;		//遷移先状態の名前					op=1,2の場合は必須。op=3の場合はNULL
} ST_NextState;
//-----------------------------------------------------------------------------
//グローバル関数宣言
//-----------------------------------------------------------------------------
void add_source(char* source);
void add_map(ST_Map* map);
//ST_Map
ST_Map* Map_new(char* name, ST_MapBody* mapBody);
//ST_MapBody
ST_MapBody* MapBody_new();
ST_MapBody* MapBody_addEnter(ST_MapBody* mapBody, ST_Func* enter);
ST_MapBody* MapBody_addLeave(ST_MapBody* mapBody, ST_Func* leave);
ST_MapBody* MapBody_addTrans(ST_MapBody* mapBody, ST_Trans* trans);
ST_MapBody* MapBody_addState(ST_MapBody* mapBody, ST_State* state);
//ST_State
ST_State* State_new(char* name, ST_StateBody* stateBody);
//ST_StateBody
ST_StateBody* StateBody_new();
ST_StateBody* StateBody_addEnter(ST_StateBody* stateBody, ST_Func* enter);
ST_StateBody* StateBody_addLeave(ST_StateBody* stateBody, ST_Func* leave);
ST_StateBody* StateBody_addTrans(ST_StateBody* stateBody, ST_Trans* trans);
//ST_Trans
ST_Trans* Trans_new(char* name, ST_TransBody* transBody);
//ST_TransBody
ST_TransBody* TransBody_newGuard(                         ST_Func* guard);
ST_TransBody* TransBody_newAct(                           ST_Func* act);
ST_TransBody* TransBody_newState(                         ST_NextState* nextState);
ST_TransBody* TransBody_addGuard(ST_TransBody* transBody, ST_Func* guard);
ST_TransBody* TransBody_addAct(  ST_TransBody* transBody, ST_Func* act);
ST_TransBody* TransBody_addState(ST_TransBody* transBody, ST_NextState* nextState);
//ST_Func
ST_Func* Func_new(int op, char* name, char* code);
//ST_NextState
ST_NextState* NextState_new(int op, char* state);
//-----------------------------------------------------------------------------
//変更履歴
//-----------------------------------------------------------------------------
// * Sun Jun 21 22:22:12 JST 2015 Naoyuki Sawa
// - 1st リリース。
// * Fri Jun 26 01:21:28 JST 2015 Naoyuki Sawa
// - 遷移の要素を、順不同で記述できるように変更しました。
//   これまでは、「遷移名 [ガード条件] {アクション} 遷移先状態」の順序に固定でしたが、今後は、[ガード条件]と{アクション}と遷移先状態は、任意の順序で記述できます。
//   どの順序で記述しても、生成されるデータに違いは有りません。
//   尚、[ガード条件]は省略可,{アクション}と遷移先状態は片方のみ省略可である事は、これまでどおりです。
// * Mon Jun 29 21:48:11 JST 2015 Naoyuki Sawa
// - 遷移の名前が同じで、ガード条件が異なる、遷移セットを定義出来るようにしました。
//   優先順位は、「SMC - The State Machine Compiler」(http://smc.sourceforge.net/)を参考にさせて頂きました。
//     1-1-1. 現在の状態の、指定された遷移の、ガードが有る遷移で、ガード条件が成立した遷移	複数有る場合は順不同。現在の実装ではガード名の順としているが、その挙動に依存してはいけない。
//     1-1-2. 現在の状態の、指定された遷移の、ガードが無い遷移
//     1-2-1. 状態マップの、指定された遷移の、ガードが有る遷移で、ガード条件が成立した遷移	複数有る場合は順不同。現在の実装ではガード名の順としているが、その挙動に依存してはいけない。
//     1-2-2. 状態マップの、指定された遷移の、ガードが無い遷移
//     2-1-1. 現在の状態の、デフォルト遷移の、ガードが有る遷移で、ガード条件が成立した遷移	複数有る場合は順不同。現在の実装ではガード名の順としているが、その挙動に依存してはいけない。
//     2-1-2. 現在の状態の、デフォルト遷移の、ガードが無い遷移
//     2-2-1. 状態マップの、デフォルト遷移の、ガードが有る遷移で、ガード条件が成立した遷移	複数有る場合は順不同。現在の実装ではガード名の順としているが、その挙動に依存してはいけない。
//     2-2-2. 状態マップの、デフォルト遷移の、ガードが無い遷移
//   上記の順に検索して、実行できる遷移がなかった場合は、エラー停止します。
//   詳細は、/clip/clipfsm.cのFsmObj_ApplyTrans()の実装を参照してください。
// * Wed Jul 01 21:26:23 JST 2015 Naoyuki Sawa
// - スクリプト内で、関数のコード指定を出来るようにしました。
//   処理内容が短い場合は、Sample/Sample.txtのmap6の例のように、関数のコード指定で書く方が簡潔です。
//   処理内容が複雑な場合は、これまでどおり名前指定にして、関数定義はアプリケーション内で行う方が、保守の観点から望ましいです。
// - 関数のコード指定内での改行は、当ツール自体は対応していません。			//┐×××訂正×××
//   先にCプリプロセッサを通せば、行末のバックスラッシュによる行継続は可能です。	//┘下記コメント参照
// * Wed Jul 01 21:52:52 JST 2015 Naoyuki Sawa
// - 行末のバックスラッシュで行継続する機能を追加しました。
//   有限状態機械マップスクリプトはCプリプロセッサと相性が悪く、当ツールにかける前にCプリプロセッサを通してCプリプロセッサによる行継続を適用する事が難しい事が判ったからです。
//   有限状態機械マップスクリプト内の'%{〜%}'の中でCプリプロセッサ疑似命令を使用していると、Cソースファイルに出力する前に展開されてしまい、予期しない結果になるからです。
//   上記の問題を避けるため、当ツール自体に、行末のバックスラッシュで行継続する機能を追加する事にしました。
// - '%{〜%}','[`〜`]','{`〜`}'の中は、字句解析によって行継続しますので、行末のバックスラッシュ指定は不要です。
// * Sun Jul 12 21:50:47 JST 2015 Naoyuki Sawa
// - ght_hash_table.cがght_set_rehash()に対応した事に伴い、ght_create()のサイズを明示せずオートリサイズに任せるようにしました。
// * Wed Jul 29 09:09:12 JST 2015 Naoyuki Sawa
// - これまで、[`…`],{`…`}の中に、特定のシフトJIS文字が含まれていると、コンパイルエラーになる不具合がありました。
//   具体的には、2バイト目がバッククォートの文字コード(\x60)の文字('〜','Ａ','形','伝'など)が含まれていた場合です。
// - 本日、`…`の中ではシフトJISを意識したスキャンを行うように修正したので、上記の不具合は無くなりました。
//   今後は、[`…`],{`…`}の中に、2バイト目がバッククォートの文字コード(\x60)の文字を含んでも、問題無く動作します。
// - ただし、[`…`],{`…`}の中に、「`」そのものを含むと、これまでと同様にコンパイルエラーになるので注意して下さい。
//-----------------------------------------------------------------------------
//バージョン定義
//-----------------------------------------------------------------------------
#define VERSION "20150729"
//-----------------------------------------------------------------------------
#endif/*__WINAPP_H__*/
