fork download
  1. import scala.util.parsing.combinator.RegexParsers
  2.  
  3.  
  4. case class Var(name : String) extends Term {
  5. override def toString = name
  6. }
  7.  
  8. case class Fun(varname : String, body : Term) extends Term {
  9. override def toString = s"(\\$varname.$body)"
  10. }
  11.  
  12. case class App(left : Term, right : Term) extends Term {
  13. override def toString = s"($left $right)"
  14. }
  15.  
  16. trait Semantic {
  17. def reduce(term : Term): Option[Term]
  18. }
  19.  
  20. object NormalOrder extends Semantic {
  21. override def reduce(term : Term): Option[Term] = term match {
  22. case App(left, right) => reduce(left) match {
  23. case Some(Fun(leftVarname, leftBody)) => reduce(apply(leftBody, leftVarname, right))
  24. case _ => None
  25. }
  26. case _ => Some(term)
  27. }
  28.  
  29. def apply(body : Term, varname : String, term : Term) : Term = body match {
  30. case Var(varname1) => if(varname1 == varname) term else Var(varname1)
  31. case Fun(varname1, body1) => Fun(varname1, apply(body1, varname, term))
  32. case App(left, right) => App(apply(left, varname, term), apply(right, varname, term))
  33. }
  34. }
  35.  
  36. object LambdaParsers extends RegexParsers {
  37. override def skipWhitespace = false
  38.  
  39. def variable : Parser[Term] = "\\w+".r ^^ {
  40. x => Var(x)
  41. }
  42.  
  43. def function : Parser[Term] = "\\(\\\\".r ~ variable ~ "\\.".r ~ term ~ "\\)".r ^^ {
  44. case _ ~ Var(varname) ~ _ ~ body ~ _ => Fun(varname, body)
  45. }
  46.  
  47. def application : Parser[Term] = "\\(".r ~ term ~ "\\s".r ~ term ~ "\\)".r ^^ {
  48. case _ ~ left ~ _ ~ right ~ _ => App(left, right)
  49. }
  50.  
  51. def term = function | application | variable
  52. }
  53.  
  54. object TopLevel {
  55. def eval(expression : String) : String = {
  56. val term = LambdaParsers.parse(LambdaParsers.term, expression).get
  57. NormalOrder.reduce(term) match {
  58. case Some(result) => result.toString
  59. case None => "Something wrong!"
  60. }
  61. }
  62. }
  63.  
  64. object Main {
  65. def main(args : Array[String]) = {
  66. println(TopLevel.eval(raw"(((\x.(\y.(x y))) (\z.z)) a)"))
  67. }
  68. }
  69.  
Success #stdin #stdout 0.37s 382080KB
stdin
Standard input is empty
stdout
a