gpt4 book ai didi

php - 匹配(配对)标记(例如,括号或引号)

转载 作者:搜寻专家 更新时间:2023-10-31 21:14:55 24 4
gpt4 key购买 nike

简而言之,我需要一个函数来尝试通过添加方括号/引号来修复基本代码,用于解析目的。也就是说,结果代码预计无法运行.

让我们看几个例子:

[1] class Aaa { $var a = "hi";       =>  class Aaa { $var a = "hi"; }
[2] $var a = "hi"; } => { $var a = "hi"; }
[3] class { a = "hi; function b( } => class { a = "hi; function b( }"}
[4] class { a = "hi"; function b( } => class { a = "hi"; function b() {}}

PS:上面的第4个例子看起来比较复杂,其实很简单。如果引擎发现一个与堆栈不匹配的结尾括号标记,它应该在那个标记之前找到相反的标记。如您所见,这非常有效。


作为函数签名,它看起来像:balanceTokens($code, $bracket_tokens, $quote_tokens)

我编写的函数使用堆栈工作。好吧,它并不完全有效,但它确实使用了堆栈。

function balanceTokens($code, $bracket_tokens, $quote_tokens){
$stack = array(); $last = null; $result = '';
foreach(str_split($code) as $c){
if($last==$c && in_array($c, $quote_tokens)){
// handle closing string
array_pop($stack);
}elseif(!in_array($last, $quote_tokens)){
// handle other tokens
if(isset($bracket_tokens[$c])){
// handle begining bracket
$stack[] = $c;
}elseif(($p = array_search($c, $bracket_tokens)) != false){
// handle ending bracket
$l = array_pop($stack);
if($l != $p)$result .= $p;
}elseif(isset($quote_tokens[$c])){
// handle begining quote
$stack[] = $c;
$last = $c;
}// else other token...
}
$result .= $c;
}
// perform fixes
foreach($stack as $token){
// fix ending brackets
if(isset($bracket_tokens[$token]))
$result .= $bracket_tokens[$token];
// fix begining brackets
if(in_array($token, $bracket_tokens))
$result = $token . $result;
}
return $result;
}

函数是这样调用的:

$new_code = balanceTokens(
$old_code,
array(
'<' => '>',
'{' => '}',
'(' => ')',
'[' => ']',
),
array(
'"' => '"',
"'" => "'",
)
);

是的,它非常通用,没有任何硬编码的标记。

我完全不知道为什么它不起作用...事实上,我什至不知道它是否应该起作用。我承认我没有花太多心思写它。也许有一些我没有看到的明显问题。

最佳答案

另一种实现方式(进行更积极的平衡):

function balanceTokens($code) {
$tokens = [
'{' => '}',
'[' => ']',
'(' => ')',
'"' => '"',
"'" => "'",
];
$closeTokens = array_flip($tokens);
$stringTokens = ['"' => true, '"' => true];

$stack = [];
for ($i = 0, $l = strlen($code); $i < $l; ++$i) {
$c = $code[$i];

// push opening tokens to the stack (for " and ' only if there is no " or ' opened yet)
if (isset($tokens[$c]) && (!isset($stringTokens[$c]) || end($stack) != $c)) {
$stack[] = $c;
// closing tokens have to be matched up with the stack elements
} elseif (isset($closeTokens[$c])) {
$matched = false;

while ($top = array_pop($stack)) {
// stack has matching opening for current closing
if ($top == $closeTokens[$c]) {
$matched = true;
break;
}

// stack has unmatched opening, insert closing at current pos
$code = substr_replace($code, $tokens[$top], $i, 0);
$i++;
$l++;
}

// unmatched closing, insert opening at start
if (!$matched) {
$code = $closeTokens[$c] . $code;
$i++;
$l++;
}
}
}

// any elements still on the stack are unmatched opening, so insert closing
while ($top = array_pop($stack)) {
$code .= $tokens[$top];
}

return $code;
}

一些例子:

$tests = array(
'class Aaa { public $a = "hi";',
'$var = "hi"; }',
'class { a = "hi; function b( }',
'class { a = "hi"; function b( }',
'foo { bar[foo="test',
'bar { bar[foo="test] { bar: "rgba(0, 0, 0, 0.1}',
);

将这些传递给函数给出:

class Aaa { public $a = "hi";}
{$var = "hi"; }
class { a = "hi; function b( )"}
class { a = "hi"; function b( )}
foo { bar[foo="test"]}
bar { bar[foo="test"] { bar: "rgba(0, 0, 0, 0.1)"}}

关于php - 匹配(配对)标记(例如,括号或引号),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11069142/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com