我正在PHP中构建一个伪变量解析器,以允许在视图中使用干净简单的语法,并为if语句实现了一个引擎。现在我希望能够使用嵌套的if语句,我想到的最简单,最优雅的解决方案是使用identation作为块的标记。
所以这基本上是我在视图中寻找的布局:
{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}
之前,如果没有匹配的{endif}
,请确保该语句不完整与{if ...}
相同的深度。
你能帮我完成吗?
答案 0 :(得分:2)
您通常不能使用正则表达式来解决此问题,因为您定义的语言不是常规的(因为它需要计算{if}
和{endif}
的出现次数。)
您所拥有的是经典匹配括号问题的变体。
您最好使用某种Finite-state machine来跟踪{if}
和{endif}
的出现次数。
答案 1 :(得分:0)
\ 1将包含您的第一场比赛,所以您可以这样做:
preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?)\1{endif}|s', $template, $match);
但是,这不一定会匹配{endif}的正确出现次数,只会出现前面有正确数量的标签的下一次出现。
答案 2 :(得分:0)
如果你使用明确的“endif”语句,你的块已经关闭,并且没有必要做任何特殊的缩进,只需匹配'/{if.+?}(.+?){endif}/' 。 1 如果,另一方面,你是什么python-like类型缩进块,你可以摆脱{endif}(和括号),只匹配缩进级别
if condition
this line is in the if block
this one too
this one not
你的表达将是这样的
/([\t]+)if(.+)\n((\1[\t]+.+\n)+)/
“条件”将匹配2并且语句正文匹配3
1 实际上这应该像/{if}((.(?!{if))+?){endif}/s
一样来处理嵌套if。