15. И НАДО БЫ УКРОТИТЬ АЛГОРИТМ ИНТЕРПРЕТАЦИИ
Т.о., мы сделали компактную, неменяющуюся "преобразовалку" инфиксного выражения в выражение в формате ПОЛИЗ. Нам осталось упростить алгоритм интерпретации.
Когда внутри него была лишь сущность "операнд" и "четыре действия арифметики", он бы невелик:
std::vector<double> Stack;
TToken token;
while (GetToken(&token))
{
switch (token.GetType())
{
case eTokenOperand: //Операнд
Stack.push_back(token.GetOperand());
break;
case eTokenPlus: //Плюс
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 + fltArg2);
}
break;
case eTokenMinus: //Минус
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 - fltArg2);
}
break;
case eTokenMultiply: //Умножить
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 * fltArg2);
}
break;
case eTokenDivide: //Разделить
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 / fltArg2);
}
break;
}
}
Теперь же количество case’ов внутри длинного оператора switch выросло на блок "Функция". Было бы только это, смирились бы. Но и внутри нового блока "Функция" возникает "портянка" по числу видов функций, которые должен "понимать" интерпретатор, а число их не ограничено.
std::vector<double> Stack;
TToken token;
while (GetToken(&token))
{
switch (token.GetType())
{
case eTokenOperand: //Операнд
Stack.push_back(token.GetOperand());
break;
case eTokenPlus: //Плюс
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 + fltArg2);
}
break;
case eTokenMinus: //Минус
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 - fltArg2);
}
break;
case eTokenMultiply: //Умножить
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 * fltArg2);
}
break;
case eTokenDivide: //Разделить
{
double fltArg2 = Stack.back();
Stack.pop_back();
double fltArg1 = Stack.back();
Stack.pop_back();
Stack.push_back(fltArg1 / fltArg2);
}
break;
case eTokenFunction: //Функция
{
if (token.GetText() == "sin") //Синус
{
double fltArg = Stack.back();
Stack.pop_back();
Stack.push_back(sin(fltArg));
}
else if (token.GetText() == "cos") //Косинус
{
double fltArg = Stack.back();
Stack.pop_back();
Stack.push_back(cos(fltArg));
}
else if (token.GetText() == "sqrt") //Корень квадратный
{
double fltArg = Stack.back();
Stack.pop_back();
Stack.push_back(sqrt(fltArg));
}
}
break;
}
}
А у нас требования к "идеальной программе". Как быть?
Далее...