0

我正在 PHP 中构建一个伪变量解析器,以允许在视图中使用简洁的语法,并为 if 语句实现了一个引擎。现在我希望能够使用嵌套的 if 语句和我想到的最简单、最优雅的解决方案是使用标识作为块的标记。

所以这基本上是我在视图中寻找的布局:

{if x is empty}
    {if y is array}
        Hello World
    {endif}
{endif}

该脚本将找到第一个 if 语句并将其与相同深度的 endif 匹配。如果它的计算结果为真,则内部块也将被解析。

现在,我在设置正则表达式以在以下代码中使用深度时遇到问题:

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?){endif}|s', $template, $match);

基本上我希望在使用某种变量([\t ]?)之前放置第一个匹配{endif}项,并确保如果没有{endif}{if ...}.

你能帮我完成吗?

4

3 回答 3

2

您通常不能对这个问题使用正则表达式,因为您定义的语言不是正则的(因为它需要计算{if}and的出现次数{endif})。

你得到的是经典匹配括号问题的变体。

您最好使用某种有限状态机来跟踪 和 的{if}出现{endif}

于 2009-11-17T11:42:50.697 回答
0

\1 将包含你的第一场比赛,所以你可以这样做:

preg_match_all('|([\t ]?){if (.+?) is (.+?)}(.+?)\1{endif}|s', $template, $match);

但是,这不一定匹配正确出现的 {endif},只会匹配前面有正确数量的制表符的下一个匹配项。

于 2009-11-17T11:45:55.397 回答
0

如果您使用显式的“endif”语句,则您的块已经关闭,无需进行任何特殊缩进,只需匹配 '/{if.+?}(.+?){endif}/'。1如果,另一方面,你有什么类似 python 的缩进块,你可以去掉 {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。

于 2009-11-17T11:59:10.677 回答