Ниже может быть реализация простого конечного автомата в C ++. Класс Tokenizer поддерживает «переменные состояния токенизации» и возвращает токены, такие как теги HTML из потока символов.
Если есть какая-либо причина для перемещения функций handle_xxx () из класса Tokenizer;
И если да, то почему & как?
#include <iostream>
#include <map>
class Token;
class CharacterReader;
class Tokenizer {
TokenizerState current_state;
CharacterReader r;
std:map<TokenizerState, void (Tokenizer::*pmf)()> stateMap;
public:
// Tokenizer States
typedef enum { INITIAL = 0, STATE_1, STATE_2, END } TokenizerState;
// State Handlers
void handle_Initial();
void handle_State_1();
void handle_State_2();
// 20 more states before END...
void handle_End();
Tokenizer(String text_to_tokenize)
{
stateMap[INITIAL] = handle_Initial;
stateMap[STATE_1] = handle_State_1;
stateMap[STATE_2] = handle_State_2;
stateMap[END] = handle_End;
current_state = TokenizerState::INITIAL;
r.set(text_to_tokenize);
}
void switchState(TokenizerState s) { current_state = s; }
void run() {
while (current_state!=TokenizerState::END) {
Token token = stateMap[current_state]();
// do something with the Token
}
}
};
void Tokenizer::handle_Initial() {
}
void Tokenizer::handle_State_1() {
char c = r++;
switch(c) {
case 'a':
break;
case 'b':
ts.switchState(Tokenizer::TokenizerState::STATE_2);
}
}
void Tokenizer::handle_State_2() {
}
void Tokenizer::handle_End() {
}
ИМХО лучшим способом было бы выдвинуть все handle_XXX()
(читать XXX как конечный автомат, запускающий событие) методы для отдельного интерфейса, и имеют различные реализации для них для каждого из идентифицированных состояний. Реализация handle_XXX()
методы, могут получать ссылку на текущий экземпляр конечного автомата и манипулировать им / работать с ним (включая запуск изменения состояния).
Вот что предлагается в общеизвестных Государственный Образец
Один из существующих недостатков, которые я вижу в вашей реализации, заключается в том, что вы упускаете возможность отображать реальные события и отправлять их в отдельный обработчик.
Немного бессмысленно продолжать приводить понятный пример кода на этой базе, которую вы дали. Я надеюсь, вы правильно поняли мои указатели.
Почему бы не определить класс TokenizerHandler и передать его экземпляры в класс Tokenzier? Тот же самый способ ссылки на функции-члены может все еще работать.