Skip to content

Instantly share code, notes, and snippets.

@edofic
Created August 25, 2012 20:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edofic/3470294 to your computer and use it in GitHub Desktop.
Save edofic/3470294 to your computer and use it in GitHub Desktop.
very simple repl for math expressions(no variables)
package parsing
import util.parsing.combinator.RegexParsers
/**
* User: andraz
* Date: 8/25/12
* Time: 4:05 PM
*/
object ExpressionParsing {
object Tokens {
sealed trait Expression
case class Number(n: Double) extends Expression
case class Add(left: Expression, right: Expression) extends Expression
case class Subtract(left: Expression, right: Expression) extends Expression
case class Multiply(left: Expression, right: Expression) extends Expression
case class Divide(left: Expression, right: Expression) extends Expression
}
object Parser extends RegexParsers {
import Tokens._
private def number: Parser[Expression] = """\d+\.?\d*""".r ^^ {
s => Number(s.toDouble)
}
private def factor: Parser[Expression] = number | ("(" ~> expr <~ ")")
private def term: Parser[Expression] = factor ~ rep(("*" | "/") ~ factor) ^^ {
case head ~ tail => {
var tree: Expression = head
tail.foreach {
case "*" ~ e => tree = Multiply(tree, e)
case "/" ~ e => tree = Divide(tree, e)
}
tree
}
}
private def expr: Parser[Expression] = term ~ rep(("+" | "-") ~ term) ^^ {
case head ~ tail => {
var tree: Expression = head
tail.foreach {
case "+" ~ e => tree = Add(tree, e)
case "-" ~ e => tree = Subtract(tree, e)
}
tree
}
}
def apply(s: String) = parseAll(expr, s) match {
case Success(tree, _) => Some(tree)
case e: NoSuccess => None
}
}
object Evaluator {
import Tokens._
def apply(e: Expression): Double = e match {
case Number(n) => n
case Add(l, r) => apply(l) + apply(r)
case Subtract(l, r) => apply(l) - apply(r)
case Multiply(l, r) => apply(l) * apply(r)
case Divide(l, r) => apply(l) / apply(r)
}
}
def apply(s: String) = Parser(s) map Evaluator.apply
def repl = {
def rep: Unit = {
print(">> ")
readLine match {
case "exit" => return
case "help" => println("enter an expression\nsupported: floats + - * / ( )")
case exp => {
println(
apply(exp) match {
case Some(res) => res
case None => "invalid syntax"
})
rep
}
}
}
rep
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment