Scala Parser组合器中的错误和故障

时间:2013-07-03 12:33:54

标签: parsing scala parser-combinators

我想使用Scala Parser Combinators为某些定义的语言实现解析器。但是,编译该语言的软件并未实现所有语言的功能,因此如果使用这些功能,我希望失败。我试着在下面写一个小例子:

object TestFail extends JavaTokenParsers {
  def test: Parser[String] =
    "hello" ~ "world" ^^ { case _ => ??? } |
    "hello" ~ ident ^^ { case "hello" ~ id => s"hi, $id" }
}

即,解析器成功执行“hello”+某个标识符,但如果标识符为“world”则失败。我看到Parsers类中存在fail()和err()解析器,但我无法弄清楚如何使用它们,因为它们返回Parser [Nothing]而不是String。该文档似乎不包括此用例...

2 个答案:

答案 0 :(得分:7)

在这种情况下,您需要err,而不是failure,因为如果分离中的第一个解析器失败,您只需转到第二个,这不是您想要的。

另一个问题是,^^相当于map,但您需要flatMap,因为err("whatever")Parser[Nothing],而不是Nothing 1}}。您可以在flatMap上使用Parser方法,但在此上下文中使用(完全等效的)>>运算符更为惯用:

object TestFail extends JavaTokenParsers {
  def test: Parser[String] =
    "hello" ~> "world" >> (x => err(s"Can't say hello to the $x!")) |
    "hello" ~ ident ^^ { case "hello" ~ id => s"hi, $id" }
}

或者,更简单一点:

object TestFail extends JavaTokenParsers {
  def test: Parser[String] =
    "hello" ~ "world" ~> err(s"Can't say hello to the world!") |
    "hello" ~ ident ^^ { case "hello" ~ id => s"hi, $id" }
}

任何一种方法都应该做你想要的。

答案 1 :(得分:3)

您可以使用^?方法:

object TestFail extends JavaTokenParsers {
  def test: Parser[String] =
    "hello" ~> ident ^? (
      { case id if id != "world" => s"hi, $id" },
      s => s"Should not use '$s' here."
  )
}