Прежде чем вы начнете добавлять черты не столь ясной дополнительной ценности, вы должны правильно понять основы. То, как вы делаете это сейчас, делает эти классы не очень полезными, по крайней мере, при построении классического AST (или "дерева разбора"). Представь себе 4 * (3 + 5). Прежде чем вы сможете использовать операцию умножения, вы должны оценить сложение в первую очередь. Это усложняет ситуацию. Как правило, вы хотите иметь возможность написать свою формулу «сразу», например, Mul (4, Add (3, 5)). Однако это не сработает, так как вы не можете получить Ints или Doubles в свою собственную иерархию классов. Обычное решение - это класс-оболочка для Numbers, скажем, «Num». Тогда мы имеем: Mul (Num (4), Add (Num (3), Num (5)). Это может показаться сложным, но теперь у вас есть «все сразу», и вы можете делать такие вещи, как введение констант и переменных, упрощение (например, Mul (Num (1), x) -> x), деривация ...
Чтобы получить это, вам нужно что-то вроде
sealed trait Expr {
def eval:Int
}
case class Num(n:Int) extends Expr {
def eval = n
}
case class Neg(e: Expr) extends Expr {
def eval = - e.eval()
}
case class Add(e1: Expr, e2: Expr) extends Expr {
def eval = e1.eval + e2.eval
}
...
Теперь вы можете написать парсер, который превращает "4 * (3 + 5)" в Mul (Num (4), Add (Num (3), Num (5))) и получить результат, вызвав для этого eval выражение.
Scala уже содержит библиотеку синтаксического анализа, называемую комбинаторы синтаксического анализа. Пример, близкий к приведенному выше, см. В http://jim -mcbeath.blogspot.com / 2008/09 / scala-parser-combinators.html