下面的代碼使用我Parser class from Paladio(這是在CC-BY 3.0),它適用於UTF-8。
它的工作方式是通過使用遞歸函數遍歷字符串。它會在每次找到(
時調用它自己。它還會在到達字符串末尾時檢測到不匹配對,但未找到相應的)
。
此外,此代碼需要一個$回調參數,您可以使用它來處理它找到的每個部分。回調接收兩個參數:1)字符串,2)等級(0 =最深)。無論回調返回將在字符串的內容中被替換(這種更改在更高級別的回調中可見)。
注意:代碼不包括類型檢查。
非遞歸部分:
function ParseParenthesis(/*string*/ $string, /*function*/ $callback)
{
//Create a new parser object
$parser = new Parser($string);
//Call the recursive part
$result = ParseParenthesisFragment($parser, $callback);
if ($result['close'])
{
return $result['contents'];
}
else
{
//UNEXPECTED END OF STRING
// throw new Exception('UNEXPECTED END OF STRING');
return false;
}
}
遞歸部分:
function ParseParenthesisFragment(/*parser*/ $parser, /*function*/ $callback)
{
$contents = '';
$level = 0;
while(true)
{
$parenthesis = array('(', ')');
// Jump to the first/next "(" or ")"
$new = $parser->ConsumeUntil($parenthesis);
$parser->Flush(); //<- Flush is just an optimization
// Append what we got so far
$contents .= $new;
// Read the "(" or ")"
$element = $parser->Consume($parenthesis);
if ($element === '(') //If we found "("
{
//OPEN
$result = ParseParenthesisFragment($parser, $callback);
if ($result['close'])
{
// It was closed, all ok
// Update the level of this iteration
$newLevel = $result['level'] + 1;
if ($newLevel > $level)
{
$level = $newLevel;
}
// Call the callback
$new = call_user_func
(
$callback,
$result['contents'],
$level
);
// Append what we got
$contents .= $new;
}
else
{
//UNEXPECTED END OF STRING
// Don't call the callback for missmatched parenthesis
// just append and return
return array
(
'close' => false,
'contents' => $contents.$result['contents']
);
}
}
else if ($element == ')') //If we found a ")"
{
//CLOSE
return array
(
'close' => true,
'contents' => $contents,
'level' => $level
);
}
else if ($result['status'] === null)
{
//END OF STRING
return array
(
'close' => false,
'contents' => $contents
);
}
}
}
我寫了一個SQL解析器,需要遞歸地執行此操作。使用正則表達式遞歸函數要比使用正則表達式遞歸地執行遞歸函數要容易得多。 – EdgeCase
你在吠叫錯誤的樹,純粹的正則表達式解決方案可能會過於複雜和難以維護。你會更好地遞歸解析字符串。 – GordonM
不要......好吧,理論上它可以完成,但是當你設法做到這一點時,它可能看起來就像是gl。一樣。哦,看看我們在正則表達式中發現了一個錯誤!恩......你怎麼解決這個問題?噢,我們還需要增加對brakets的支持!恩......你怎麼補充的?我告訴你,你最好使用更易讀的解析器。你問這個事實,表明你可能無法維護它。 – Theraot