在Scala语法分析器组合器中没有排序解析器

问题描述:

我需要以无序的方式解析这些单词。现在我可以看到以下在Scala语法分析器组合器中没有排序解析器

def first: Parser[String] = ???  
def second: Parser[String] = ??? 
def unordered = (first ~ second) | (second ~ first) 

但我想知道是否有任何原生解决方案?

的API并不大:https://static.javadoc.io/org.scala-lang.modules/scala-parser-combinators_2.12/1.0.6/scala/util/parsing/combinator/Parsers.htmlhttps://static.javadoc.io/org.scala-lang.modules/scala-parser-combinators_2.12/1.0.6/scala/util/parsing/combinator/Parsers $ Parser.html

通过这个来看,似乎答案是没有,有没有办法更简单地做到这一点。不过,这种方式看起来并不糟糕。

+0

是的,它看起来如此: (就目前的解决方案而言,这些条件的数量增长可能会变得复杂。 – ikryvorotenko

我结合~|解析器为命名的自定义解析器实现了这个$

它类似于~

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