我们有一个解析输入字符串的多线程RPC服务器。我们遇到了Scala的解析器组合器库不是多线程安全的问题:任何解析都使用Parsers.scala中的var lastNoSuccess。我们在这行中得到一个NullPointerException
if (!(lastNoSuccess != null && next.pos < lastNoSuccess.next.pos))
通过创建一个扩展其中一个Parsers的对象来实现解析器的默认方法,但是我想按需构造一个解析器,因此每个都有自己的内部状态,所以我使用的是一个类而不是一个对象。但是,我无法编译它,因为我需要对结果进行模式匹配:
import scala.util.parsing.combinator.RegexParsers
class SqlParserImpl
extends RegexParsers
{
val term: Parser[String] = """(?i)term\b""".r
}
object Test
{
def main(args: Array[String]): Unit =
{
val parser = new SqlParserImpl
parser.parseAll(parser.term, "term") match {
// How do I match?
case SqlParserImpl#Success(result, _) => true
case SqlParserImpl#NoSuccess => false
}
}
}
失败
t.scala:16: error: '=>' expected but '#' found.
case SqlParserImpl#Success(result, _) => true
^
t.scala:17: error: '=>' expected but '#' found.
case SqlParserImpl#NoSuccess => false
^
two errors found
答案 0 :(得分:10)
使用此:
val parser = new SqlParserImpl
parser.parseAll(parser.term, "term") match {
case parser.Success(result, _) => true
case parser.NoSuccess(_, _) => false
}
#
符号用于指定类型成员。在您的情况下,它使用构造函数或提取器模式,需要引用一个对象或看起来像构造函数的东西。
嗯。我没有2.7便利。试试这个:
parser.parseAll(parser.term, "term") match {
case parser.Success(result, _) => true
case parser.Failure(_, _) => false
case parser.Error(_, _) => false
}
答案 1 :(得分:4)
我能够编译以下内容:
object Test {
def main(args: Array[String]): Unit = {
val parser = new SqlParserImpl
println(parser.parseAll(parser.term, "term") match {
case x: parser.Success[_] => true
case x: parser.NoSuccess => false
})
}
}
答案 2 :(得分:4)
NoSuccess
对象(带有提取器)在2009年被添加回来,当时没有代码被反向移植到2.7它的实现非常简单:
object NoSuccess {
def unapply[T](x: ParseResult[T]) = x match {
case Failure(msg, next) => Some(msg, next)
case Error(msg, next) => Some(msg, next)
case _ => None
}
}
因此,您可以将parser.NoSuccess(_, _)
匹配替换为一个parser.Failure(_, _)
和一个parser.Error(_, _)
匹配。但是如果你对返回的不感兴趣,那么匹配类型更简单:
case _: parser.Success[_] => true
case _: parser.NoSuccess => false