优化ruby 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>(?

我正在开发一款ruby baser lexer。为了提高性能,我将所有令牌的regexp合并到一个带有匹配组名称的大型regexp中。生成的regexp如下所示:

/\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