Skip to content

Instantly share code, notes, and snippets.

Created October 22, 2009 03:42
Show Gist options
  • Save anonymous/215710 to your computer and use it in GitHub Desktop.
Save anonymous/215710 to your computer and use it in GitHub Desktop.
sealed abstract class Expr {
def eval():Double
}
case class EValue(value:Double) extends Expr {
def eval():Double = value
}
case class ESum(a:List[Expr]) extends Expr {
def eval():Double = a.foldLeft(0.0)(_+_.eval)
}
case class ESubtract(a:List[Expr]) extends Expr {
def eval():Double = a.tail.foldLeft(a.head.eval)(_-_.eval)
}
case class EMult(a:List[Expr]) extends Expr {
def eval():Double = a.foldLeft(1.0)(_*_.eval)
}
case class EDiv(a:List[Expr]) extends Expr {
def eval():Double = a.tail.foldLeft(a.head.eval)(_/_.eval)
}
import scala.util.parsing.combinator.syntactical._
object PNCalc extends StandardTokenParsers {
val opMap = Map("+" -> ESum, "-" -> ESubtract, "*" -> EMult, "/" -> EDiv)
lexical.delimiters ++= List("(",")") ++ opMap.keysIterator.toList
def value = numericLit ^^ { s => EValue(s.toDouble) }
//def operator = "+" | "-" | "/" | "*"
def operator = opMap.keysIterator.toList.tail.foldLeft(Parser(opMap.keysIterator.toList.head))(_|_)
def sum:Parser[Expr] = "(" ~ "+" ~> rep(value|expr) <~ ")" ^^ {
a:List[Expr] => ESum(a)
}
def subtract:Parser[Expr] = "(" ~ "-" ~> rep(value|expr) <~ ")" ^^ {
a:List[Expr] => ESubtract(a)
}
def multiply:Parser[Expr] = "(" ~ "*" ~> rep(value|expr) <~ ")" ^^ {
a:List[Expr] => EMult(a)
}
def divide:Parser[Expr] = "(" ~ "/" ~> rep(value|expr) <~ ")" ^^ {
a:List[Expr] => EDiv(a)
}
def expr:Parser[Expr] = (value|sum|subtract|multiply|divide)
def parse(s:String) = {
phrase(expr)(new lexical.Scanner(s))
}
def apply(s:String):Expr = {
parse(s) match {
case Success(tree,_) => tree
case e:NoSuccess =>
throw new IllegalArgumentException("Bad Syntax "+s)
}
}
def test(exprstr:String) = {
parse(exprstr) match {
case Success(tree,_) =>
println("Tree: "+tree)
val v = tree.eval()
println("Eval: "+v)
case e:NoSuccess => Console.err.println(e)
}
}
def main(args:Array[String]) = test(args(0))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment