Как разобрать строку с несколькими возможностями?

0

В последнее время я пишу очень повторный код. Мне нужно найти лучшее решение.

На данный момент я делаю это (псевдокод)

std::map<std::string/*commandname*/, commandfunction*> Commands;

void OnPlayerExecuteCommand(cplayer* player, std::string command, std::string parameters)
{
    //find check blablabla yaddayadda then..
    Commands[command]->execute(player, parameters);
}

//heal PlayerId/Name (float)amount
void Command_HealMe(cplayer* player, std::string parameters)
{
    SomeParsingCodeA(params);//get the cplayer* from playername or id and float heal amount
}
//vehicle name color1 color2, eg /vehicle Ferrari 0xFF0000 123456
void Command_SpawnVehicle(cplayer* player, std::string parameters)
{
    SomeParsingCodeB(params);//get the vehiclename, and colors
}

//kick playername/id reason, eg /kick player_a you are spamming the chat
void Command_KickSomeone(cplayer* player, std::string parameters)
{
    SomeParsingCodeC(params);//get cplayer* of playername or id, and get the rest string
}

Но каждый фрагмент SomeParsingCode* содержит много повторяющихся кодов, таких как IsValidPlayer(string)//returns Cplayer from id or name, анализирует строки на числа или float или что-то еще.

Я думаю, что проще писать код, создавая универсальную функцию синтаксического анализа, например:

auto result = ParseMyParameters("Player_string_or_int;int_or_hex;int_or_hex",input) if(result.good()){//continue

Я думал о сопоставлении каждого запроса персонажу, как:

character - expected input
u - PlayerName as String or PlayerID as integer(u as in user)
i - integer number
x - hex formatted number
f - real number
g - integer or hex
w - one worded string
r - return remaining string, 
    like /kick player_a you are spamming the chat
    would be parsed with "ur", and the result would be a cplayer pointer and the string "you are spamming the chat"

затем создавая функцию, которая пеет строку и анализирует все запрошенные вещи по одному.

Но я думал, что C++ имеет так много хороших вещей, я действительно не знаю, что использовать в этой ситуации, в каких контейнерах или boost/C++ можно использовать для этой задачи? Есть ли что-то уже в C++, которые позволили мне это сделать? Какой подход рекомендуется?

Кроме того, это, вероятно, потребует нескольких вариационных аргументов, использует varargs или я могу использовать некоторые вариативные шаблоны? как

ParseString<cplayer*,int,float,std::string>("Joe 5 5.0 hello my friend!");

с

std::string = "hello my friend!";

или

ParseString<cplayer*,int,float,std::vector<std::string>>("Joe 5 5.0 hello my friend!");

с std::vector<std::string> = {"hello", "my", "friend!"};

?

Теги:
parsing

1 ответ

0

Это проще, чем LEX (FLEX) или YACC (BISON).

Вы можете использовать их для определения своих команд и предоставления действий, когда они встречаются.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню