title: FSMの実装
css: test.css

有限状態機械の実装
----------------------------------------

そこで汎用的な有限状態機械の
ためのルールを作成しました．基本的には以下の
ルールの内容がわからなくても、使い方がわかれば
使えるようにしているつもりです。

具体的な有限状態機械の定義や状態遷移表のデータは
Notation3で書きやすいようにしてあります．

JenaCheckの中で有限状態機械を同時に2つ以上
動作させることも可能にしてあります．

FSMを簡単にテストするために、三組入力の文字を
FSMの入力に変換してFSMを動作させるルールも入ってます。

FSMの状態だけではなかなか使いにくい時があるので、
FSMに変数を保存できるようにして、文字入力や出力では
それも使ってます。

以下で出てくるsttというのは
状態遷移表(stt:State Transition Table)のことですが，
正確には状態遷移表の一マス(状態遷移関数と行ったほうがよか
ったかもしれない)に対応します．

    @prefix fsm: <http://fsm.org/> .
    @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    @prefix in: <http://input.org/namespace#> .
    #状態遷移
    (?fsm rdf:type fsm:fsm)
    (?fsm fsm:status ?sb)
    noValue(?sb fsm:is fsm:old)
    (?sb fsm:status ?status)
    (?fsm fsm:input ?ib)
    noValue(?ib fsm:is fsm:old)
    (?ib fsm:input ?input1)
    (?stt rdf:type fsm:stt)
    (?stt fsm:target_fsm ?fsm)
    (?stt fsm:status ?status)
    (?stt fsm:input ?input2)
    equal(?input1,?input2)
    (?stt fsm:output ?list)
    listEntry(?list,0,?p)
    listEntry(?list,1,?o)
    (?stt fsm:next_status ?ns)
    makeTemp(?sb2)
    makeTemp(?ob)
        ->
        (?sb fsm:is fsm:old)
        (?ib fsm:is fsm:old)
        (?ob rdf:type fsm:out)
        (?ob ?p ?o)
        (?ob fsm:target_fsm ?fsm)
        (?fsm fsm:status ?sb2)
        (?sb2 fsm:status ?ns)
        .
    #状態遷移に対応しない入力があった時は，
    #その入力は消してしまう
    (?fsm rdf:type fsm:fsm)
    (?fsm fsm:status ?sb)
    noValue(?sb fsm:is fsm:old)
    (?sb fsm:status ?status)
    (?fsm fsm:input ?ib)
    noValue(?ib fsm:is fsm:old)
    (?ib fsm:input ?input)
    (?fsm fsm:inputList ?b)
    (?b fsm:status ?status)
    (?b fsm:list ?list)
    listNotContains(?list,?input)
        ->
        print('予定外の入力(',?input,')を無視します．')
        (?ib fsm:is fsm:old)
        .
    #初期インプットモード
    -> (fsm:input fsm:mode fsm:b) .
    -> (fsm:b fsm:is fsm:fsm) .
    #三つ組入力をFSMの入力に変換する
    (fsm:tripleInput fsm:bindto ?fsm)
    (fsm:input fsm:mode ?b)
    (?b fsm:is fsm:fsm)
     noValue(?b fsm:is fsm:old)
    (?inputb in:input ?x)
    noValue(?inputb in:is in:old)
    makeTemp(?ib)
        ->
        (?fsm fsm:input ?ib)
        (?ib fsm:input ?x)
        (?inputb in:is in:old)
        .
    #三つ組入力をFSMの変数に代入する
    (fsm:tripleInput fsm:bindto ?fsm)
    (fsm:input fsm:mode ?b)
    (?b fsm:is fsm:temp)
    noValue(?b fsm:is fsm:old)
    (?b fsm:var ?var)
    (?inputb in:input ?x)
    noValue(?inputb in:is in:old)
    makeTemp(?ib)
    makeTemp(?bb)
    makeTemp(?inputb2)
        ->
        (?inputb in:is in:old)
        (?fsm fsm:var ?ib)
        (?ib ?var ?x)
        (?b fsm:is fsm:old)
        (fsm:input fsm:mode ?bb)
        (?bb fsm:is fsm:fsm)
        (?fsm fsm:input ?inputb2)
        (?inputb2 fsm:input '@finished@')
        .
    #以下，FSMの出力処理で指定できるルール
    #
    #fsm:nop なにもしない
    #状態の遷移だけさせたい時に使う
    (?b rdf:type fsm:out)
    noValue(?b fsm:is fsm:fin)
    (?b fsm:nop ?x)
    (?b fsm:target_fsm ?fsm)
    makeTemp(?ib)
        ->
        (?b fsm:is fsm:fin)
        (?fsm fsm:input ?ib)
        (?ib fsm:input '@finished@')
        .
    #fsm:print 単純文字出力
    (?b rdf:type fsm:out)
    noValue(?b fsm:is fsm:fin)
    (?b fsm:print ?x)
    (?b fsm:target_fsm ?fsm)
    makeTemp(?ib)
        ->
        print(?x)
        (?b fsm:is fsm:fin)
        (?fsm fsm:input ?ib)
        (?ib fsm:input '@finished@')
        .
    #fsm:read 文字入力
    #(fmsの変数(引数で指定)に代入される)
    (?b rdf:type fsm:out)
    noValue(?b fsm:is fsm:fin)
    (?b fsm:read ?var)
    (fsm:input fsm:mode ?b2)
    (?b2 fsm:is fsm:fsm)
    noValue(?b2 fsm:is fsm:old)
    makeTemp(?b3)
        ->
        (?b2 fsm:is fsm:old)
        (fsm:input fsm:mode ?b3)
        (?b3 fsm:is fsm:temp)
        (?b3 fsm:var ?var)
        (?b fsm:is fsm:fin)
        .
    #fsm:varPrint 変数(引数で指定)の出力
    (?b rdf:type fsm:out)
    noValue(?b fsm:is fsm:fin)
    (?b fsm:varPrint ?var)
    (?b fsm:target_fsm ?fsm)
    (?fsm fsm:var ?b2)
    noValue(?b2 fsm:is fsm:old)
    (?b2 ?var ?value)
    makeTemp(?ib)
        ->
        print(?value)
        (?b fsm:is fsm:fin)
        (?fsm fsm:input ?ib)
        (?ib fsm:input '@finished@')
        .
    #fsm:bind 変数に値を代入
    (?b rdf:type fsm:out)
    noValue(?b fsm:is fsm:fin)
    (?b fsm:bind ?list)
    listEntry(?list,0,?var)
    listEntry(?list,1,?value)
    (?b fsm:target_fsm ?fsm)
    makeTemp(?vb)
    makeTemp(?ib)
        ->
        (?fsm fsm:var ?vb)
        (?vb ?var ?value)
        (?b fsm:is fsm:fin)
        (?fsm fsm:input ?ib)
        (?ib fsm:input '@finished@')
        .
    #fsm:unbind 変数を消去
    (?b rdf:type fsm:out)
    noValue(?b fsm:is fsm:fin)
    (?b fsm:unbind ?var)
    (?b fsm:target_fsm ?fsm)
    (?fsm fsm:var ?vb)
    (?vb ?var ?value)
    noValue(?vb fsm:is fsm:old)
    makeTemp(?ib)
        ->
        (?vb fsm:is fsm:old)
        (?b fsm:is fsm:fin)
        (?fsm fsm:input ?ib)
        (?ib fsm:input '@finished@')
        .

FSMが実行できる出力処理としてfsm:nop，fsm:print，fsm:input，
fsm:read，fsm:varPrint，fsm:bind，fsm:unbindを書きましたが，
これに加えてユーザが自分でoutputを定義して使うこともできます．

