2013-07-03 55 views
6

我想使用Scala解析器组合器来实现一些定义语言的解析器。但是,编译该语言的软件并未实现所有语言的功能,所以如果使用这些功能,我想失败。我试图建立下面一个小例子:Scala解析器组合器中的错误和失败

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

即解析器的“你好” +一些识别成功,但失败如果标识符为“世界”。我发现Parsers类中存在fail()和err()解析器,但我无法弄清楚如何使用它们,因为它们返回Parser [Nothing]而不是String。这个文档似乎没有涵盖这个用例...

回答

7

在这种情况下,你想要err,而不是failure,因为如果第一个解析器在析取失败,你会转移到第二个,这不是你想。

的另一个问题是,^^map等价,但你要flatMap,因为err("whatever")Parser[Nothing],而不是一个Nothing。你可以使用上ParserflatMap方法,但是在这种情况下它更习惯使用(完全等同)>>操作:

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

两种方法都应该做你想做的事。

+0

这正是我一直在寻找。是否>>,〜>(和<〜)操作符记录在某处(Scaladoc之外,这对我来说不够详细)? – scand1sk

+0

@ scand1sk:参见['Parsers#Parser'](http://www.scala-lang.org/api/current/index.html#scala.util.parsing.combinator.Parsers$Parser)类来获取文档。 – senia

+1

我猜''你好“〜”世界“>>'是拼写错误,应该有''hello'〜>'world >> >>'使用'$ x'。 – senia

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

不幸的是,这个解决方案在我的全局解析器项目中会太麻烦...... – scand1sk

+0

@ scand1sk:'>>'是您的案例中最好的解决方案。但是'^?'允许你使用这样的附加方法:'case _〜id if isValidId(id)=>'。 – senia

相关问题