首先,看看pear-FSM的自帶例子examples\rpn.php php
<?php require_once 'FSM.php'; function BeginBuildNumber($symbol, $payload) { array_push($payload, $symbol); } function BuildNumber($symbol, $payload) { $n = array_pop($payload); $n = $n . $symbol; array_push($payload, $n); } function EndBuildNumber($symbol, $payload) { $n = array_pop($payload); array_push($payload, (int)$n); } function DoOperator($symbol, $payload) { $ar = array_pop($payload); $al = array_pop($payload); if ($symbol == '+') { array_push($payload, $al + $ar); } elseif ($symbol == '-') { array_push($payload, $al - $ar); } elseif ($symbol == '*') { array_push($payload, $al * $ar); } elseif ($symbol == '/') { array_push($payload, $al / $ar); } } function DoEqual($symbol, $payload) { echo array_pop($payload) . "\n"; } function Error($symbol, $payload) { echo "This does not compute: $symbol\n"; } $stack = array(); $fsm = new FSM('INIT', $stack); $fsm->setDefaultTransition('INIT', 'Error'); $fsm->addTransitionAny('INIT', 'INIT'); //若是輸入符號是"=",則從"INIT"到"INIT"狀態,並調用「DoEqual" $fsm->addTransition('=', 'INIT', 'INIT', 'DoEqual'); //若是輸入符號是0~9,從"INIT"到」BUILD_NUMBER',調用‘BeginBuildNumber’ $fsm->addTransitions(range(0,9), 'INIT', 'BUILDING_NUMBER', 'BeginBuildNumber'); //若是輸入符號是0~9, 則從"BUILDING_NUMBER",到」BUILDING_NUMBER「,調用BuildNumber $fsm->addTransitions(range(0,9), 'BUILDING_NUMBER', 'BUILDING_NUMBER', 'BuildNumber'); //輸入爲空格就從BUILDING_NUMBER回到INIT,且調用EndBuildNumber $fsm->addTransition(' ', 'BUILDING_NUMBER', 'INIT', 'EndBuildNumber'); //輸入爲加減乘除就從INIT回到INIT,調用DoOperator $fsm->addTransitions(array('+','-','*','/'), 'INIT', 'INIT', 'DoOperator'); echo "Expression:\n"; $stdin = fopen('php://stdin', 'r'); $expression = rtrim(fgets($stdin)); $symbols = preg_split('//', $expression, -1, PREG_SPLIT_NO_EMPTY); $fsm->processList($symbols);
這個例子沒有調用實例,可是能夠從代碼上看出,這是一個簡單的0~9的四則運算表達式計算器 git
在longlong ago之前,我在數據結構課學習棧和廣義表的時候學習過相似手法,下面來分析下這段代碼執行後輸入四則運算表達式的結果。 github
1. 輸入了0~9,加減乘除以外的符號,則觸發Error,到INIT狀態 express
2. INIT能夠到INIT 數據結構
3. 碰到=,DoEqual,而後回到INIT 函數
4. 在INIT和數字輸入狀態,可輸入0~9數字,轉到數字輸入階段 學習
5. 在INIT階段可輸入加減乘除,觸發DoOperator,而後能夠繼續運算 測試
6. 空格是結束 ui
經實測,(命令行下 php 你的文件目錄\fsm\rpn.php)
this
這個example有bug,要把
BeginBuildNumber
等幾個函數的參數
$payload改爲
&$payload而後輸入測試的格式是
3 4 + =
中間要有空格。
而後就能夠輸出個7
若是要進一步觀察,print_r下$fsm可大體觀察到這個狀態機的設計。
然而須要進一步注意的是,在github上有個荷蘭人提出
在fsm.php中,process函數中,
$this->_currentState = $transition[0];這句有問題,由於狀態轉換還沒有完成,我的以爲有道理,建議這裏改掉。
這裏就感受FSM的例子不是很爽,除了有bug外, 測試例子都是要摸索出來,接下來我來改改這例子,讓它好用一些。