C ++ State Machine

Ниже может быть реализация простого конечного автомата в 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() {
}

0

Решение

ИМХО лучшим способом было бы выдвинуть все handle_XXX() (читать XXX как конечный автомат, запускающий событие) методы для отдельного интерфейса, и имеют различные реализации для них для каждого из идентифицированных состояний. Реализация handle_XXX() методы, могут получать ссылку на текущий экземпляр конечного автомата и манипулировать им / работать с ним (включая запуск изменения состояния).

Вот что предлагается в общеизвестных Государственный Образец

Один из существующих недостатков, которые я вижу в вашей реализации, заключается в том, что вы упускаете возможность отображать реальные события и отправлять их в отдельный обработчик.

Немного бессмысленно продолжать приводить понятный пример кода на этой базе, которую вы дали. Я надеюсь, вы правильно поняли мои указатели.

0

Другие решения

Почему бы не определить класс TokenizerHandler и передать его экземпляры в класс Tokenzier? Тот же самый способ ссылки на функции-члены может все еще работать.

-1

По вопросам рекламы [email protected]