ゆうげんおーとまとん - folklorecrysisprogrammer/folklorecrisis GitHub Wiki
【拡張有限オートマトン】
有限オートマトン的なのを実装します。(恐らく、決定性有限オートマトン)
状態Aの時1が入力されると状態がBになるオートマトンを定義するなら、
A.setRule(input(1)>>_state(B));
↑このようになります
以下は詳細な解説です。
【ルール書き方】
Rule=input(入力名)>>アクション>>アクション.....
さらに、|を使って複数のRuleを結合できます。
Rule3=
Rule1 |
Rule2 |
input(KFC)>>_state(マクドナルド);
【アクションの型】
アクションの型は、以下の型の関数を返すクラスとする。
遷移時にはこの関数が呼ばれるとする。
/関数の型
ienumerator<bool> (Trigger)
この関数の返り値が
yield return falseまたは yield breakで
終了します。
yield return trueの場合は遷移は遅延され、
この関数は再び呼ばれます。
【Ruleが提供する処理】
/x状態をセットする
/これが呼ばれたら以降のアクションは無視される
setState(x)
/現在の状態を取得する
getState()
/これが呼ばれたら遷移中止。
Cancel()
【標準用意のアクション】
/xフレーム遅延
/遅延してる間に新しい入力があった場合、
/現在の遷移を破棄し、新しい入力の方に切り替える。
/(この遷移破棄は全ての遅延するアクションで起こります)
_lazy(x)
/x状態をセット
/setStateを呼んでるのでこれ以降のアクションは呼ばれない
_state(x)
/現在の状態とxが同じなら、cancel()する
_sameStateCancel(x)
【状態にルールを適応させる】
/定義したルールを状態にセットします
/デフォルト入力は、何も入力されなかった時に入力される値です。省略できます。
/省略した場合本当に何も入力されません。
状態.setRule(ルール,デフォルト入力)
【例】
/ルール定義
moveRule=
input(前)>>
_sameStateCancel(前歩行)>>
_state(前歩行)|
input(後)>>
_sameStateCancel(後歩行)>>
_state(後歩行)|
input(右)>>
_sameStateCancel(右歩行)>>
_state(右歩行)|
input(左)>>
_sameStateCancel(左歩行)>>
_state(左歩行);
/各状態にルール適応
前歩行.setRule(
moveRule|
input(止)>>
lazy(10)>>
_state(前立ち止まり)
);
後歩行.setRule(moveRule);
左歩行.setRule(moveRule);
右歩行.setRule(moveRule);
public:
void Run() { sm.SetOrderVector(ov); sm.Run(); }
Script() :Script::base_type(Code) {
std::vector<int> v = {1,2,3};
using boost::phoenix::ref;
using spt::qi::eps;
using spt::qi::lit;
using spt::qi::_1;
using spt::qi::_val;
using spt::qi::double_;
using spt::qi::bool_;
using spt::qi::int_;
using spt::qi::alpha;
using spt::qi::as_string;
using spt::ascii::char_;
spt::qi::standard_wide::char_type wchar_;
using spt::qi::real_parser;
using spt::qi::strict_real_policies;
real_parser<double, strict_real_policies<double>> strict_double;
Code =
*(
(DC >> lit(';'))
|
(-(Label[AddOrderLabel()]>>lit(' '))>>Order[AddOrder()] >> lit(';'))
|
(Comment)
);
NullChar = lit("\\0")[_val = '\0'];
EndLineChar = lit("\\n")[_val='\n'];
Char = lit('\'') >>(NullChar|EndLineChar|char_)-'\''>> lit('\'');
Value = strict_double | int_| Char|bool_;
ValueAdr = Value[_val = BindValueAdr::Make(sm)] | String[_val=BindStringAdr::Make(sm)];
DC =
(Label >> lit(' ') >> lit("idc") >> lit(' ') >> int_%',')[BindDCV::Make<int>(sm)] |
(Label >> lit(' ') >> lit("ddc") >> lit(' ') >> double_%',')[BindDCV::Make<double>(sm)] |
(Label >> lit(' ') >> lit("bdc") >> lit(' ') >> bool_%',')[BindDCV::Make<bool>(sm)] |
(Label >> lit(' ') >> lit("cdc") >> lit(' ') >> Char%',')[BindDCV::Make<char>(sm)]|
(Label >> lit(' ') >> lit("cdc") >> lit(' ') >> String)[BindDCV::Make<char>(sm)];
Label =as_string[(+(char_('A', 'Z')))];
String= lit('"')>>(+((NullChar|EndLineChar|char_|wchar_)-'"'))>> lit('"');
Comment = lit("/*") >>*((char_|wchar_)-"*/")>> lit("*/");
LabelAdr = Label[_val = BindLabelAdr::Make(sm)];
Register =
lit("ax")[_val = sm.GetAX()] |
lit("gr1")[_val = sm.GetGR(1)] |
lit("gr2")[_val = sm.GetGR(2)] |
lit("gr3")[_val = sm.GetGR(3)] |
lit("gr4")[_val = sm.GetGR(4)] |
lit("gr5")[_val = sm.GetGR(5)] |
lit("gr6")[_val = sm.GetGR(6)] |
lit("gr7")[_val = sm.GetGR(7)] |
lit("gr8")[_val = sm.GetGR(8)];
Adr = LabelAdr | Register|ValueAdr;
Args1 = (Adr >> lit(' ') >> Adr)[_val = BindArgs1::Make()];
Args3 = (Adr >> lit(' ') >> Adr >> lit(' ') >> Adr)[_val = BindArgs3::Make()];
Args4 = (Adr >> lit(' ') >> Adr >> lit(' ') >> Adr >> lit(' ') >> Adr)[_val = BindArgs4::Make()];
Args5 = (Adr)[_val=BindArgs5::Make()];
Args = (Args1 | Args3 | Args4 | Args5);
Order = (PRINT|ADD|LD|LDR|JMP|JMPB|CPAEQ|CPANEQ|INC|PUSH|POP|REF|DREF|CAST);
JMP = lit("jmp") >> lit(' ') >> Args[_val = BindJMP::Make(sm)];
JMPB = lit("jmpb") >> lit(' ') >> Args[_val = BindJMPB::Make(sm)];
PRINT =
(lit("iprint") >> lit(' ') >> Args[_val = BindPRINT<int>::Make()])|
(lit("dprint") >> lit(' ') >> Args[_val = BindPRINT<double>::Make()])|
(lit("bprint") >> lit(' ') >> Args[_val = BindPRINT<bool>::Make()])|
(lit("cprint") >> lit(' ') >> Args[_val = BindPRINT<char>::Make()])|
(lit("sprint") >> lit(' ') >> Args[_val = BindSPRINT::Make()]);
LD=
(lit("ild") >> lit(' ') >> Args[_val = BindLD<int>::Make()]) |
(lit("dld") >> lit(' ') >> Args[_val = BindLD<double>::Make()]) |
(lit("bld") >> lit(' ') >> Args[_val = BindLD<bool>::Make()]) |
(lit("cld") >> lit(' ') >> Args[_val = BindLD<char>::Make()]);
LDR =
(lit("ildr") >> lit(' ') >> Args[_val = BindLDR<int>::Make()]) |
(lit("dldr") >> lit(' ') >> Args[_val = BindLDR<double>::Make()]) |
(lit("bldr") >> lit(' ') >> Args[_val = BindLDR<bool>::Make()]) |
(lit("cldr") >> lit(' ') >> Args[_val = BindLDR<char>::Make()]);
ADD =
(lit("iadd") >> lit(' ') >> Args[_val = BindADD<int>::Make()]) |
(lit("dadd") >> lit(' ') >> Args[_val = BindADD<double>::Make()]) |
(lit("badd") >> lit(' ') >> Args[_val = BindADD<bool>::Make()]) |
(lit("cadd") >> lit(' ') >> Args[_val = BindADD<char>::Make()]) |
(lit("padd") >> lit(' ') >> Args[_val = BindADD<char*>::Make()]);
PUSH =
(lit("ipush") >> lit(' ') >> Args[_val = BindPUSH<int>::Make(sm)]) |
(lit("dpush") >> lit(' ') >> Args[_val = BindPUSH<double>::Make(sm)]) |
(lit("bpush") >> lit(' ') >> Args[_val = BindPUSH<bool>::Make(sm)]) |
(lit("cpush") >> lit(' ') >> Args[_val = BindPUSH<char>::Make(sm)]);
POP =
(lit("ipop") >> lit(' ') >> Args[_val = BindPOP<int>::Make(sm)]) |
(lit("dpop") >> lit(' ') >> Args[_val = BindPOP<double>::Make(sm)]) |
(lit("bpop") >> lit(' ') >> Args[_val = BindPOP<bool>::Make(sm)]) |
(lit("cpop") >> lit(' ') >> Args[_val = BindPOP<char>::Make(sm)]);
INC =
(lit("iinc") >> lit(' ') >> Args[_val = BindINC<int>::Make()]) |
(lit("dinc") >> lit(' ') >> Args[_val = BindINC<double>::Make()]) |
(lit("binc") >> lit(' ') >> Args[_val = BindINC<bool>::Make()]) |
(lit("cinc") >> lit(' ') >> Args[_val = BindINC<char>::Make()]);
CPAEQ =
(lit("icpaeq") >> lit(' ') >> Args[_val = BindCPAEQ<int>::Make(sm)]) |
(lit("dcpaeq") >> lit(' ') >> Args[_val = BindCPAEQ<double>::Make(sm)]) |
(lit("bcpaeq") >> lit(' ') >> Args[_val = BindCPAEQ<bool>::Make(sm)]) |
(lit("ccpaeq") >> lit(' ') >> Args[_val = BindCPAEQ<char>::Make(sm)]);
CPANEQ =
(lit("icpaneq") >> lit(' ') >> Args[_val = BindCPANEQ<int>::Make(sm)]) |
(lit("dcpaneq") >> lit(' ') >> Args[_val = BindCPANEQ<double>::Make(sm)]) |
(lit("bcpaneq") >> lit(' ') >> Args[_val = BindCPANEQ<bool>::Make(sm)]) |
(lit("ccpaneq") >> lit(' ') >> Args[_val = BindCPANEQ<char>::Make(sm)]);
REF =
(lit("ref") >> lit(' ') >> Args[_val = BindREF::Make()]);
DREF =
(lit("idref") >> lit(' ') >> Args[_val = BindDREF<int>::Make()]) |
(lit("ddref") >> lit(' ') >> Args[_val = BindDREF<double>::Make()]) |
(lit("bdref") >> lit(' ') >> Args[_val = BindDREF<bool>::Make()]) |
(lit("cdref") >> lit(' ') >> Args[_val = BindDREF<char>::Make()]) |
(lit("pdref") >> lit(' ') >> Args[_val = BindDREF<void*>::Make()]);
CAST =
(lit("icastd") >> lit(' ') >> Args[_val = BindCAST<int, double>::Make()]) |
(lit("dcasti") >> lit(' ') >> Args[_val = BindCAST<double, int>::Make()]) |
(lit("icastc") >> lit(' ') >> Args[_val = BindCAST<int, char>::Make()]) |
(lit("ccasti") >> lit(' ') >> Args[_val = BindCAST<char, int>::Make()]) |
(lit("icastb") >> lit(' ') >> Args[_val = BindCAST<int, bool>::Make()]) |
(lit("bcasti") >> lit(' ') >> Args[_val = BindCAST<bool, int>::Make()]) |
(lit("dcastc") >> lit(' ') >> Args[_val = BindCAST<double, char>::Make()]) |
(lit("ccastd") >> lit(' ') >> Args[_val = BindCAST<char, double>::Make()]) |
(lit("dcastb") >> lit(' ') >> Args[_val = BindCAST<double, bool>::Make()]) |
(lit("bcastd") >> lit(' ') >> Args[_val = BindCAST<bool, double>::Make()]) |
(lit("ccastb") >> lit(' ') >> Args[_val = BindCAST<char, bool>::Make()]) |
(lit("bcastc") >> lit(' ') >> Args[_val = BindCAST<bool, char>::Make()]);
}
//scriptコード全体をまとめる文法
spt::qi::rule<Iterator>Code;
//DC 命令
spt::qi::rule<Iterator>DC;
//PRINT命令
spt::qi::rule<Iterator,OrderBase*>PRINT;
//LD命令
spt::qi::rule<Iterator, OrderBase*>LD;
//LDA命令
spt::qi::rule<Iterator, OrderBase*>LDR;
//ADD命令
spt::qi::rule<Iterator, OrderBase*>ADD;
//INC命令
spt::qi::rule<Iterator, OrderBase*>INC;
//PUSH命令
spt::qi::rule<Iterator, OrderBase*>PUSH;
//POP命令
spt::qi::rule<Iterator, OrderBase*>POP;
//CPAEQ命令
spt::qi::rule<Iterator, OrderBase*>CPAEQ;
//CPANEQ命令
spt::qi::rule<Iterator, OrderBase*>CPANEQ;
//JMP命令
spt::qi::rule<Iterator, OrderBase*>JMP;
//JMPB命令
spt::qi::rule<Iterator, OrderBase*>JMPB;
//REF命令
spt::qi::rule<Iterator, OrderBase*>REF;
//DREF命令
spt::qi::rule<Iterator, OrderBase*>DREF;
//CAST命令
spt::qi::rule<Iterator, OrderBase*>CAST;
//実行命令
spt::qi::rule<Iterator, OrderBase*>Order;
//ラベル
spt::qi::rule<Iterator,std::string()>Label;
//ラベルが指すアドレス
spt::qi::rule<Iterator, void*>LabelAdr;
//レジスタのアドレス
spt::qi::rule<Iterator, void*>Register;
//アドレス
spt::qi::rule<Iterator, void*>Adr;
//Arg<1>
spt::qi::rule<Iterator, Args<1>()>Args1;
//Arg<3>
spt::qi::rule<Iterator, Args<3>()>Args3;
//Arg<4>
spt::qi::rule<Iterator, Args<4>()>Args4;
//Arg<5>
spt::qi::rule<Iterator, Args<5>()>Args5;
//Args<...>
spt::qi::rule<Iterator, VarArgs()>Args;
//char形式
spt::qi::rule<Iterator,char()>Char;
//null文字
spt::qi::rule<Iterator, char()>NullChar;
//改行文字
spt::qi::rule<Iterator, char()>EndLineChar;
//文字列
spt::qi::rule<Iterator, std::vector<char>>String;
//コメント
spt::qi::rule<Iterator>Comment;
//即値
spt::qi::rule<Iterator, VarValue>Value;
//即値アドレス
spt::qi::rule<Iterator, void*>ValueAdr;