gpt4 book ai didi

scala - 动态组合 Scala 的解析器组合子的函数是什么?

转载 作者:行者123 更新时间:2023-12-01 23:55:01 25 4
gpt4 key购买 nike

我正在寻找一个动态组合 Scala Parser Combinators 的函数。例如,如果我想静态地进行,我可以这样写:

def aDirective: Parser[String] = "a" ^^ { case _ => "a" }
def bDirective: Parser[String] = "b" ^^ { case _ => "b" }

def combinedDirective: Parser[List[String]] =
aDirective ~ bDirective ^^ { case a ~ b => List(a, b) }

然而,为了生成解析器的组合,我希望能够动态地执行此操作,而不是静态编码。

例如:

def aDirective: Parser[String] = "a" ^^ { case _ => "a" }
def bDirective: Parser[String] = "b" ^^ { case _ => "b" }

def combinedDirective: Parser[List[String]] =
combine(List(aDirective, bDirective))

def combine(parsers: List[Parser[T]): Parser[List[T]] = ???

认为我需要从解析器列表转到结果列表解析器。所以我尝试为名为 combine 的函数编写签名。

目前我不知道如何实现combine 功能。无论我尝试哪种方式,它似乎都充满了我目前无法想到如何解决的问题。例如,我如何为折叠构造一个初始解析器?我已尝试尝试各种 foldLeftreduceLeft 构造,但似乎无法完全实现。

我正在使用 Scala 2.11。有什么想法吗?

最佳答案

这是一个 sequencing operation , 和 Scalaz提供了一个快捷方式(通常您不需要使用 Scalaz 的显式实例定义样板,但是 this is a special case ):

import scala.util.parsing.combinator.RegexParsers
import scalaz._, Scalaz._

object MyParser extends RegexParsers {
implicit val pm = std.util.parsing.combinator.parser.parserMonad(this)

def aDirective: Parser[String] = "a" ^^ { case _ => "a" }
def bDirective: Parser[String] = "b" ^^ { case _ => "b" }

def combine[T](parsers: List[Parser[T]]): Parser[List[T]] = parsers.sequenceU

def combinedDirective: Parser[List[String]] =
combine(List(aDirective, bDirective))
}

然后:

scala> MyParser.parseAll(MyParser.combinedDirective, "ab")
res0: MyParser.ParseResult[List[String]] = [1.3] parsed: List(a, b)

你也可以自己定义一个折叠:

import scala.util.parsing.combinator.RegexParsers

object MyParser extends RegexParsers {
def aDirective: Parser[String] = "a" ^^ { case _ => "a" }
def bDirective: Parser[String] = "b" ^^ { case _ => "b" }

def combine[T](parsers: List[Parser[T]]): Parser[List[T]] =
parsers.foldRight(success(List.empty[T])) {
case (p, acc) => for {
pRes <- p
accRes <- acc
} yield pRes :: accRes
}

def combinedDirective: Parser[List[String]] =
combine(List(aDirective, bDirective))
}

而且它的工作原理完全一样。诀窍就是让基础正确——它需要是一个总是以空列表作为其值的解析器。


更新:如果你正在定义一个类,而不是一个对象,上面的 Scalaz 方法将不起作用(出于一些奇怪的原因——简而言之,this 不够稳定) .不过,您可以很容易地定义自己的 monad 实例:

class MyParser extends RegexParsers {
implicit val pm = new Monad[Parser] {
def point[A](a: => A): Parser[A] = success(a)
def bind[A, B](fa: Parser[A])(f: A => Parser[B]): Parser[B] = fa flatMap f
}

def aDirective: Parser[String] = "a" ^^ { case _ => "a" }
def bDirective: Parser[String] = "b" ^^ { case _ => "b" }

def combine[T](parsers: List[Parser[T]]): Parser[List[T]] = parsers.sequenceU

def combinedDirective: Parser[List[String]] =
combine(List(aDirective, bDirective))
}

这里其实不需要monad实例来使用sequence,只是一个applicative functor,但是定义起来其实更方便一些,monad实例在其他情况下可能会有用。

关于scala - 动态组合 Scala 的解析器组合子的函数是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24336770/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com