1

I am looking to build an evaluation tree, for starters, for arithmetic expressions.

I have the following case classes defined:

abstract class Expr
case class Num(n: Integer) extends Expr
case class Plus(e1: Expr, e2: Expr) extends Expr

My parser, when it sees the expression 1 + 1 + 1 produces the following tree:

Plus(Plus(Num(1), Num(1)), Num(1))

I then have the following data type defined:

case class Tree[Expr](e: Expr, children: List[Tree[Expr]])

Here is a badly drawn evaluation tree:

  Num(1)         Num(1)
----------------------------    
     Plus(Num(1), Num(1))         Num(1)
 ---------------------------------------
     Plus(Plus(Num(1),Num(1)), Num(1))

I want to build up a tree data structure representing that. So, the resulting output of evaluation would be:

Tree(
  Plus(Plus(Num(1), Num(1)), Num(1)),
  List(Tree(Plus(Num(1),Num(1),
       List(Tree(Num(1), List()),
            Tree(Num(1), List()))),
  Tree(Num(1), List())))

I want to have a method eval:

def eval(e: Expr, t: Tree[Expr]): Tree[Expr] = (e, t) match {
  // Do the matching on Num
  case Num(n) ........ =>
  case Plus(e1, e2)  ...... => 
}

Is it the right way to represent this evaluation tree and if so, how can I go about creating such a nested tree data structure.

EDIT: Here is a method eval for addition only

def eval(e: Expr): Tree[Expr] = e match {
    case Num(n) => Tree(Num(n), Nil)
    case Plus(e1, e2) => Tree(Plus(e1, e2), List(eval(e1), eval(e2)))
}
  • I don't think you need the tree class. You create a tree just through nesting Pluses already – puhlen Jan 20 '17 at 18:30
  • Not an assignment, a project of mine. My parser produced a nested tree which is initial expression. I drew evaluation tree in my post. I updated the post above where I came up with solution for language that only has additions. – StudentOfLogic Jan 20 '17 at 18:45
  • I didn't say anything about an assignment. I'm Still failing to see the advantage of the Tree class, the Plus class is already a tree on its own. – puhlen Jan 20 '17 at 18:57
  • I now see your point after looking at it more. Thanks for the remark. – StudentOfLogic Jan 20 '17 at 19:25

1 Answers1

2

You may have it like this:

def toTree(e: Expr): Tree[Expr] = e match {
  case Plus(e1, e2) => Tree(e, List(eval(e1), eval(e2)))
  case _ => Tree(e, List())
}

However, you'd better omit Tree as @puhlen suggests. The following method should be enough:

def children(e: Expr): List[Expr] = e match {
  case Plus(e1, e2) => List(e1, e2)
  case _ => List()
}

Just use it wherever you would use Tree.children

Arseniy Zhizhelev
  • 2,381
  • 17
  • 21
  • Another question then. This evaluation tree will be used to generate HTML for it. Each case class will have pretty print method which will display lambda as lambda char etc. However, is this the right data structure to go about traversing and rendering it to HTML? – StudentOfLogic Jan 20 '17 at 18:58
  • I don't see any problems with this structure yet. `pretty` might be easily implemented with pattern matching similar to `children`. – Arseniy Zhizhelev Jan 22 '17 at 17:56
  • I wrote something similar to this: https://zeroturnaround.com/rebellabs/parsing-lambda-calculus-in-scala/ and went on to apply this to my more elaborate language. It seem okayish so far but I was also wondering about having Expr trait that is implemented by case classes and then each override pretty method. In addition, I found it hard to incorporate PrettyPrinter when I have types around. Types are not Expr, they are of type Type, so I'd probably need to make PrettyPrinter be a polymorphic kind of printer. Any thoughts? – StudentOfLogic Jan 23 '17 at 08:13
  • (1) you usually don't need to `override` methods in functional programming. The above `children` is not overriding anything - it's a standalone method that contains all logic in the single place. (2) Types can be treated similar to data when you are processing your own language. Scala has some type API to match types. You may have a look at a few questions: http://stackoverflow.com/search?q=match+TypeRef, http://stackoverflow.com/questions/12842729/finding-type-parameters-via-reflection-in-scala-2-10 – Arseniy Zhizhelev Jan 24 '17 at 09:21