Вот немного другой способ реализации - с чистыми функциями, без классов.
Но в виде templates.
Обратите внимание на главную функция Real. Она короткая. Весь фокус в матрице, где записаны имена функций-состояний.
В главной функции цикл остается неизменным - меняется только матрица. И вызов функции-состояния делается по указателю. На КП реализовать - нефиг делать.
Код:
Листинг 5.6. Шаблонная реализация автомата–преобразователя дробных констант
// шаблон Number
template<class T>
struct Number
{ int signN;
T N;
T FP;
T F;
bool signP;
T P;
Number():signN(+1), N(),FP(), F(), signP(true), P() {}
};
// Функции-обработчики
// в состоянии start – обработка знака
template<class T>
State startS(const char &ch, Number<T> &D)
{ if (ch == '-') D.signN = -1;
return s1; // первая цифра
}
// в состоянии start и s1 – обработка первой цифры
template<class T>
State startD(const char &ch, Number<T> &D)
{ D.N = digit(ch);
return s2; // целая часть
}
// в состоянии s2 – обработка цифр целой части
template<class T>
State intD(const char &ch, Number<T> &D)
{ D.N = D.N * 10 + digit(ch);
return s2; // целая часть
}
// . . . [b]Здесь еще несколько функций - состояний[/b]
template<class T>
T Real(const string &str)
{ typedef State (*Action)(const char &ch, Number<T> &D);
Action matrix[Class][states] =
// start s1 s2 s3 s4 s5 s6 s7
// перед после целая после дроб. после после порядок
// числом знака часть точки часть Е знака Е
{{startD, startD, intD, float1D, floatD, exp1D, exp1D, expD },//цифра
{Error, Error, Point, Error, Error, Error, Error, Error},//точка
{Error, Error, Exp, Error, Exp, Error, Error, Error},//порядок
{startS, Error, Error, Error, Error, expS, Error, Error},//знак
{Error, Error, Other, Error, Other, Error, Error, Other} //другой
};
Number<T> D;
double result;
size_t n = 0;
State s = start;
while((s != finish)&&(s != error)&&(n < str.size()))
{ Symbol t = type(str[n]);
s = matrix[t][s](str[n], D); //cout << endl;
++n;
}
if ((s==s2)||(s==s4)||(s==s7)||(s==finish))
{ result = D.N+D.F;
if(!D.signP) D.P = -D.P;
result = D.signN * result * pow(static_cast<T>(10.0), D.P);
}
else result = 0;
return result;
}