Scala解析器组合:如何反转匹配?

5

在Scala解析器组合中是否可以反转匹配?我正在尝试使用解析器匹配不以一组关键字开头的行。我可以使用令人讨厌的零宽度负向先行正则表达式(例如"(?!h1|h2).*")来实现这一点,但我宁愿使用Scala解析器。我能想到的最好方法是:

def keyword = "h1." | "h2."
def alwaysfails = "(?=a)b".r
def linenotstartingwithkeyword = keyword ~! alwaysfails | ".*".r

这里的思路是使用 ~! 来防止回溯到全匹配正则表达式,然后继续使用 regex "(?=a)b".r,它不匹配任何内容。(顺便问一下,是否有预定义的解析器总是失败的?) 这样,如果找到关键词,则该行不会被匹配,但如果关键词不匹配,则该行将匹配。
我想知道是否有更好的方法来完成这个任务。有吗?
1个回答

7
您可以在此处使用not
import scala.util.parsing.combinator._

object MyParser extends RegexParsers {
  val keyword = "h1." | "h2."
  val lineNotStartingWithKeyword = not(keyword) ~> ".*".r

  def apply(s: String) = parseAll(lineNotStartingWithKeyword, s)
}

现在:

scala> MyParser("h1. test")
res0: MyParser.ParseResult[String] = 
[1.1] failure: Expected failure

h1. test
^

scala> MyParser("h1 test")
res1: MyParser.ParseResult[String] = [1.8] parsed: h1 test

请注意,Parsers上也有一个failure方法,因此您也可以使用keyword ~! failure("keyword!")编写您的版本。但是,not更好用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接