【发布时间】:2017-06-04 23:11:33
【问题描述】:
我需要以无序的方式解析单词。现在我可以看到以下内容
def first: Parser[String] = ???
def second: Parser[String] = ???
def unordered = (first ~ second) | (second ~ first)
但我想知道是否有任何本地解决方案?
【问题讨论】:
标签: scala parsing parser-combinators
我需要以无序的方式解析单词。现在我可以看到以下内容
def first: Parser[String] = ???
def second: Parser[String] = ???
def unordered = (first ~ second) | (second ~ first)
但我想知道是否有任何本地解决方案?
【问题讨论】:
标签: scala parsing parser-combinators
我通过将 ~ 和 | 解析器组合成名为 $ 的自定义解析器来实现这一点
看起来类似于~
trait ExtParsers extends JavaTokenParsers {
def unordered[T,U](tp: Parser[T], tu: Parser[U]): Parser[$[T, U]] =
tp ~ tu ^^ { case (x ~ y) => $(x, y) } | tu ~ tp ^^
{ case (x ~ y) => $(y, x) }
case class $[+a, +b](_1: a, _2: b)
implicit class ExtParser[+T](val parser: Parser[T]) {
def $[U](tu: Parser[U]): Parser[$[T, U]] = unordered(parser, tu)
}
}
object MyParser extends ExtParsers {
def unord: Parser[String] =
(ident $ stringLiteral $ wholeNumber $ floatingPointNumber) ^^ {
case (id $ sl $ wn $ fpn) =>
s"ident=$id string=$sl int=$wn float=$fpn"
}
}
并通过测试:
@Test def test() {
val expected = "ident=value string=\"test\" int=10 float=10.99"
assertEquals(expected,
MyParser.parseAll(MyParser.unord, "value \"test\" 10 10.99").get)
assertEquals(expected,
MyParser.parseAll(MyParser.unord,"\"test\" value 10 10.99").get)
assertEquals(expected,
MyParser.parseAll(MyParser.unord,"10 value \"test\" 10.99").get)
}
【讨论】:
API 不是那么大:https://static.javadoc.io/org.scala-lang.modules/scala-parser-combinators_2.12/1.0.6/scala/util/parsing/combinator/Parsers.html 和 https://static.javadoc.io/org.scala-lang.modules/scala-parser-combinators_2.12/1.0.6/scala/util/parsing/combinator/Parsers$Parser.html
看这个,答案似乎是否,没有办法更简单地做到这一点。不过,这种方式似乎一点也不差。
【讨论】: