以下代码使用 my Parser class(它在 CC-BY 3.0 下),它适用于 UTF-8(感谢 my UTF8 class)。
它的工作方式是使用递归函数来迭代字符串。每次找到( 时,它都会调用自己。当它到达字符串的末尾而没有找到对应的)时,它也会检测到不匹配的对。
此外,此代码采用 $callback 参数,您可以使用它来处理它找到的每个部分。回调接收两个参数: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
);
}
}
}