Positioning Before the Name Argument List Syntax

How do you do it in parser combinators

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") 
0
source share
1 answer

Ok, here is a reasonable approach

 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)))) 
0
source

All Articles