Информация об изменениях

Сообщение Re[4]: [Nitra] Пример простого языка вычисляющего выражения от 08.12.2015 20:34

Изменено 09.12.2015 21:28 VladD2

Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, novitk, Вы писали:


N>>Мало? Я уверен, что реализация этой задачи на скажем ANTLR/Скале будет не больше.


VD>Я рад за твою уверенность. Сделай, сравним.


Думал оно будет очевидно. Впрочем мне не сложно набросать полсотни строчек.

import scala.util.parsing.combinator._

object Main extends JavaTokenParsers {
  class Expr;
  case class NumberExpr(num: Int) extends Expr;
  case class MultExpr(expr: Expr) extends Expr;
  case class DivExpr(expr: Expr) extends Expr;
  case class AddExpr(expr: Expr) extends Expr;
  case class SubtractExpr(expr: Expr) extends Expr;
  case class VarExpr(name: String) extends Expr;
  case class OpExpr(expr: Expr, subExprs: List[Expr]) extends Expr;
  class VarDef(val name: String, val expr: Expr)

  class EvalContext(val vars: Map[String, VarDef]) {
    val results = scala.collection.mutable.Map[String, Int]()
    def evalVar(name: String): Int =
      {
        if (!results.contains(name))
          results(name) = evalExpr(vars(name).expr)
        results(name)
      }
    def evalExpr(expr: Expr): Int = expr match {
      case NumberExpr(num) => num
      case VarExpr(name: String) => evalVar(name)
      case OpExpr(expr, subExprs: List[Expr]) =>
        subExprs.foldLeft(evalExpr(expr)) {
          (a, subExpr) =>
            subExpr match {
              case MultExpr(exprInner) => a * evalExpr(exprInner)
              case DivExpr(exprInner) => a / evalExpr(exprInner)
              case AddExpr(exprInner) => a + evalExpr(exprInner)
              case SubtractExpr(exprInner) => a - evalExpr(exprInner)
            }
        }
    }
  }

  def makeOpExpr(p: ~[Expr, List[Expr]]): Expr = p match {
    case f ~ Nil => f
    case f ~ l => OpExpr(f, l)
  }
  def factor: Parser[Expr] = wholeNumber ^^ (s => NumberExpr(s.toInt)) | ident ^^ VarExpr | "(" ~> expr <~ ")"
  def term: Parser[Expr] = (factor ~ rep("*" ~> factor ^^ MultExpr | "/" ~> factor ^^ DivExpr)) ^^ makeOpExpr
  def expr: Parser[Expr] = (term ~ rep("+" ~> term ^^ AddExpr | "-" ~> term ^^ SubtractExpr)) ^^ makeOpExpr
  def varDef: Parser[VarDef] = ("var" ~> ident) ~ ("=" ~> expr) ^^ { case n ~ e => new VarDef(n, e) }
  def varDefParseAll(in: CharSequence): ParseResult[VarDef] = parseAll(varDef, in)

  def main(args: Array[String]) = {
    val vars: Map[String, VarDef] = Map(args.toSeq.map(varDefParseAll).filter(_.successful).map {
      pr =>
        {
          val vd = pr.get
          vd.name -> vd
        }
    }: _*)
    val evalCtx = new EvalContext(vars)
    println(evalCtx.evalVar("b"))
  }
}
Re[4]: [Nitra] Пример простого языка вычисляющего выражения
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, novitk, Вы писали:


N>>Мало? Я уверен, что реализация этой задачи на скажем ANTLR/Скале будет не больше.


VD>Я рад за твою уверенность. Сделай, сравним.


Думал оно будет очевидно. Впрочем мне не сложно набросать полсотни строчек.

[scala]
import scala.util.parsing.combinator._

object Main extends JavaTokenParsers {
class Expr;
case class NumberExpr(num: Int) extends Expr;
case class MultExpr(expr: Expr) extends Expr;
case class DivExpr(expr: Expr) extends Expr;
case class AddExpr(expr: Expr) extends Expr;
case class SubtractExpr(expr: Expr) extends Expr;
case class VarExpr(name: String) extends Expr;
case class OpExpr(expr: Expr, subExprs: List[Expr]) extends Expr;
class VarDef(val name: String, val expr: Expr)

class EvalContext(val vars: Map[String, VarDef]) {
val results = scala.collection.mutable.Map[String, Int]()
def evalVar(name: String): Int =
{
if (!results.contains(name))
results(name) = evalExpr(vars(name).expr)
results(name)
}
def evalExpr(expr: Expr): Int = expr match {
case NumberExpr(num) => num
case VarExpr(name: String) => evalVar(name)
case OpExpr(expr, subExprs: List[Expr]) =>
subExprs.foldLeft(evalExpr(expr)) {
(a, subExpr) =>
subExpr match {
case MultExpr(exprInner) => a * evalExpr(exprInner)
case DivExpr(exprInner) => a / evalExpr(exprInner)
case AddExpr(exprInner) => a + evalExpr(exprInner)
case SubtractExpr(exprInner) => a — evalExpr(exprInner)
}
}
}
}

def makeOpExpr(p: ~[Expr, List[Expr]]): Expr = p match {
case f ~ Nil => f
case f ~ l => OpExpr(f, l)
}
def factor: Parser[Expr] = wholeNumber ^^ (s => NumberExpr(s.toInt)) | ident ^^ VarExpr | "(" ~> expr <~ ")"
def term: Parser[Expr] = (factor ~ rep("*" ~> factor ^^ MultExpr | "/" ~> factor ^^ DivExpr)) ^^ makeOpExpr
def expr: Parser[Expr] = (term ~ rep("+" ~> term ^^ AddExpr | "-" ~> term ^^ SubtractExpr)) ^^ makeOpExpr
def varDef: Parser[VarDef] = ("var" ~> ident) ~ ("=" ~> expr) ^^ { case n ~ e => new VarDef(n, e) }
def varDefParseAll(in: CharSequence): ParseResult[VarDef] = parseAll(varDef, in)

def main(args: Array[String]) = {
val vars: Map[String, VarDef] = Map(args.toSeq.map(varDefParseAll).filter(_.successful).map {
pr =>
{
val vd = pr.get
vd.name -> vd
}
}: _*)
val evalCtx = new EvalContext(vars)
println(evalCtx.evalVar("b"))
}
}
[/scala]