使用 Scala/SBT 解析器组合器重复依赖解析器 [英] Repeating dependent parsers with Scala/SBT parser combinators

查看:34
本文介绍了使用 Scala/SBT 解析器组合器重复依赖解析器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

解析 Value[,Value]+ 形式的字符串可以通过 rep1sep(Value, ',') 轻松完成.当值解析器依赖于重复中先前解析的值时,有没有办法实现 rep1sep 功能?例如,强制要求每个值都必须是唯一的?

Parsing a string of the form Value[,Value]+ can be easily accomplished via rep1sep(Value, ','). Is there a way to achieve rep1sep functionality when the Value parser is dependent on the previously parsed Values in the repetition? For example, enforcing a requirement that each value must be unique?

依赖解析器的标准技术是 flatMap,但我无法让它工作.这是一种这样的尝试:

The standard technique for dependent parsers is flatMap, but I am having trouble getting that working. Here's one such attempt:

def Values(soFar: Set[Value]): Parser[Set[Value]] =
  Value(soFar) flatMap { v => (',' ~> Values(soFar + v)).?.map { _ getOrElse soFar } }

def Value(soFar: Set[Value]): Parser[Value] =
  Num+ flatMap { v => if (soFar.contains(v)) failure("%d already appears".format(v)) else success(v) }

通常,我需要一种形式的 rep1sep,其中解析器参数是一个从 Seq[A]Parser[A] 的函数:

Generically, I need a form of rep1sep where the parser argument is a function from Seq[A] to Parser[A]:

def rep1sepDependent(rep: Seq[A] => Parser[A], sep: Parser[Any]): Seq[A] = ???

注意:我意识到这里的用例是有问题的,验证唯一性最好在解析后处理.我在使用 SBT 解析组合器来完成制表符时遇到了这个问题——特别是,我想为用户尚未输入的那些键提供键/值对的完成选项.请参阅 此示例 和可构建的 SBT 项目.

Note: I realize the use case is questionable here and that validating uniqueness is better handled post parsing. I've encountered this problem while using the SBT parsing combinators for the purpose of tab completion -- specifically, I'd like to present completion options for key/value pairs for only those keys that the user has not already entered. See this parser for a full example and buildable SBT project.

推荐答案

以下内容不像您的 rep1sepDependent 那样通用,但它有效:

The following isn't quite as generic as your rep1sepDependent, but it works:

def rep1sepUnique[T](p: => Parser[T], q: => Parser[Any]) = {
  def checkIfSeen(seen: Set[T]): Parser[Set[T]] = q ~> p >> (v =>
    if (seen(v)) failure("Duplicate: %s".format(v)) else checkIfSeen(seen + v)
  ) | success(seen)
  p >> (v => checkIfSeen(Set(v)))
}

例如:

import scala.util.parsing.combinator._

object parseUniqueWords extends RegexParsers {
  def rep1sepUnique[T](p: => Parser[T], q: => Parser[Any]) = {
    def checkIfSeen(seen: Set[T]): Parser[Set[T]] = q ~> p >> (v =>
      if (seen(v)) failure("Duplicate: %s".format(v)) else checkIfSeen(seen + v)
    ) | success(seen)
    p >> (v => checkIfSeen(Set(v)))
  }

  def apply(s: String) = parseAll(rep1sepUnique("\\w+".r, ","), s)
}

这给了我们:

scala> parseUniqueWords("aaa,bb,c")
res0: parseUniqueWords.ParseResult[Set[String]] = [1.9] parsed: Set(aaa, bb, c)

scala> parseUniqueWords("aaa,bb,aaa")
res1: parseUniqueWords.ParseResult[Set[String]] = 
[1.11] failure: Duplicate: aaa

aaa,bb,aaa
          ^

这就是我们想要的.

这篇关于使用 Scala/SBT 解析器组合器重复依赖解析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆