## Scala DSL technique if-else constructs Pub

Consolidated post - original posted in Aug, 2011.

Believe it or not, I've had a hard time coming up with this construct, so I figured it's worth publishing it, maybe save others the hassle.

You want to come up with a recursive if/else construct, like below (I used a dollar sign to denote the DSL if - I've used wif/welse in the past - use whatever you want):

``````  var branch = 1

val expr =

\$if(branch == 1) {

v("a") := 11

v("b") := 12

} \$else \$if(branch == 2) {

v("a") := 21

v("b") := 22

} \$else \$if(branch == 3) {

v("a") := 31

v("b") := 32

} \$else {

v("a") := 41

v("b") := 42

}
``````

Note the recursive if-else-if-else-if-else. The idea is that the if/else token will modify its own else branch depending on the following else - either the final else {} or an else followed by an if:

``````  case class TIf(cond: () => Boolean, body: () => Unit, var elsebranch: Option[TElse] = None) extends Token("IF ") {

val scope = TScope(body)

def \$else[T](body: => T) = { this.lastif.elsebranch = Some(TElse(() => body)); this }

def \$else(i: TIf) = {

this.lastif.elsebranch = Some(TElseIf(i))

this

}

def lastif = elsebranch.map(_.lastif).getOrElse(this)

...
``````

Also note that the way scala works is that the if-else tree is built from the top, so each else() is actually invoked on the root IF, therefore it needs to recursively find the last unbound IF and bind itself there as the elsebranch.

Having said that, find the full code and use it as a template, here.

Enjoy!

P.S. One issue with the simplified version built here is that it doesn't stop you from simple syntax errors like having an if-else-else... how would you fix it so the compiler stops you rather than the runtime exception?