我在Regexes中遇到了将代码划分为功能组件的问题。它们可能会破裂,或者它们可能需要很长时间才能完成。经历提出了一个问题:
“我什么时候应该使用解析器?”
答案 0 :(得分:9)
当您对文本的词汇或语义含义感兴趣时,您应该使用解析器,而模式可能会有所不同。当你只是想要匹配或替换字符模式时,解析器通常是矫枉过正的,无论它们的功能意义如何。
在您的情况下,您似乎对文本背后的含义(代码的“功能组件”)感兴趣,因此解析器将是更好的选择。但是,解析器可以在内部使用正则表达式,因此不应将它们视为互斥。
然而,“解析器”并不自动意味着它必须复杂。例如,如果您对C代码块感兴趣,则可以简单地解析{和}的嵌套组。这个解析器只对两个标记('{'和'}')以及它们之间的文本块感兴趣。
然而,由于嵌套语义,这里的简单正则表达式比较是不够的。请使用以下代码:
void Foo(bool Bar)
{
if(Bar)
{
f();
}
else
{
g();
}
}
解析器将理解Foo的整体范围,以及Foo中包含的每个内部范围(if和else块)。当它遇到每个'{'标记时,它“理解”它们的含义。然而,简单的搜索并不理解文本背后的含义,并且可能将以下内容解释为块,我们当然知道这是不正确的:
{
if(Bar)
{
f();
}
答案 1 :(得分:3)
在以下情况下需要解析器:
我的2美分。
答案 2 :(得分:2)
对于正则表达式,解析器有一些引人注目的用例。您应该使用解析器而不是正则表达式:
答案 3 :(得分:2)
The Dragon Book有一小段关于你不能使用正则表达式的内容:
对于1和2,有一个简单的解释,你不能捕获一个子串,以便你以后可以匹配它。如果你愿意,那么你将使用解析器。想想你将如何在这些案例中使用正则表达式,你将直观地得出你不能得出的结论。 :)
对于3,它与K& R中用于解析字符串文字的问题相同。你不能只说一个字符串文字在第一个'''和第二'''之间,但当有一个转义引号(\“)时会发生什么?
至于与罗素悖论的关系,我认为你的预感是正确的,因为这个问题是正则表达式有限的内省能力。这本书参考了证明。如果你愿意,我可以帮你查一查。
答案 4 :(得分:1)
一旦遇到问题,您就需要使用解析器。正则表达式并不意味着(或根本无法)解决。例如,匹配(非)平衡括号(递归地)是这些问题之一。虽然PCRE等一些风格让你走得很远,但他们并没有赢得手写的解析器。
答案 5 :(得分:1)
以下是一些用例,由Steve Yegge提供:Rich Programmer Food。
答案 6 :(得分:0)
你的问题有点模糊,但我想我的观点是,当你的正则表达式变得复杂或需要太长时间,并且你有一个合理定义的“语言”来处理时,解析器会更容易。
我认为你不能在沙子中设置一条线并且说一方的任何东西都可以通过正则表达式来完成,另一方面你需要一个解析器。这取决于具体情况。
答案 7 :(得分:0)
当解析器可以执行时,正则表达式无法做到这一点 例如:
开始:: =(内);
Inner :: =开始| X;
正则表达式无法执行此操作,因为正则表达式无法跟踪是否有相同数量的打开和关闭括号。这就是为什么当你试图标记和解析一个大文件时,应该使用解析器,而正则表达式可以简单地在文件中找到特殊模式。