大家來找錯 自己寫個正則引擎 二 構建抽象模式樹

2022-01-30 21:13:31 字數 2437 閱讀 2852

上一帖已經說過了大概的設計,第一步我們是要把輸入的正則式構建成抽象模式樹,我們先定義表示模式樹的類。

public enum releation

public class patternnode

public patternnode(string text)

public listnodes

public string text

public bool oneormore

public releation releation

} 基本不用解釋,屬於乙個僅用於封裝資料的類,大家可以針對命名和**布局風格挑一些刺兒。難點在於根據正則式解析成模式樹,我是這樣做的:按理說這種複雜邏輯的實現,應該先寫偽**,在腦子裡演練一番演算法,然後再寫真正的目標**,可我之前寫的偽**沒保留下來,就說說思路吧,**如下:

public static patternnode parse(string input)

要解析輸入的正則式肯定要從頭向後便利輸入的字串,由於遍歷的邏輯比較複雜,所以打算用while迴圈,比較靈活,宣告變數index用來控制迴圈,while的條件是index < input.length

考慮到小括號的影響,迴圈外要用乙個變數leftparenthesiscount來對左括號進行計數,以檢測出括號少括或者多括的錯誤正則式。

用乙個stringbuild變數currentscanstr來儲存遍歷過程中的子模式,我們叫它字模式緩衝區

迴圈過程中主要是處理"|","(",")"這3個字元,在遇到|的時候,如果左括號的個數為0,並且子模式緩衝區有資料,就把當前子模式新增到子節點中。如果左括號計數大於0,那就把當前字元放到子模式緩衝區裡,下一次遞迴解析會處理它,本次處理只處理本層的模式。

遇到(只要增加左括號計數並更新子模式緩衝區就行,但遇到)除了遞減左括號計數器外,還需要考慮括號外有閉包的情況,把*也加到子模式緩衝區裡。

每乙個層次的解析迴圈完了後要檢查左括號是否為0,如果不為0,說明少些了有括號,直接跑錯。如果迴圈完了子模式緩衝區裡還有資料,也要新增到子節點裡。

遍歷結束後,如果如果子節點數量大於1,那就說明本層的解析有或關係,就把本級節點的關係設定為or。可以看到迴圈的邏輯裡是在遇到|的時候新增子節點的。

上面這個方法基本上是只處理或的關係,可以看到上面的函式裡在沒有掃瞄出或子節點時呼叫了processandreleation,該方法去嘗試解析連線子節點,如下

private static void processandreleation(patternnode pattnode)

else

});}

else

string qukuohao = pattnode.text.substring(1, toremove);

var qukuohaonode = parse(qukuohao);

pattnode.nodes = qukuohaonode.nodes ;

pattnode.releation = qukuohaonode.releation;

pattnode.oneormore = pattnode.text.endswith("*");

}else //如"abc"

}else

}}

說實在的,這個函式折騰時間最長,基本思路和處理或子節點類似,也是乙個大迴圈,只不過處理的情況更複雜

遇到(時如果左括號為0,並且子模式緩衝區有資料,應該先把緩衝區新增到子節點,然後再把當前的字元放入緩衝區,比如abc(de(fg))取出abc

遇到)時同樣要處理括號外有*的情況,但本層之處理本層的模式,所以要確保只有最頂層的括號閉合才取出來abc(de(fg))只取(de(fg)),不取(fg)。

迴圈結束後如果有子節點,說明本層有and關係,因為本函式是通過()來進行本層的分割,也就是只解析連線子節點,如果子節點裡面如果有括號的話,肯定還有and和or的關係,所以要遍歷子節點,遞迴呼叫parse來解析本層的子模式。

如何本函式沒有解析出and子節點,那說明本層要解析的模式字串的最外層是括號括住的,要把最外層的括號去掉,然後遞迴呼叫parse方法。

我們來測試一下,給定乙個輸入,把解析出來的模式樹用treeview來表示。

private void showparsenode(patternnode pattnode, treenodecollection coll)

for (int i = 0; i < pattnode.nodes.count; i++)

} 截圖如下,可以驗證下這兩個方法的執行結果是否正確,treeview的每個節點的表示是」模式字串:子節點間關係:是否匹配多次」

這兩個函式共同組成乙個遞迴的呼叫,而且每個函式裡的if else,while都不算少,而且while裡還有break,我可以很肯定的**,儘管這段**我連寫帶除錯費了好長時間,但這段**裡肯定有低階錯誤,或者有更清晰簡單的寫法,請大家來指教一下,或者自己完全重新寫乙個更優雅的。

Nginx啟動指令碼大家來找茬

今天講到shell程式設計,我給大家講解手工開發nginx啟動指令碼時,寫的指令碼,除錯發現有問題,挺有意思的乙個問題點,有2個地方有影響啟動和停止的問題,有興趣的可以研究下,一周後公布結果!root oldboy 03 cat nginxd good bin sh retval 0 etc ini...

Nginx啟動指令碼大家來找茬

今天講到shell程式設計,我給大家講解手工開發nginx啟動指令碼時,寫的指令碼,除錯發現有問題,挺有意思的乙個問題點,有2個地方有影響啟動和停止的問題,有興趣的可以研究下,一周後公布結果!root oldboy 03 cat nginxd good bin sh retval 0 etc ini...

應用之星 新版本上線有禮 大家一起來「找茬」

一 公測內容 1.重點對製作過程進行測試,將你在使用中遇到的bug 體驗不好的地方詳細寫下來,最好有截圖 2.如果你對整個 有更好的想法,歡迎提供給我們 二 應用之星 改版介紹 三 應用之星新版本的優勢是什麼?1.製作零門檻 無需任何技術基礎,通過簡單拖拽即可快速製作,同時內建的豐富元件能夠輕鬆滿足...