Из второго задания задача
Задача поставлена так : прочитать стек до конца и записать все что в нем есть в правильной нотации
В общем случае стек может содержать несколько законченных выражений
Например, 2,2,+,2,2,+,2,2,+
В этом случае на выходе должно получиться , 2+2,2+2,2+2
Достаточно разобраться с обработкой одного выражения, а остальные два будут обработаны аналогично, так как функция evaluate возвращает остаток стека и можно видеть что обработка не закончена и перейти к созданию следующей строки
Функция evaluate рекурсивно вызывает себя в случае если элемент стека операция
Если элемент стека операнд, то происходит возврат результата вверх по цепочке функций
Для того чтобы правильно расставить скобки в выражении для бинарной операции нужно иметь информацию о приоритете последней выполненной над операндом операции, для этого нужно немного расширить свойства типа заданного enum Op
Нужно добавить параметр для задания приоритета операции целого типа
Например так
private enum Op : Printable{
case Operand(Double)
case UnaryOperation(String, Int, Double->Double)
case BinaryOperation(String, Int, (Double,Double)->Double)
case Variable(String)
var description:String{
get{
switch self{
case .Operand(let operand):
return "\(operand)"
case .Variable(let symbol):
return symbol
case .UnaryOperation(let symbol, _, _):
return symbol
case .BinaryOperation(let symbol, _, _):
return symbol
}
}
}
}
Тогда для получения нужной информации evaluate можно записать так
private func erbol(ops: [Op]) -> (result: Double?, remainingOps: [Op], pt:Int, di:String){
if !ops.isEmpty {
var remainingOps = ops
let op = remainingOps.removeLast()
switch op{
case .Operand(let operand):
return(operand,remainingOps, 255, "\(operand)")
case .Variable(let symbol):
// Ищем значение переменной в словаре
if let variableValue = variableValues[symbol] {
return (variableValue, remainingOps, 255, "")
} else {
// Если значения нет то возвращаем nil
return (nil, remainingOps, 255, "")
}
case .UnaryOperation(let symbolOperation, let priority, let operation):
let operandEvaluation = erbol(remainingOps)
if let operand = operandEvaluation.result{
let dis = symbolOperation + "(" + operandEvaluation.di + ")"
return (operation(operand), operandEvaluation.remainingOps, priority, dis)
}
case .BinaryOperation(let symbolOperation, let priority, let operation):
var op1Evaluation = erbol(remainingOps)
if let operand1 = op1Evaluation.result{
var op2Evaluation = erbol(op1Evaluation.remainingOps)
if let operand2 = op2Evaluation.result{
if (priority > op1Evaluation.pt){ op1Evaluation.di = "(" + op1Evaluation.di + ")"}
if (priority > op2Evaluation.pt){ op2Evaluation.di = "(" + op2Evaluation.di + ")"}
let dis = op2Evaluation.di + symbolOperation + op1Evaluation.di
return (operation(operand1,operand2),op2Evaluation.remainingOps, priority, dis)
}
}
}
}
return (nil, ops, 255, "")
}
func erbol1() {
let aa = erbol(opStack)
println("Дисплей " + aa.di)
}
Параметр di возвращает созданную строчку с содержимым стека