2009-11-17 90 views
0

我在PHP中構建了一個僞變量解析器,允許在視圖中使用乾淨和簡單的語法,並實現了if語句的引擎。現在我希望能夠使用嵌套的if語句,我想到的最簡單,最優雅的解決方案是使用identation作爲塊的標記。在preg_match_all中使用正則表達式

所以這是basicly我正在尋找在視圖中的佈局:

{if x is empty} 
    {if y is array} 
     Hello World 
    {endif} 
{endif} 

該腳本會發現第一個if語句,並在同一深度ENDIF匹配。如果評估結果爲true,則內部塊也將被解析。

現在,我無法設置正則表達式在下面的代碼中使用深度:

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?){endif}|s', $template, $match); 

基本上我想在([\t ]?)第一場比賽到{endif}之前使用某種類型的變量被放置,並確保在與{if ...}深度相同的深度上沒有匹配的{endif}時,該聲明不會完整。

你能幫我完成嗎?

+1

你不想使用其中的一個原因? http://www.webresourcesdepot.com/19-promising-php-template-engines/ – 2009-11-17 11:39:02

+0

我正在擴展CodeIgniter內置的模板工具,並且if語句是我需要的唯一精簡版。 – Christoffer 2009-11-17 13:00:12

回答

0

\ 1將包含您的第一場比賽,所以你可以這樣做:

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?)\1{endif}|s', $template, $match); 

然而,這並不一定會匹配{} ENDIF,只有下一次出現的正確的發生是由前正確數量的選項卡。

2

對於此問題,通常不能使用正則表達式,因爲您定義的語言不規則(因爲它需要計算出現{if}{endif})。

你得到的是經典匹配圓括號問題的變體。

如果您使用某種Finite-state machine來跟蹤{if}{endif}的出現情況,那麼您最好使用這種方法。

0

如果您使用顯式的「endif」語句,您的塊已經關閉,並且不需要做任何特殊的縮進,只需匹配'/{if.+?}(.+?){endif}/ 」。 如果,在另一邊,你什麼蟒蛇,都縮進塊,你可以擺脫{ENDIF}(和括號),只有匹配縮進水平

if condition 
     this line is in the if block 
     this one too 
    this one not 

你的表情會是這樣

/([\t]+)if(.+)\n((\1[\t]+.+\n)+)/ 

「條件」將是比賽2和聲明體匹配3

其實這應該是這樣的/{if}((.(?!{if))+?){endif}/s處理嵌套,如果是正確的。