Skip to content

Instantly share code, notes, and snippets.

@JohnNilsson
Created March 5, 2011 00:47
Show Gist options
  • Save JohnNilsson/855981 to your computer and use it in GitHub Desktop.
Save JohnNilsson/855981 to your computer and use it in GitHub Desktop.
class Calc extends PackratParsers {
type Elem = Char
val vars = mutable.Map[Char,Int]()
def parse(input:CharSequence) = doIt(new PackratReader(new CharSequenceReader(input)))
val spaces: Parser[Seq[Char]] = elem("Whitespace", _.isWhitespace)*
val digit: Parser[Char] = elem("Digit", _.isDigit)
val letter: Parser[Char] = elem("Letter", _.isLetter)
val aVar: Parser[Char] = letter
val num: Parser[Int] = ((digit)+) ^^ { _.mkString.toInt }
val priExpr: Parser[Int] =
( spaces ~> aVar ^^ { vars(_) }
| spaces ~> num
| '('~>expr<~')' )
lazy val mulExpr: PackratParser[Int] =
( mulExpr~'*'~priExpr ^^ { case x~_~y => x*y }
| mulExpr~'/'~priExpr ^^ { case x~_~y => x/y }
| priExpr )
lazy val addExpr: PackratParser[Int] =
( addExpr~'+'~mulExpr ^^ { case x~_~y => x+y }
| addExpr~'-'~mulExpr ^^ { case x~_~y => x-y }
| mulExpr )
lazy val expr: Parser[Int] =
( aVar~'='~expr ^^ { case v~_~e => vars(v) = e; e }
| addExpr )
lazy val doIt: Parser[Int] = rep1sep(expr,';'~spaces)<~spaces ^^ ( _.last )
}
object CalcSpec extends Properties("Calc") {
val N = Gen.choose(0,100)
val Np = Gen.choose(1,100)
val C = Gen.choose('A','Z')
property("Literals") = forAll(N) { i => parse(i.toString) == i }
property("Sum") = forAll(N,N) { (x,y) => parse(x+"+"+y) == x+y }
property("Subt") = forAll(N,N) { (x,y) => parse(x+"-"+y) == x-y }
property("Mult") = forAll(N,N) { (x,y) => parse(x+"*"+y) == x*y }
property("Div") = forAll(N,Np) { (x,y) => parse(x+"/"+y) == x/y }
property("Presedence") =
( forAll(N,N,N) { (x,y,z) => parse( x+"+"+y+ "*"+z) == x+(y*z) }
&& forAll(N,N,N) { (x,y,z) => parse("("+x+"+"+y+")*"+z) == (x+y)*z } )
property("Store") = forAll(C,N) { (c,n) => parse(c+"="+n) == n }
property("Load" ) = forAll(C,N) { (c,n) => parse(c+"="+n+";"+c+"+"+c) == n+n }
property("Mutation" ) = forAll(C,N,N) { (c,x,y) => parse(c+"="+x+";"+c+"="+y+";"+c) == y }
private def parse(in:String) = (new Calc).parse(in).get
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment