【问题标题】:Errors and failures in Scala Parser CombinatorsScala Parser Combinators 中的错误和失败
【发布时间】:2013-07-03 12:33:53
【问题描述】:

我想使用 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。文档似乎没有涵盖这个用例……

【问题讨论】:

    标签: parsing scala parser-combinators


    【解决方案1】:

    在这种情况下,您需要err,而不是failure,因为如果析取中的第一个解析器失败,您将继续执行第二个解析器,这不是您想要的。

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

    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" }
    }
    

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

    【讨论】:

    • 这正是我想要的。 >>、~>(和
    • @scand1sk:请参阅Parsers#Parser 类的文档。
    • 我猜"hello" ~ "world" >>是一个错字,应该有"hello" ~> "world" >>才能使用$x
    • @senia:谢谢——你说得对,我的原始版本可以编译并工作,但错误消息不会像应有的那样清晰。
    【解决方案2】:

    您可以使用^? 方法:

    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."
      )
    }
    

    【讨论】:

    • 不幸的是,这个解决方案在我的全局解析器项目中太麻烦了……
    • @scand1sk: >> 是您的最佳解决方案。但是^? 允许你使用这样的加法:case _ ~ id if isValidId(id) =>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    相关资源
    最近更新 更多