出于教育目的,我尝试构建PUG Parser。 我有两个循环,一个循环PUG-Code的行,另一个循环unclosed标签,我保存最后一次迭代。
在我的代码中,内部循环似乎只运行一次,因为当我将echo
语句用于调试时,我没有获得足够的输出。
foreach ($lines as $line) {
#Increment the line number
$lineNum++;
#Save the current indentation for later use
$currentIndentation = strspn($line, " ");
#Go though list of unclosed tags and recursivley close all that need to be closed
foreach ($unclosed_tags as $lineNum => $tag) {
#Assign a variable to the tag indentation
$tagIndentation = $tag[1];
echo $tag[0] . "$tagIndentation:$currentIndentation=" . !($tagIndentation < $currentIndentation) . "<br>";
#Check if the current indentation is not smaller than the tag
if (!($tagIndentation < $currentIndentation)) {
#Close the tag
$output .= "</" . $tag[0] . ">";
#Remove the tag from unclosed list cince we just closed it
$unclosed_tags = array_diff($unclosed_tags, array($unclosed_tags[$key]));
}
}
#Get the current element (== the first string in a string)
$currentElement = preg_replace('/(\s*)([^\s]*)(.*)/', '$2', $line);
#Output as open tag
$output .= "<" . $currentElement . ">" . trim(str_replace_first($currentElement, "", $line));
#Add to list of unclosed tags
$unclosed_tags[$lineNum] = array($currentElement, $currentIndentation);
}
我尝试解析的示例.pug文件如下所示:
html
head
title Test
body
h1 This page was defined using JADE (PUG)!
h2 This a Header 2
div
p <strong>This text will appear strong</strong>
hr
br
ul
li This
li is a
li test
ol
li <b>Ordered Test</b>
li for the win
导出的html看起来像这样
<html>
<head>
<title>Test</title>
<body>
<h1>This page was defined using JADE (PUG)!</h1>
<h2>This a Header 2</h2>
<div>
<p><strong>This text will appear strong</strong></p>
<hr/>
</p>
<br/>
</p>
<ul>
<li>This</li>
<li>is a</li>
<li>test</li>
<ol>
<li><b>Ordered Test</b></li>
<li>for the win</li>
来自关闭未关闭标签的公寓这是我的完整算法,但它不起作用,因为有时标签没有关闭,因为内循环无法检查是否需要在此循环中关闭更多标签!
我不是在寻找现有的库,而是提示我的代码无效的原因以及如何提高代码质量和执行时间!
答案 0 :(得分:1)
所以我发现了一些有用的东西。以下是代码示例,我将解释以下更改:
$unclosed_tags
好的,所以改变是:
for
的方式,只是一个直接追加。您不需要跟踪此处的行号,这样我们就可以使用$unclosed_tags
循环作为内循环。之后,唯一剩下的就是以相反的顺序循环其余的foreach(array_reverse($unclosed_tags) as $i=>$line){ ...
并关闭它们。我想你也可以保留行号和{{1}}与for循环相同的结果。
答案 1 :(得分:0)
中断会让你脱离foreach循环,它不会跳过你到循环中的下一个实例。因此,在这种情况下,您可以删除 else 语句,如果它与 if 不匹配,则只会执行任何操作。
如果您的中断是有意的,那么您将无法在$ unclosed_tags变量中正确地预期/处理数据。
答案 2 :(得分:0)
我制定了一个解决方案。最有可能的问题是由于错误声明的数组访问器。
foreach ($lines as $line) {
#Increment the line number
$lineNum++;
#Save the current indentation for later use
$currentIndentation = strspn($line, " ");
print_r($unclosed_tags);
#Go though list of unclosed tags and recursivley close all that need to be closed
foreach ($unclosed_tags as $tagIndentation => $tag) {
#Check if the current indentation is not smaller than the tag
if (!($tagIndentation < $currentIndentation)) {
#Close the tag
$output .= str_repeat(' ', $tagIndentation) . "</" . $tag . ">\n";
#Remove the tag from unclosed list cince we just closed it
unset($unclosed_tags[$lineNum]);
}
}
#Get the current element (== the first string in a string)
$currentElement = preg_replace('/(\s*)([^\s]*)(.*)/', '$2', $line);
#Output as open tag
$output .= str_repeat(' ', $currentIndentation) . "<" . $currentElement . ">" . trim(str_replace_first($currentElement, "", $line)) . "\n";
#Add to list of unclosed tags
$unclosed_tags[$currentIndentation] = $currentElement;
}
#Close all remaining unclosed tags
这是工作代码。
随意在您的项目中使用它(尽管注意StackOverflows License)