0

Wie würden Sie tun, dass in den Parser KombinatorenPositional vor Named Liste Argument Parsen

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

Antwort

0

Ok, hier ist Geist Ansatz

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 = [email protected] 

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