有人可以帮我理解以下行为:
parseAll (parseIf, "If bla blablaa")
会产生is expected
。相反,我总是得到string matching regex 'is\b' expected but 'b' found
。
我想它与空格有关,因为" If bla is blablaa"
(注意开头的空格)会产生相同的行为。我尝试使用StandardTokenParsers,一切正常。但不幸的是,STP不支持正则表达式。
后续问题:我如何改变RegexParsers所以它使用一系列字符串而不是一系列字符?这会使错误报告变得更加容易。
lazy val parseIf = roleGiverIf ~ giverRole
lazy val roleGiverIf =
kwIf ~> identifier | failure("""A rule must begin with if""")
lazy val giverRole =
kwIs ~> identifier | failure("""is expected""")
lazy val keyword =
kwIf | kwAnd | kwThen | kwOf | kwIs | kwFrom | kwTo
lazy val identifier =
not(keyword) ~ roleEntityLiteral
// ...
def roleEntityLiteral: Parser[String] =
"""([^"\p{Cntrl}\\]|\\[\\/bfnrt]|\\u[a-fA-F0-9]{4})\S*""".r
def kwIf: Parser[String] = "If\\b".r
def kwIs: Parser[String] = "is\\b".r
// ...
parseAll(parseIf, "If bla blablaa") match {
case Success(parseIf, _) => println(parseIf)
case Failure(msg, _) => println("Failure: " + msg)
case Error(msg, _) => println("Error: " + msg)
答案 0 :(得分:0)
这个问题很奇怪。当您致电|
并且双方都失败时,会选择失败发生在最后的一侧,并选择偏向左侧的那一方。
当您尝试直接使用giverRole
进行解析时,会产生您期望的结果。但是,如果在失败之前添加成功匹配,则会产生您看到的结果。
原因相当微妙 - 我只是通过在所有解析器上撒上log
语句来找到它。要理解它,您必须了解 RegexParser
如何跳过空格。具体来说,在accept
上跳过空格。由于failure
不会调用accept
,因此不会跳过空格。
虽然kwIs
上b
发生了失败,但由于空格被跳过,failure
If空格发生 >。这里:
If bla blablaa
^ kwIs fails here
^ failure fails here
因此,kwIs
上的错误消息优先于我提到的规则。
您可以通过使解析器跳过空格而不匹配任何内容来解决此问题。重要的是,此模式始终匹配,否则您将收到更加混乱的错误消息。以下是我认为有效的建议:
"\\b|$".r ~ failure("is expected")
另一种解决方案是使用acceptIf
或acceptMatch
而不是使用隐式正则表达式接受,在这种情况下,您可以提供量身定制的错误消息。