如何对 Scala 解析器组合器结果进行模式匹配

发布于 2024-11-05 13:07:52 字数 1273 浏览 3 评论 0原文

我们有一个多线程 RPC 服务器来解析输入字符串。我们遇到了 Scala 的解析器组合器库不是多线程安全的问题: Parsers.scala 用于任何解析。我们在这一行中得到一个 NullPointerException

if (!(lastNoSuccess != null && next.pos < lastNoSuccess.next.pos))

通过创建一个扩展解析器之一的对象来实现解析器的默认方法,但我想按需构造一个解析器,以便每个解析器都有自己的内部状态,所以我使用一个类来代替一个物体的。但是,我无法编译它,因为我需要对结果进行模式匹配:

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

We have a multithreaded RPC server that parses input strings. We've run into an issue where Scala's parser combinator library is not multithreaded safe: the var lastNoSuccess in Parsers.scala is used by any parsing. We get a NullPointerException in this line

if (!(lastNoSuccess != null && next.pos < lastNoSuccess.next.pos))

The default way to implement the parser by making an object that extends one of the Parsers, but I want to construct a parser on demand so each has its own internal state, so I'm using a class instead of an object. However, I can't get it to compile since I need to pattern match on the result:

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

Fails with

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

作妖 2024-11-12 13:07:52

使用:

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
}

Use this:

val parser = new SqlParserImpl
parser.parseAll(parser.term, "term") match {
  case parser.Success(result, _) => true
  case parser.NoSuccess(_, _) => false
}

The # sign is used to designate a type member. In your case it's using a constructor or an extractor pattern which needs to reference to an object or something that looks like a constructor.

Hmm. I don't have a 2.7 handy. Try this:

parser.parseAll(parser.term, "term") match {
  case parser.Success(result, _) => true
  case parser.Failure(_, _) => false
  case parser.Error(_, _) => false
}
江挽川 2024-11-12 13:07:52

我能够编译以下内容:

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

I was able to compile the following:

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
    })
  }
}
最好是你 2024-11-12 13:07:52

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

例如 Eugene 建议一个>。

The NoSuccess object (with extractor) was added back in 2009, at a time when no code was being backported to 2.7 anymore It's implementation, however, is pretty simple:

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

So you can replace the parser.NoSuccess(_, _) match with one parser.Failure(_, _) and one parser.Error(_, _) match. But if you are not interested in what is being returned, then it's simpler to match against the type:

case _: parser.Success[_] => true
case _: parser.NoSuccess  => false

Like suggested by Eugene.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文