背景
在短信轉(zhuǎn)發(fā)工具TranspondSms中,實(shí)現(xiàn)了幻馁,單個(gè)匹配規(guī)則提鸟,像這樣:
一開(kāi)始是單個(gè)條件的匹配伏伐,比如 當(dāng)手機(jī)號(hào)是10086就轉(zhuǎn)發(fā) ,后面有用戶反饋說(shuō)有些短信單個(gè)條件不能篩選出來(lái)鸠补,「截圖」萝风,像這種情況,當(dāng)手機(jī)號(hào)是10086并且內(nèi)容包含欠費(fèi)就轉(zhuǎn)發(fā) 有群里用戶直接說(shuō)用正則表達(dá)式紫岩,之前有考慮一下规惰,發(fā)現(xiàn)正則表達(dá)式對(duì)普通用戶要求太高,并且不容易實(shí)現(xiàn)條件遞歸嵌套
自由度最高的就是自己實(shí)現(xiàn)一個(gè)語(yǔ)法集泉蝌,因?yàn)檫@里的場(chǎng)景很簡(jiǎn)單歇万,只是對(duì)短信進(jìn)行判斷而已,條件很少像手機(jī)號(hào)短信內(nèi)容卡槽 并且否或者 開(kāi)頭結(jié)尾包含相等 調(diào)研了一些語(yǔ)法解析器像 感覺(jué)很好用勋陪,但是用在這里有點(diǎn)殺雞用牛刀了贪磺,整理了一下要做什么決定手寫(xiě) 首先用戶輸入或選擇規(guī)則,如果要使用多級(jí)選擇框來(lái)實(shí)現(xiàn)多級(jí)嵌套界面有點(diǎn)難搞?
交互方案
遂決定直接使用文本框接受用戶提交的規(guī)則诅愚,然后對(duì)這些規(guī)則一行一行解析寒锚,然后組織嵌套關(guān)系,最后把要判斷的手機(jī)號(hào)短信內(nèi)容傳進(jìn)來(lái)進(jìn)行判斷
語(yǔ)法設(shè)計(jì)
接下來(lái)就是看怎么定義規(guī)則既語(yǔ)法呻粹,這里的嵌套情況像這種 當(dāng)手機(jī)號(hào)是10086并且(內(nèi)容包含欠費(fèi) 或者 內(nèi)容包含停機(jī)) 這里就看怎么表達(dá)這種嵌套關(guān)系壕曼,一種是直接用括號(hào)苏研,一種是模仿Python語(yǔ)法等浊,每一行代表一條規(guī)則,每一行前面用行首空格代表與上一條規(guī)則的關(guān)系摹蘑,比如兩行行首都是2個(gè)空格表示這兩行平級(jí)筹燕,逐個(gè)判斷就好,如果第一行0個(gè)空格第二行1空格衅鹿,就代表第二行規(guī)則屬于第一行規(guī)則撒踪,他們?cè)谝粋€(gè)小括號(hào)里,這樣就可以表達(dá)多個(gè)條件的優(yōu)先級(jí)了大渤。
解析
接下來(lái)是實(shí)現(xiàn)層面的設(shè)計(jì)制妄,既然每個(gè)規(guī)則有關(guān)聯(lián)比如下一個(gè)規(guī)則上一個(gè)規(guī)則子規(guī)則父規(guī)則,用一個(gè)列表肯定是不行的泵三,用樹(shù)可以耕捞,好,每個(gè)節(jié)點(diǎn)保存上個(gè)節(jié)點(diǎn)下個(gè)節(jié)點(diǎn)父節(jié)點(diǎn)子節(jié)點(diǎn)烫幕,并且保存規(guī)則本身像 并且當(dāng)手機(jī)號(hào)是10086
接下來(lái)是解析每一行 每個(gè)關(guān)鍵字用空格隔開(kāi)俺抽,考慮到用戶要求匹配的值無(wú)法想象,就把末尾的位置就給要求匹配的值较曼,每一行長(zhǎng)這個(gè)樣子 并且 不是 手機(jī)號(hào) 包含 10086hhchj紅紅火火恍恍惚惚 這里“包含”空格后面的值直接全部都是用戶要求匹配的值磷斧,這樣就減少解析用戶不確定輸入的未知風(fēng)險(xiǎn)
首先每一行一個(gè)一個(gè)字讀取,讀取有分為幾個(gè)狀態(tài),行首空格階段:用于記錄這一行有幾個(gè)行首空格弛饭,通過(guò)對(duì)比上個(gè)節(jié)點(diǎn)的行首空格數(shù)來(lái)確定和上個(gè)節(jié)點(diǎn)的關(guān)系 接著必須出現(xiàn) 并 或 兩個(gè)字之一冕末,這時(shí)階段變換行首空格階段結(jié)束,再后面一個(gè)字必須是且 者 兩個(gè)字之一孩哑,再后面必須是一個(gè)空格栓霜,這個(gè)階段是連接詞階段,用來(lái)解析出連接詞并且或者横蜒,如果不滿足這個(gè)語(yǔ)法直接輸出行號(hào)并報(bào)語(yǔ)法錯(cuò)誤:只支持并且或者 之后這個(gè)樣子依次是確認(rèn)詞階段胳蛮,匹配名階段,匹配值階段
當(dāng)各個(gè)階段都順利完成后丛晌,一條規(guī)則就生成了
連接
然后通過(guò)對(duì)比當(dāng)前規(guī)則和前一個(gè)規(guī)則的行首空格數(shù)確認(rèn)當(dāng)前規(guī)則和前一個(gè)規(guī)則的關(guān)系
最終生成一個(gè)規(guī)則樹(shù):
規(guī)則的執(zhí)行流程:
判定流程
對(duì)要判斷的短信(包含手機(jī)號(hào)仅炊,短信內(nèi)容),先執(zhí)行本節(jié)點(diǎn)的規(guī)則澎蛛,如果有子結(jié)點(diǎn)(圖中虛線指向的節(jié)點(diǎn))就遞歸合并子結(jié)點(diǎn)的規(guī)則匹配結(jié)果抚垄,如果有下一條規(guī)則(圖中實(shí)線箭頭指向的節(jié)點(diǎn))就遞歸合并下一條規(guī)則匹配結(jié)果;如果最后結(jié)果是真就轉(zhuǎn)發(fā)這條短信谋逻,為假就不轉(zhuǎn)發(fā)這條短信呆馁。
補(bǔ)充一個(gè)完整的流程圖: