PHP模板引擎(如果条件解析器)

时间:2018-10-31 09:36:37

标签: php parsing templates

出于学习目的,我试图编写一个简单的PHP模板解析器,并且尝试实现条件逻辑,但解析器将非常有限,但是没关系,我只是对实现自己决定的目标感兴趣。

代码如下:

$pat = '/{if (\b[A-Za-z0-9_]+\b)}(.*?){\\/if}/s';

$message = '{if another}Another{/if} {if outer}Outer {if inner}Inner {if innermost}Innermost{/if}{/if}{/if}';
$vars = ['another' => false, 'outer' => true, 'inner' => true, 'innermost' => true];

while (preg_match_all($pat, $message, $m)) {
    foreach ($m[1] as $n => $key) {
        $all = $m[0][$n];
        $text = $m[2][$n];

        if (!isset($vars[$key]) || empty($vars[$key])) {
            $message = str_replace($all, '', $message);
              } else {
                  $message = str_replace($all, $text, $message);
              }
          }
      }

      echo $message;

if条件的解析器要求:

  1. 跳过条件,如果变量值不存在或包含虚假值。
  2. 如果条件应支持嵌套。

不幸的是,我对正则表达式的理解非常有限,我只设法构造了一个简单的正则表达式(可能小于可接受的值),因此基本上我需要支持是否可以用这种格式编写条件。

{if something}某事{/ if}

从代码中可以看到,我提供了一个示例,其中message包含两个不相关的变量,并且有一个变量“ outer”,如果条件相互嵌套,则该变量包含另外两个变量。

当所有变量都包含真实值时,似乎一切正常,但是如果将变量设置为falsy值,并且该变量嵌套在内部,则$ message变量中的文本将无法正确解析。我收到了其他不必要的{/ if}关闭标签。

当我检查它检查变量值是否为空的地方时,我注意到它没有给我if条件块的正确部分,因此我可以查找和替换if条件不成立的if语句。

我以为我的正则表达式有缺陷,但是我不确定是否可以用我要问的正则表达式来实现,是否应该尝试另一种新方法,或者只有一个小的解决方案需要要做什么?

考虑到上述要求,至少我想知道正确的算法如何解决此问题。

预先感谢您可以提供给我的所有信息。

1 个答案:

答案 0 :(得分:1)

尽管大多数引擎都具有强大的扩展功能,但您不能使用正则表达式来做到这一点,有些引擎可能允许您执行此操作。有关匹配嵌套结构的详细信息,请参见this question。有关正则表达式的限制,另请参见this answer

“正确”的方法是使用解析器。对于StackOverflow答案,解析的介绍太大了。我建议阅读Engineering: A Compiler,或者阅读更轻巧(免费)的Let's Build a CompilerCrafting Interpreters

基本方法是找到模板的语法(否则,自己重建)并识别词法元素或记号。也就是说,您可以使用正则表达式来匹配{if var_name}{/if}和普通文本,然后对这些元素进行操作。分离后,问题变得容易得多。