优化ruby regexp--许多匹配组
我正在开发一款ruby baser lexer。为了提高性能,我将所有令牌的regexp合并到一个带有匹配组名称的大型regexp中。生成的regexp如下所示:优化ruby regexp--许多匹配组,ruby,regex,optimization,pattern-matching,lexer,Ruby,Regex,Optimization,Pattern Matching,Lexer,我正在开发一款ruby baser lexer。为了提高性能,我将所有令牌的regexp合并到一个带有匹配组名称的大型regexp中。生成的regexp如下所示: /\A(?<__anonymous_-1038694222803470993>(?-mix:\n+))|\A(?<__anonymous_-1394418499721420065>(?-mix:\/\/[\A\n]*))|\A(?<__anonymous_3077187815313752157>(?
/\A(?<__anonymous_-1038694222803470993>(?-mix:\n+))|\A(?<__anonymous_-1394418499721420065>(?-mix:\/\/[\A\n]*))|\A(?<__anonymous_3077187815313752157>(?-mix:include\s+"[\A"]+"))|\A(?<LET>(?-mix:let\s))|\A(?<IN>(?-mix:in\s))|\A(?<CLASS>(?-mix:class\s))|\A(?<DEF>(?-mix:def\s))|\A(?<DEFM>(?-mix:defm\s))|\A(?<MULTICLASS>(?-mix:multiclass\s))|\A(?<FUNCNAME>(?-mix:![a-zA-Z_][a-zA-Z0-9_]*))|\A(?<ID>(?-mix:[a-zA-Z_][a-zA-Z0-9_]*))|\A(?<STRING>(?-mix:"[\A"]*"))|\A(?<NUMBER>(?-mix:[0-9]+))/
哪个输出
#<MatchData
"\n"
__anonymous_-1038694222803470993:"\n"
__anonymous_-1394418499721420065:nil
__anonymous_3077187815313752157:nil
LET:nil
IN:nil
CLASS:nil
DEF:nil
DEFM:nil
MULTICLASS:nil
FUNCNAME:nil
ID:nil
STRING:nil
NUMBER:nil>
验证匹配组是否有匹配项
这里的问题是它的速度很慢(我花了大约10%的时间在循环中;还有8%的时间抓取@input[@pos..-1]
,以确保\A按照预期的方式工作,以匹配字符串的开头(我不放弃输入,只是移动其中的@pos)
您可以在查看完整代码
关于如何使它至少快一点有什么想法吗?有没有办法更容易地计算出“成功”的比赛组?我可能完全误解了这一点,但我假设除了一个标记以外,其他所有标记都不是
nil
,这就是你想要的标记
如果是这样的话,根据您使用的正则表达式的风格,您可以使用负前瞻来检查非nil
值
([^\n:]+:(?!nil)[^\n\>]+)
这将匹配整个令牌,即
NAME:value
您可以使用regexp方法.captures()
和.names()
:
或者,如果您希望获得多个成功的价值,您可以:
success_names_arr = []
success_names_arr.push(@input.names[index]) #within the above loop
与您最初的想法非常相似,但如果您希望提高效率,
.captures()
方法应该有帮助。只有一个标记不是nil,但我需要确定是哪一个。正则表达式是每个标记正则表达式的串联,以加快速度。我对ruby不太熟悉,所以实现可能需要调整,但上面的正则表达式将匹配一个字符串,该字符串包含:
,后面不跟nil
。您知道吗然后可以根据冒号拆分捕获的字符串。我还修改了正则表达式,以考虑结束符
让我更正一下,您建议正则表达式匹配匹配数据#inspect?我不确定这意味着什么。但在这一点上,我不知道组合正则表达式的哪一部分匹配(即,原始令牌名称是什么)。然后可能尝试使用pre_-match?a=@input.match(/your_-regex/).pre_-match
。如果我正确理解了您的代码,pre_-match就是这个名称?(您可能需要将冒号去掉)。在稍微单独的注释中,您可以在代码中稍微干燥一下(第129-131行)val,type,resolved_type=nil
更新了问题,提供了更多关于从何处获取匹配数据以及我遗漏了什么的详细信息。添加的信息非常有用。我在上面更新了我的答案。^^。这对您来说应该很有用,仅供参考,非常好的一点,但是使用RE for lexer使开发变得非常简单(节省了开发时间).不过,我正在考虑一种更直接的lexer方法。
([^\n:]+:(?!nil)[^\n\>]+)
matching_string = "\n ...garbage" # or whatever this really is in your code
@input = matching_string.match bigregex # bigregex = your regex
arr = @input.captures
arr.each_with_index do |value, index|
if not value.nil?
the_name_you_want = @input.names[index]
end
end
success_names_arr = []
success_names_arr.push(@input.names[index]) #within the above loop