2012-03-02 229 views
3

給定C#中的正則表達式,是否有一種方法可以生成被此正則表達式接受的單詞?正則表達式:語言生成器

例如,讓我們考慮:

[ab]c*b* 

是否有可以自動生成像枚舉函數:

a 
b 
ac 
ab 
bc 
bb 
acb 
bcb 
acc 
bcc 
... 

顯然,這個名單是無限的潛在的,長期的AS-的你想要的話,發電機必須是聰明的,以便從最簡單的到最複雜的輸出,而不會陷入無限循環。

我認爲這將是一個有用的工具,以驗證正則表達式。一般而言,很容易看到正則表達式接受您計劃接受的單詞。通常要看到它會接受的其他詞彙更加困難。

編輯:這個問題不是關於如何做到這一點,而是:有沒有什麼可以用來在C#中使用它?

+1

尋找解決[停止問題](http://en.wikipedia.org/wiki/Halting_problem)? – Oded 2012-03-02 15:09:11

+0

正則表達式不完整。編輯:一般的正則表達式並不完整。如果C#允許你編寫完整的圖靈,那麼是的,這是一個問題,這些功能將不得不被禁止。 – zmccord 2012-03-02 15:16:00

+0

哦,我看到這也是一個部分愚弄http://stackoverflow.com/questions/4208733/generative-regular-expressionions – zmccord 2012-03-02 15:19:52

回答

1

這甚至不是C#特有的問題;我認爲你可以用任何真正的正則表達式來做到這一點。

在我看來,你應該能夠告訴任何正則表達式匹配的世代故事,這只是一個重寫列表。在你的例子中[ab]c*b*可以生成acccbbb;那就是[ab]c*b* - >ac*b* - >acccb* - >acccbbb。對於每個運營商,我們可以想象它列舉了它重寫的所有方式;那麼這只是一個枚舉重寫的所有組合的問題,歸結爲列舉所有N元組的自然數。

編輯:自然的N元組是glib比較。但是你可以想象,基本上在重寫狀態上執行廣度優先遍歷,輸出每個字符串,所有操作符都被重寫。

+0

您可以將您的正則表達式轉換爲有限狀態自動機,然後用某種啓發式方法來探索圖。但是,真的,我沒有時間自己做;) – 2012-03-02 15:59:23

0

我不知道如何在C#中做到這一點,但理論上是的,它可以做到。

您需要將您的正則表達式轉換爲NFA或DFA圖形,橫向使用BFS跟蹤當前路徑,爲每條邊添加一個新字符,並在完成節點時打印當前路徑被擊中。根據手頭的正則表達式,您的內存使用情況可以輕鬆呈指數增長。

例如,給定的正則表達式(a|b)*abb我們可以創建一個NFA圖表如下所示:

NFA for <code>(a|b)*abb</code>

這NFA圖形既可以採用識別一個單詞,枚舉所有可能的單詞。我們通過非確定性遍歷圖來做到這一點。意思是,我們需要跟蹤圖表中所有可能的路徑。

從零開始,我們做一個BFS,並且對於每個有兩個或更多輸出邊的節點,我們創建一個新的非確定性路徑。所述BFS訪問該節點按照下面的順序,每次打印:

0, 1, 7, 2, 4, 8, 3, 5, 9, 6, 6, 10, 1, 1, 7, ... 

對於每個節點訪問我們有中間臨時路徑爲:

  • 0 「」
  • 1中,「E 「
  • 7, 」E「
  • 2, 」EE「
  • 4, 」EE「
  • 8,」 E一個」
  • 3, 「EEA」
  • 5中, 「EEB」
  • 9中, 「EAB」
  • 6中, 「eeae」
  • 6中, 「eebe」
  • 10 「eabb」
  • 1 「eeaee」
  • 1 「eebee」

在 「E」 符號是表示空字符串0123的ε-信,應在打印每個單詞時將其過濾掉。

通過在圖上做一個BFS,我們將每個單詞按照需要用NFA識別單詞的邊的數量進行排序。由於圖形包含一個循環,因此該過程永遠不會結束。

每一次每一個不確定的路徑到達我們打印生成的字符串結束節點10:

  • 「ABB」
  • 「AABB」
  • 「BABB」