package lab11 import java.io._ import scala.util.parsing.combinator._ class Definition case class Valdef(name : String, expr : ExprTree) extends Definition case class Defdef(name : String, expr : ExprTree) extends Definition class ExprTree case class Block(defs : List[Definition], expr : ExprTree) case class Number(value : Int) extends ExprTree case class Variable(name : String) extends ExprTree case class Operator(left : ExprTree, right : ExprTree, f: (Int, Int) => Int) extends ExprTree case class Function(params : List[String], body : Block) extends ExprTree case class IfExpr(cond : ExprTree, thenBlock : Block, elseBlock : Block) extends ExprTree case class Funcall(fun : ExprTree, args : List[ExprTree]) extends ExprTree case class Closure(params : List[String], body : Block, var env : List[(String, Any)]) extends ExprTree { override def toString = "Closure(" + params + "," + body + ")" } class SL1Parser extends JavaTokenParsers { def block: Parser[Block] = rep(valdef | defdef) ~ expr ^^ { case lst ~ e => Block(lst, e) } def expr: Parser[ExprTree] = ("if" ~> ("(" ~> expr <~ ")") ~ block <~ "else") ~ block ^^ { case e ~ b1 ~ b2 => IfExpr(e, b1, b2) } | expr2 def expr2: Parser[ExprTree] = (term ~ rep(("+" | "-") ~ term)) ^^ { case a ~ lst => (a /: lst) { case (x, "+" ~ y) => Operator(x, y, _ + _) case (x, "-" ~ y) => Operator(x, y, _ - _) } } def term: Parser[ExprTree] = (factor ~ rep(("*" | "/" ) ~ factor)) ^^ { case a ~ lst => (a /: lst) { case (x, "*" ~ y) => Operator(x, y, _ * _) case (x, "/" ~ y) => Operator(x, y, _ / _) } } def factor: Parser[ExprTree] = wholeNumber ^^ { x : String => Number(x.toInt) } | "(" ~> expr <~ ")" | valOrFuncall def valOrFuncall = valOrFun ~ opt( "(" ~> repsep(expr, ",") <~ ")" ) ^^ { case expr ~ Some(args) => Funcall(expr, args) case expr ~ None => expr } def valOrFun = "(" ~> expr <~ ")" | ident ^^ { Variable(_) } | funliteral def funliteral: Parser[ExprTree] = ("{" ~> repsep(ident, ",") <~ "=>") ~ block <~ "}" ^^ { case params ~ block => Function(params, block) } def funcall: Parser[ExprTree] = expr ~ ( "(" ~> repsep(expr, ",") <~ ")" ) ^^ { case fun ~ args => Funcall(fun, args) } def valdef: Parser[Definition] = ("val" ~> ident <~ "=") ~ (expr <~ ";") ^^ { case name ~ expr => Valdef(name, expr) } def defdef: Parser[Definition] = ("def" ~> ident <~ "=") ~ (funliteral <~ ";") ^^ { case name ~ expr => Defdef(name, expr) } } object Main { def spy[T](t : T) = { println(t); t } def lookup(name : String, symbols : List[(String, Any)]) = symbols.find(_._1 == name) match { case Some(pair) => pair._2 case None => None } def eval(expr : ExprTree, symbols : List[(String, Any)]) : Any = expr match { case Number(num) => num case Variable(name) => lookup(name, symbols) case Operator(left, right, f) => { eval(left, symbols) match { case arg1 : Int => eval(right, symbols) match { case arg2 : Int => f(arg1, arg2) } } } case IfExpr(cond, block1, block2) => { eval(cond, symbols) match { case result : Int => if (result > 0) evalBlock(block1, symbols) else evalBlock(block2, symbols) } } case Funcall(fun, args) => eval(fun, symbols) match { case Closure(params, body, syms) => evalBlock(body, params.zip(args.map(eval(_, symbols))) ::: syms) } case Function(params, body) => Closure(params, body, symbols) case _ => expr } def evalDef(symbols : List[(String, Any)], defn : Definition) = defn match { case Defdef(name, Function(params, body)) => { val cl = Closure(params, body, symbols) val syms = (name, cl) :: symbols cl.env = syms syms } case Valdef(name, Function(params, body)) => { (name, Closure(params, body, symbols)) :: symbols } case Valdef(name, expr) => { (name, eval(expr, symbols)) :: symbols } } def evalBlock(block : Block, symbols : List[(String, Any)]) : Any = eval(block.expr, (symbols /: block.defs) { evalDef(_, _) } ) def main(args : Array[String]) : Unit = { val parser = new SL1Parser val result = parser.parse(parser.block, new InputStreamReader(System.in)) println(result) println(evalBlock(result.get, List())) } }