Created
August 25, 2012 20:00
-
-
Save edofic/3470294 to your computer and use it in GitHub Desktop.
very simple repl for math expressions(no variables)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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