Wednesday, 17 February 2010

A little Scala parser

package myparser;

import scala.util.parsing.combinator._

//
// Arithmétique: un petit parser
// Thierry
//
class Arithmétique extends JavaTokenParsers {
def expr: Parser[Double] = term ~ rep("plus" ~ term | "minus" ~ term) ^^ (evaluate(_))
def term: Parser[Double] = numb ~ rep("multiply" ~ numb | "divide" ~ numb) ^^ (evaluate(_))
def numb: Parser[Double] = fact ~ rep("expo" ~ fact) ^^ (evaluate(_))
def fact: Parser[Double] = floatingPointNumber ^^ (_.toDouble) | "(" ~> expr <~ ")"

def evaluate(value: ~[Double, List[~[String, Double]]]) : Double = value match {
case lhs~ops => (
(lhs /: ops)((acc, op) => op match {
case "plus"~rhs => acc + rhs
case "minus"~rhs => acc - rhs
case "multiply"~rhs => acc * rhs
case "divide"~rhs => acc / rhs
case "expo"~rhs => Math.pow(lhs, rhs)
})
)
}

def parse(data: String) = parseAll(expr, data)
}

object MyParser extends Arithmétique {
def main(args: Array[String]) {
val expr1 = "1 plus 2 expo 2"
val res1 = parse(expr1)
println(expr1 + " => " + res1.get)

val expr2 = "2 multiply (3 plus 7)"
val res2 = parse(expr2)
println(expr2 + " => " + res2.get)

val expr3 = "2 multiply (3 plus 7) multiply 3.14 divide 3.0"
val res3 = parse(expr3)
println(expr3 + " => " + res3.get)

val expr4 = "((2 multiply (3 plus 7)) plus 4) divide 2"
val res4 = parse(expr4)
println(expr4 + " => " + res4.get)

val expr5 = "10 expo 10"
val res5 = parse(expr5)
println(expr5 + " => " + res5.get)

val expr6 = "10 expo (5 divide 2)"
val res6 = parse(expr6)
println(expr6 + " => " + res6.get)
}
}

No comments: