import scala.util.parsing.combinator.JavaTokenParsers
/**
* Created by Stanislav on 02.05.2015.
*/
class lab4 (var text: String){
abstract class Expr
case class Variable(name : String) extends Expr
case class Number(value: Double) extends Expr
case class UnaryOp(operator: String, arg: Expr) extends Expr
case class BinaryOp(operator: String, left: Expr, right: Expr) extends Expr
def setText(t : String): Unit = {
text = t
}
object Calc {
def simplify(e: Expr): Expr = {
// сначала упрощаем подвыражения
val simpSubs = e match {
// упрощаем обе части выражения
case BinaryOp(op, left, right) => BinaryOp(op, simplify(left), simplify(right))
// упрощаем операнд
case UnaryOp(op, operand) => UnaryOp(op, simplify(operand))
// здесь нечего упрощать
case _ => e
}
// теперь упрощаем само выражение, считая,
// что все вложенные выражения уже упрощены
def simplifyTop(x: Expr) = x match {
// Двойное отрицание не меняет значение операнда
case UnaryOp("-", UnaryOp("-", x)) => x
// Знак "+" не меняет значение операнда
case UnaryOp("+", x) => x
// Умножение x на 1 равно х
case BinaryOp("*", x, Number(1)) => x
// Умножение 1 на x равно х
case BinaryOp("*", Number(1), x) => x
// Умножение х на 0 равно 0
case BinaryOp("*", x, Number(0)) => Number(0)
// Умножение 0 на x равно 0
case BinaryOp("*", Number(0), x) => Number(0)
// Деление х на 1 равно х
case BinaryOp("/", x, Number(1)) => x
// Добавление х к 0 равно х
case BinaryOp("+", x, Number(0)) => x
// Добавление 0 к х равно х
case BinaryOp("+", Number(0), x) => x
// Других вариантов упрощения нет
case _ => e
}
simplifyTop(simpSubs)
}
object ExprParser extends JavaTokenParsers {
def expr: Parser[Expr] =
(term ~ "-" ~ expr) ^^ { case lhs~minus~rhs => BinaryOp("-", lhs, rhs) } |
(term ~ "+" ~ expr) ^^ { case lhs~minus~rhs => BinaryOp("+", lhs, rhs) } |
term
def term: Parser[Expr] =
(factor ~ "*" ~ factor) ^^ { case lhs~times~rhs => BinaryOp("*", lhs, rhs) } |
(factor ~ "/" ~ factor) ^^ { case lhs~div~rhs => BinaryOp("/", lhs, rhs) } |
factor
def factor : Parser[Expr] =
"(" ~> expr <~ ")" |
floatingPointNumber ^^ {x => Number(x.toFloat)}|
ident ^^ {x => Variable(x)}
def parse(text : String) = parseAll(expr, text)
}
def parse(text : String) = {
val results = ExprParser.parse(text)
System.out.println("parsed " + text + " as " + results + " which is a type "
+ results.getClass())
results.get
}
def evaluate() : Double = evaluate(parse(text))
def evaluate(e: Expr): Double = {
simplify(e) match {
case Variable(x) => {
System.out.println("Введите значение переменной " + x)
System.out.print(x + " = ")
val temp = readLine()
evaluate(parse(temp))
}
case Number(x) => x
case UnaryOp("-", x) => -(evaluate(x))
case BinaryOp("+", x1, x2) => (evaluate(x1) + evaluate(x2))
case BinaryOp("-", x1, x2) => (evaluate(x1) - evaluate(x2))
case BinaryOp("*", x1, x2) => (evaluate(x1) * evaluate(x2))
case BinaryOp("/", x1, x2) => (evaluate(x1) / evaluate(x2))
}
}
}
}
object Main {
def main(args: Array[String]): Unit = {
var line = ""
System.out.println("Введите выражние: ")
line = readLine()
val t = new lab4(line)
while(true) {
System.out.println("Что надо сделать? Введите цифру:")
System.out.println("1. Ввести новое выражние")
System.out.println("2. Вычеслить результат")
System.out.println("3. Показать текущее выражение")
System.out.println("4. Вместо переменной выражение и перестроить дерево")
System.out.println("5. Выход")
System.out.print(">>>")
var action = readInt()
action match {
case 1 => {
line = readLine()
t.setText(line)
}
case 2 => System.out.println("Результат: " + t.Calc.evaluate())
case 3 => System.out.println("Выражение: " + line)
case 4 => System.out.println("Implemented method")
case 5 => System.exit(0)
}
}
}
}
// TODO: Иправить ошибку: 2-2-3 (скобки)