【问题标题】:Positional before Named argument list parsing命名参数列表解析之前的位置
【发布时间】:2016-06-26 09:35:18
【问题描述】:

你会如何在解析器组合器中做到这一点

def namedAfterPos[P, N](pos: Parser[P], nmd: Parser[N], sep: Parser[_] = ",") = ???

List("a", "a,a,a", "a,a,a=b,a=b", "a=b, a=b") map (_ parseWith namedAfterPos("a", "a=b")) map {case Success(res, _) => res}
val Failure("positional is not expected after named", pos) = "a,a=b,a" parseWith namedAfterPos("a", "a=b")

【问题讨论】:

    标签: arguments parser-combinators named-parameters positional-parameter


    【解决方案1】:

    好的,这是思维导图

    scala> def namedAfterPos[P, N](pos: Parser[P], nmd: Parser[N], sep: Parser[_] = ",") = {
    
      // NB! http://stackoverflow.com/q/38041980/6267925 disucsses that that defining type 
      // aliases for result type is a bad programming practice that we use! Nevertheless,
      // define result type -- first comes the list of positional params, second - named.
      type Res = (List[P], List[N]); // named and positional have different types
    
      def namedOrPositional(positional: Boolean, acc: Res): Parser[Res] = {
    
        // once association accepted, we'll try the comma and go for next or exit
        def recur(positional: Boolean, acc: Res) =
           (sep flatMap {_ => namedOrPositional(positional, acc)}) | success(acc); 
    
        // named association should always be acceptable - stop accepting positionals when found
        (nmd flatMap {n => recur(false, acc match {case (p,nn)=> (p, n :: nn)})}) | 
    
        // if named failed - we have positional arg
        (pos flatMap {p => 
    
          // proceed if positionals are still accepted
          if (positional) recur(true, acc match {case (pp, n) => (p :: pp, n)}) 
    
          // if they are not - report parsing failure
          else failure("positional is not expected after named")})
      };
    
      namedOrPositional(true, (Nil, Nil)) // start collecting the args
    } 
    
    defined function namedAfterPos
    scala> List("a", "a,a,a", "a,a,a=b,a=b", "a=b, a=b") map (
        _ p namedAfterPos("a", "a=b")) map {case Success(res, _) => res} 
    res67: List[(List[P], List[N])] = List((List(a), List()), (List(a, a, a), List()), (List(a, a), List(a=b, a=b)), (List(), List(a=b, a=b)))
    val Failure("positional is not expected after named", pos) = "a,a=b,a" p namedAfterPos("a", "a=b") 
    pos: Input = scala.util.parsing.input.CharSequenceReader@1726cd4
    
    // named param is usually has a form of identifier "=" expr and positionals are expressions
    scala> def paredArgList[K,V](name: Parser[K] = identifier, value: Parser[V] = expr) = 
      pared(namedAfterPos(value, name ~ ("=" ~> value) map {case n~v => (n,v)}))  
    defined function paredArgList
    scala> List("a+b-1", "b=1+1", "a,a+1", "b=3+1,c=c+1", "1,b=g+g,d=123,bd=123+1") map ("(" + _ + ")" p paredArgList()) map {case Success(res, _) => res} 
    res70: List[(List[P], List[N])] = List((List(a + b - 1), List()), (List(), List((b,1 + 1))), (List(a + 1, a), List()), (List(), List((c,c + 1), (b,3 + 1))), (List(1), List((bd,123 + 1), (d,123), (b,g + g))))
    

    【讨论】:

      猜你喜欢
      • 2018-12-22
      • 2020-11-10
      • 2020-01-23
      • 1970-01-01
      • 2015-10-12
      • 2015-11-29
      • 2019-11-09
      • 2015-06-19
      • 1970-01-01
      相关资源
      最近更新 更多