I’m using the preg_replace_callback
to replace the results of the tests in the $regexList
.
[...] The problem is that this function picks up the occurrence of the first Pattern in $regexList
, instead of taking the first occurrence in $string
that has a Pattern on $regexList
.
Use only one regex.
In this case, do not use an array. Instead:
$regexList = [
'/regex1/',
'/regex2/',
'/regex3/',
];
Use this:
$regex = '/regex1|regex2|regex3/';
In function:
$resultado = preg_replace_callback(
$regex,
function ($matches) {
// ...
return 'substituído';
},
$texto
);
But how do you know which regex was found?
You can use groups to identify them.
$regex = '/(regex1)|(regex2)|(regex3)/';
So:
$resultado = preg_replace_callback(
$regex,
function ($matches) {
if ($matches[1]) {
return 'regex1 substituído';
} else if ($matches[2]) {
return 'regex2 substituído';
} else if ($matches[3]) {
return 'regex3 substituído';
}
},
$texto
);
But you have other groups in the patterns, and counting the right group number can be tricky. We can use appointed groups to make things easier.
$regex = '/(?P<padrao1>regex1)|(?P<padrao2>regex2)|(?P<padrao3>regex3)/';
$resultado = preg_replace_callback(
$regex,
function ($matches) {
if ($matches['padrao1']) {
return 'regex1 substituído';
} else if ($matches['padrao2']) {
return 'regex2 substituído';
} else if ($matches['padrao3']) {
return 'regex3 substituído';
}
},
$texto
);
Code
To answer your question, with a little recursion:
function analisar( $string ) {
$regex = '/
(?P<var> {{\s*\$(.*?)\s*}} )
|
(?P<loop> @for\((.*?)\)\s*{{((?:[^{}]|(?R))*)}} )
|
(?P<statement> @if\((.*?)\)\s*{{((?:[^{}]|(?R))*)}} )
/x';
$resultado = preg_replace_callback(
$regex,
function ($matches) {
/*
//debug
echo "\n\nSubst: $matches[0]\n\$matches = ";
var_export($matches);
*/
if ($matches['var']) {
return getVar($matches[2]);
} else if ($matches['loop']) {
return loop($matches[4], $matches[5]);
} else if ($matches['statement']) {
return getStatementResult($matches[7], $matches[8]);
}
},
$string
);
return $resultado;
}
function getVar($nomeDaVariavel){
return 'VAR('
. analisar($nomeDaVariavel)
. ')';
}
function loop($nomeDoArray, $codigo){
return "LOOP\nLOOP-COND("
. analisar($nomeDoArray)
. ")\nLOOP-CODIGO("
. analisar($codigo)
. ')';
}
function getStatementResult($expressãoBooleana, $codigo){
return "IF\nIF-COND("
. analisar($expressãoBooleana)
. ")\nIF-CODIGO("
. analisar($codigo)
. ')';
}
Testing:
$string = '
<span>{{ $nomeCompleto }}</span>
@for($nomes as $nome)
{{
@if($nome == \'Eleandro\')
{{
<p>{{ $nome }}</p>
}}
}}
';
echo analisar($string);
Upshot:
<span>VAR(nomeCompleto)</span>
LOOP
LOOP-COND($nomes as $nome)
LOOP-CODIGO(
IF
IF-COND($nome == 'Eleandro')
IF-CODIGO(
<p>VAR(nome)</p>
)
)
Demo: https://ideone.com/pBfQBP
In this case, it would be interesting to use the interpreter pattern, because it is evident that your problem generates a Composite structure. At the moment, I’m running out of time to formulate a solution.
– Gabriel Heming
I am not understanding your question, the Regexlist has 3 Regex’s inside it, why not call only one of them when there is the need and assign in the variable, using it at the time you need? There is no method that makes the code "read" from top to bottom, it already does it naturally, just you structure correctly.
– Paz
@I’m using preg_replace_callback to replace the results of Patterns who are in the $regexList. As you can see here, that one function also receives a array with Patterns_ (in case the $regexList. The problem is that function takes the occurrence of the first Pattern in $regexList, instead of picking up the first occurrence in $string that has a Pattern in the $regexList, understands?
– e200
I don’t know what I can find first on $string, can be a @if, one @for or a {{$var}}, but I know that I must replace the occurrences that appear first on $string, in the case, the first occurrence would be **{$var}}, then I would replace {{$var}} with something, the second would be @for, then I’d run the loop, and so on... This is what I’m not getting.
– e200