出于学习目的,我试图编写一个简单的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条件的解析器要求:
不幸的是,我对正则表达式的理解非常有限,我只设法构造了一个简单的正则表达式(可能小于可接受的值),因此基本上我需要支持是否可以用这种格式编写条件。
{if something}某事{/ if}
从代码中可以看到,我提供了一个示例,其中message包含两个不相关的变量,并且有一个变量“ outer”,如果条件相互嵌套,则该变量包含另外两个变量。
当所有变量都包含真实值时,似乎一切正常,但是如果将变量设置为falsy值,并且该变量嵌套在内部,则$ message变量中的文本将无法正确解析。我收到了其他不必要的{/ if}关闭标签。
当我检查它检查变量值是否为空的地方时,我注意到它没有给我if条件块的正确部分,因此我可以查找和替换if条件不成立的if语句。
我以为我的正则表达式有缺陷,但是我不确定是否可以用我要问的正则表达式来实现,是否应该尝试另一种新方法,或者只有一个小的解决方案需要要做什么?
考虑到上述要求,至少我想知道正确的算法如何解决此问题。
预先感谢您可以提供给我的所有信息。
答案 0 :(得分:1)
尽管大多数引擎都具有强大的扩展功能,但您不能使用正则表达式来做到这一点,有些引擎可能允许您执行此操作。有关匹配嵌套结构的详细信息,请参见this question。有关正则表达式的限制,另请参见this answer。
“正确”的方法是使用解析器。对于StackOverflow答案,解析的介绍太大了。我建议阅读Engineering: A Compiler,或者阅读更轻巧(免费)的Let's Build a Compiler或Crafting Interpreters。
基本方法是找到模板的语法(否则,自己重建)并识别词法元素或记号。也就是说,您可以使用正则表达式来匹配{if var_name}
,{/if}
和普通文本,然后对这些元素进行操作。分离后,问题变得容易得多。