我正在以学习和爱好的名义开发自己的模板引擎。我有一个正则表达式,它使用与 TWIG 几乎相同的语法来查找 if 语句。
您可以查看正则表达式here有一些工作示例,然后是我正在尝试实现的示例。
这是正则表达式:
{%\s*if\s+(?<var>(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(?:\.(?:[a-zA-Z0-9_\x7f-\xff]*))*)\s(?:(?<operation>=|!=|<=|<|>=|>)\s(?<var2>(?:(?:(?1)*)(?:\.(?:(?2)*))*)|(?:[0-9]+))\s?)?%}(?<if>(?:(?!{% e(?:lse|nd if) %}).)*)(?:{%\h?else\h?%}(?<else>[\s\S]*?))?{%\h?end if\s?%}
这是它正在处理的数据:
THESE WORK
{% if thing %}
stuff
{% end if %}
{% if thing %}
stuff
{% else %}
other stuff
{% end if %}
{%if thing = thingy %}
stuff
{% else %}
other stuff
{% end if %}
THIS DOESN'T
Problem starts here:
{% if this = that %}
{% if item.currency = 0 %}
selected="selected"
{% else %}
you
{% end if %}
{% end if %}
基本上,我希望正则表达式搜索最后一个 {% end if %} 标记,并将其间的所有内容用作稍后可以递归解析的字符串。
另外,作为旁注,将问题的大部分信息留在正则表达式测试器的链接中是否合适?或者我也应该在这里复制大部分问题(在SO上)?
最佳答案
修订版 1
由于您正在进行实验,经过一番闲逛后,为您想出了一个通用的正则表达式。
这可能会增加您当前的知识,并提供一些可以借鉴的东西。
概要:
在纯正则表达式解决方案中,平衡文本的概念大约是
正则表达式引擎消失了。它不会填写详细信息。
为此你必须自己做。
与下降解析器等相比,这是一种缓慢的方法。
不同之处在于它不需要放松就知道它在哪里。
因此,这将允许您在遇到错误时继续解析。
有点从过去的错误中获得更多意义以帮助调试。
在做这种事情时,你应该解析每一个字符。
所以我们解析内容、分隔符开始、核心、结束和错误。
在本例中,我们在外部范围上预留了 7 个捕获组来浏览信息。
Content
- 这是由 if/else/end if
以外的任何内容组成的。
Else
- 这是else
语句
Begin
- 这是开始 if
block
If_Content
- 这是 if block 内容
核心
- 这是外部开始和结束之间的所有内容
。还包含嵌套内容。
End
- 这是外部 end if
block
Error
- 这是不平衡错误,它是 if
或 end if
。
用法:
在宿主程序中,定义一个名为ParseCore()
的函数
该函数需要传递(或知道)当前的核心字符串。
如果是 C++,则会传递开始和结束字符串迭代器。
无论如何,字符串必须是函数的本地字符串。
在此函数中,处于 while 循环中解析字符串。
在每场比赛中,执行 if/else 查看上面的哪个组匹配。
只能是这些组合
内容
或
其他
或
开始、If_Content、核心、结束
或
错误
只有一组对于递归很重要。这是核心
组。
当该组匹配时,您将递归函数调用
ParseCore()
将 Core 字符串传递给它。
重复此操作,直到不再有匹配项为止。
错误报告、创建结构树以及其他任何事情都可以做
在此函数内。
您甚至可以在任何时候设置一个全局标志来展开递归调用
并退出。举例来说,您想在发生错误或类似情况时停止。
注意:在首次调用 ParseCore()
时,您只需传入整个原始字符串即可开始解析。
祝你好运!
# (?s)(?:(?<Content>(?&_content))|(?<Else>(?&_else))|(?<Begin>{%\s*if\s+(?<If_Content>(?&_ifbody))\s*%})(?<Core>(?&_core)|)(?<End>{%\s*end\s+if\s*%})|(?<Error>(?&_keyword)))(?(DEFINE)(?<_ifbody>(?>(?!%}).)+)(?<_core>(?>(?<_content>(?>(?!(?&_keyword)).)+)|(?(<_else>)(?!))(?<_else>(?>{%\s*else\s*%}))|(?>{%\s*if\s+(?&_ifbody)\s*%})(?:(?=.)(?&_core)|){%\s*end\s+if\s*%})+)(?<_keyword>(?>{%\s*(?:if\s+(?&_ifbody)|end\s+if|else)\s*%})))
(?s) # Dot-all modifier
# =====================
# Outter Scope
# ---------------
(?:
(?<Content> # (1), Non-keyword CONTENT
(?&_content)
)
| # OR,
# --------------
(?<Else> # (2), ELSE
(?&_else)
)
| # OR
# --------------
(?<Begin> # (3), IF
{% \s* if \s+
(?<If_Content> # (4), if content
(?&_ifbody)
)
\s* %}
)
(?<Core> # (5), The CORE
(?&_core)
|
)
(?<End> # (6)
{% \s* end \s+ if \s* %} # END IF
)
| # OR
# --------------
(?<Error> # (7), Unbalanced IF or END IF
(?&_keyword)
)
)
# =====================
# Subroutines
# ---------------
(?(DEFINE)
# __ If Body ----------------------
(?<_ifbody> # (8)
(?>
(?! %} )
.
)+
)
# __ Core -------------------------
(?<_core> # (9)
(?>
#
# __ Content ( non-keywords )
(?<_content> # (10)
(?>
(?! (?&_keyword) )
.
)+
)
|
#
# __ Else
# Guard: Only 1 'else'
# allowed in this core !!
(?(<_else>)
(?!)
)
(?<_else> # (11)
(?> {% \s* else \s* %} )
)
|
#
# IF (block start)
(?>
{% \s* if \s+
(?&_ifbody)
\s* %}
)
# Recurse core
(?:
(?= . )
(?&_core)
|
)
# END IF (block end)
{% \s* end \s+ if \s* %}
)+
)
# __ Keyword ----------------------
(?<_keyword> # (12)
(?>
{% \s*
(?:
if \s+ (?&_ifbody)
| end \s+ if
| else
)
\s* %}
)
)
)
示例输入(已删除)
选定的输出(已删除)
伪代码使用示例
bool bStopOnError = false;
regex RxCore(".....");
bool ParseCore( string sCore, int nLevel )
{
// Locals
bool bFoundError = false;
bool bBeforeElse = true;
match _matcher;
while ( search ( core, RxCore, _matcher ) )
{
// Content
if ( _matcher["Content"].matched == true )
// Print non-keyword content
print ( _matcher["Content"].str() );
// OR, Analyze content.
// If this 'content' has error's and wish to return.
// if ( bStopOnError )
// bFoundError = true;
else
// Else
if ( _matcher["Else"].matched == true )
{
// Check if we are not in a recursion
if ( nLevel <= 0 )
{
// Report error, this 'else' is outside an 'if/end if' block
// ( note - will only occur when nLevel == 0 )
print ("\n>> Error, 'else' not in block " + _matcher["Else"].str() + "\n";
// If this 'else' error will stop the process.
if ( bStopOnError == true )
bFoundError = true;
}
else
{
// Here, we are inside a core recursion.
// That means there can only be 1 'else'.
// Print 'else'.
print ( _matcher["Else"].str() );
// Set the state of 'else'.
bBeforeElse == false;
}
}
else
// Error ( will only occur when nLevel == 0 )
if ( _matcher["Error"].matched == true )
{
// Report error
print ("\n>> Error, unbalanced " + _matcher["Error"].str() + "\n";
// // If this unbalanced 'if/end if' error will stop the process.
if ( bStopOnError == true )
bFoundError = true;
}
else
// IF/END IF block
if ( _matcher["Begin"].matched == true )
{
// Analyze 'if content' for error and wish to return.
string sIfContent = _matcher["If_Content"].str();
// if ( bStopOnError )
// bFoundError = true;
// else
// {
// Print 'begin' ( includes 'if content' )
print ( _matcher["Begin"].str() );
//////////////////////////////
// Recurse a new 'core'
bool bResult = ParseCore( _matcher["Core"].str(), nLevel+1 );
//////////////////////////////
// Check recursion result. See if we should unwind.
if ( bResult == false && bStopOnError == true )
bFoundError = true;
else
// Print 'end'
print ( _matcher["End"].str() );
// }
}
else
{
// Reserved placeholder, won't get here at this time.
}
// Error-Return Check
if ( bFoundError == true && bStopOnError == true )
return false;
}
// Finished this core!! Return true.
return true;
}
///////////////////////////////
// Main
string strInitial = "...";
bool bResult = ParseCore( strInitial, 0 );
if ( bResult == false )
print ( "Parse terminated abnormally, check messages!\n" );
关于php - 使用正则表达式解析嵌套的 IF 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36700579/