在Scala的解析器组合器(尤其是JavaTokensParser)中,有一个stringLiteral定义,它与类似Java的字符串相匹配。
def stringLiteral: Parser[String] =
("\""+"""([^"\p{Cntrl}\\]|\\[\\'"bfnrt]|\\u[a-fA-F0-9]{4})*"""+"\"").r
不幸的是,此正则表达式不适用于长字符串。有人知道这样做的可重用实现,还是对正则表达式的修改更节省空间?
有趣的问题!
只是玩这个,并提出了以下内容:
val r = ("\"" + "(?:[^\"\\p{Cntrl}\\\\]*|(?:\\\\(?:[\\\\'\"bfnrt]|u[a-fA-F0-9]{4}))*)*" + "\"").r
注意:上面的正则表达式是从第一个版本开始修复的……前导“ \”和结尾字符都需要重复,而不仅仅是我原来使用的结尾字符!
编辑:找到了更有效的正则表达式。使用以下命令,它可以解析最多950\\ns
对字符串,而原始字符串只能解析556,至少在我的默认配置中。
val r = ("\"" + "(?:[^\"\\p{Cntrl}\\\\]*|\\\\[\\\\'\"bfnrt]|\\\\u[a-fA-F0-9]{4})*" + "\"").r
编辑2:根据@schmmd的评论,我有一个更好的正则表达式。这可以解析2500个\ns
酷刑案。秘诀是使用贪婪的所有格修饰符,这基本上关闭了回溯的需要,因此也关闭了递归。
val r = (""""([^"\p{Cntrl}\\]*+(?:\\[\\'"bfnrt])*+(?:\\u[a-fA-F0-9]{4})*+)*+"""").r
解决方案的实质是每次匹配事物时都尽力尝试和咀嚼。
scala> val r = (""""([^"\p{Cntrl}\\]*+(?:\\[\\'"bfnrt])*+(?:\\u[a-fA-F0-9]{4})*+)*+"""").r
r: scala.util.matching.Regex = "([^"\p{Cntrl}\\]*+(?:\\[\\'"bfnrt])*+(?:\\u[a-fA-F0-9]{4})*+)*+"
scala> r.pattern.matcher("\"" + "\\ns" * 2500 + "\"").lookingAt
res4: Boolean = true
scala> r.pattern.matcher("\"" + "s" * 2500 + "\"").lookingAt
res5: Boolean = true
更新:一个pull请求被提交给乡亲阶。并被接受。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句