CTRE 01 基本原理

2022-08-11 06:21:15 字數 2116 閱讀 8406

compile time regular expression(ctre)是乙個在編譯期生成正規表示式(regex)匹配器的c++庫。因為是在編譯期對表示式進行構建,這比很多執行期構建的regex庫要高效很多,而且**——包括生成的彙編——也更簡潔易讀,效果像這樣:

bool matched = ctre::match(str);
當然class模版引數(non type template parameter)是c++20的特性,c++17不能這樣用,而應該傳入乙個static物件的引用給模版。

經過一番搜尋,我發現網上關於ctre的學習資料幾乎等於沒有,甚至關於模版程式設計也只有大神們偶爾貼幾段**,一點解釋都沒有。這裡我嘗試重新造一遍此輪子,希望能幫到也想學習metaprogramming的你。

在模版程式設計前,我們先了解一下regex的原理。

regex的語法其實非常簡單,regex可以是

注意我們使用的regex中,a?是(\(\epsilon\)|a)的「縮寫」,a+是(a·a*)的「縮寫」。我們一般還省略concat的點號。

這個語法足以構建我們一般使用的基本的regex,當然高階特性如capture group不包含在這語法裡。

要構建regex,首先要用parser將輸入的字串轉換成ast形式。由於 我還沒學編譯原理,只知道ll(1) regex語法屬於ll(1)語法,所以我們選擇簡單的ll(1) parser即可。

ll(1) parser只需要乙個parse table,而parse table由\(firsts\)和\(follows\)得到,可以看這裡的解釋。其中用到的語法表達形式叫context free grammar (cfg),可以看這裡的解釋。

有個稍微不好理解的地方是:如果\(t'\rightarrow ft\),且\(t\)是non-terminal,那麼\(follows(f)=firsts(t)\)。如果\(firsts(t)\)含有\(\epsilon\)(空字元),則\(follows(f)\)就包含\(follows(t)\)中所有terminal。這是因為\(\epsilon\)表示\(t\)可以轉換為空字元,如果\(t\)是空的,那麼跟在\(t\)後的terminal就相當於跟在\(f\)後。

有了parse table後,就可以根據它進行stack的push和pop操作了。

regex的匹配一般是通過有限狀態機(finite automata, fa)進行的。

fa由4元組描述:(有限個狀態,狀態轉移條件,乙個起始狀態,一或多個終止狀態)。

fa從乙個初始狀態開始,然後根據狀態轉移條件轉移到下一狀態,直到到達終止狀態,可以看這個解釋。對regex來說,到達輸入末端時,fa處於終止狀態就代表匹配成功。

[0-9]+生成的fa,雙圈的圓表示終止狀態:

實際生成fa時是不斷地進行小fa的連線,連線的方法其實不太簡單,寫到這部分再說。

還有乙個問題是,fa可能存在同時可以進行幾個狀態轉移的情況,這樣的fa稱為non-determinestic fa(nfa),匹配nfa需要同時考慮多個狀態轉移進行搜尋,導致效率低。於是就出現如何將nfa轉換為狀態轉移路徑可以唯一確定的determinestic fa(dfa)的問題,這個問題也不簡單,以後再說。

總結一下我們需要實現些什麼,首先計算都是編譯期進行的,所以所有資料結構都要支援constexpr

模版引數regex是乙個字串,這個字串在編譯期即確定,所以我們需要大小固定的字串物件:class fixedstring

乙個通過過載規則描述的parse table:struct parsetable

ll(1) parser需要的編譯期棧:class stack

乙個能夠表示ast的表示式模版(expression template)

有限狀態機本身:class finiteautomata

有限狀態機的執行期匹配機制

有限狀態機需要的集合容器,同樣在編譯期即確定:class fixedset

狀態轉移的表示

mysql的基本原理 Mysql 基本原理

mysql 基本原理 mysql是一種關聯式資料庫管理系統,關聯式資料庫將資料儲存在不同的表中,而不是將所有資料放在乙個大倉庫內,這樣就增加了速度並提高了靈活性 ysql是資料庫登入命令 uroot預設超級使用者登入 p 預設沒密碼 中寫密碼 mysqladmin uroot password 12...

8 2 1 基本原理

乙個舞台動畫物件在包含許多舞台資訊 出現在何處,佔多大面積,處在什麼角度,是否可見 這些資訊分別儲存在動畫物件的屬性中。在 中讀取這些屬性可以了解物件的位置 大小 角度等狀態資訊 修改這些屬性可以改變物件的位置 大小 角度等狀態。如果從資料的角度去理解,動畫就是在固定時間間隔點不斷修改動畫物件某項屬...

Csocket基本原理

我通過幾個採用 csocket 類編寫並基於 client server 客戶端 服務端 的網路聊天和傳輸檔案的程式 在除錯這些程式的過程中,追蹤深入至 csocket 類核心原始碼 sockcore.cpp 對於csocket 類的執行機制可謂是一覽無遺,並且對於阻塞和非阻塞方式下的 socket...