Scala: conversion question

I am using a Scala parser as follows:

def a = b ~ c ^^ { case x ~ y => A(x,y) } def b = ... { B() } def c = ... { C() } 

I now have a function change that changes when parsing a link previously parsed by B as val in C Therefore, the constructor C matters:

 C(ref:B) 

I can imagine the only way to achieve this is the dirty work of fixing it by assigning an instance of the parsed object B to def c between parsing a . Something like the following:

 var temp:B = null def a = ( b ^^ { case x => temp = x } ) ~ c(temp) ^^ {case x ~ y => A(x,y} ) 

Is there a standard, clean way to do this? The definition of a cannot be violated; it is used in many places in the rest of the code.

Another solution is to use var instead of val and the following:

  def a = (b ~ c ) ^^ { case x ~ y => y.ref = c ; A(x,y) } 

But this is also unacceptable, since now it will "work", but in the future it will require additional efforts and boiler room code.

I have not tested this code, as this is a small part, and all changes require a lot of effort, so first you need to get an expert opinion.

+4
source share
3 answers

Without changing the definition of a , there is no way to do this purely. The ~ combinator creates a new Parser that sequentially applies b and c , then binds (well, logically tuples) the results and returns them as the result. The key point is that application c not a function of the output of b , so you can do nothing to get the results of b inside the application c .

What I would do is add a new combinator that does what you want. I don't feel particularly creative by name, but I think this should give you a rough idea:

 implicit def cleverParserSyntax[A](left: Parser[A]) = new { def ~%[B](right: A => Parser[B]): Parser[A ~ B] = for { lr <- left rr <- right(lr) } yield new ~(lr, rr) } def a = b ~% c ^^ { case x ~ y => A(x,y) } def b = ... { B() } def c(res: B) = ... { C(res) } 
+2
source

I'm not sure if I understood the problem correctly, but if C depends on B, why not express it in a functional way?

 case class B(...) case class C(b: B, ...) case class A(b: B, c: C) def b: Parser[B] = ... ^^ { B(...) } def c: Parser[B => C] = ... ^^ { C(_, ...) } def a: Parser[A] = b ~ c ^^ { A(b, c(b)) } 

Thus, your problem is resolved, and your dependencies are expressed in an explicit and concise manner.

+2
source

I would do this:

 case class B(x: String) case class C(b: B, x: String) case class A(b: B, c: C) class MyParser extends RegexParsers { def a = b >> c ^^ { case x ~ y => A(x, y) } def b = "\\w+".r ^^ B def c(b: B) = "\\d+".r ^^ (x => new ~(b, C(b, x))) } 

Now, if B happens much earlier than C , things get complicated. I suggest, if it works out that hairy, to find a document on the Scala parser, which is included in many very advanced functions.

+1
source

All Articles