bool AbstractParser::parseField(StringView words) { #define PARSE_FIELD(X) \ for (const auto x : DEFINED_ROOM_##X##_TYPES) { \ if (getParserCommandName(x).matches(firstWord)) { \ setRoomFieldCommand(x, RoomField::X##_TYPE); \ return true; \ } \ } if (words.isEmpty()) return false; // REVISIT: support "set room field XXX" ? const auto firstWord = words.takeFirstWord(); if (!words.isEmpty()) return false; PARSE_FIELD(LIGHT); PARSE_FIELD(SUNDEATH); PARSE_FIELD(PORTABLE); PARSE_FIELD(RIDABLE); PARSE_FIELD(ALIGN); return false; #undef PARSE }
void AbstractParser::parseSpecialCommand(StringView wholeCommand) { if (wholeCommand.isEmpty()) throw std::runtime_error("input is empty"); if (evalSpecialCommandMap(wholeCommand)) return; const auto word = wholeCommand.takeFirstWord(); sendToUser(QString("Unrecognized command: %1\r\n").arg(word.toQString())); }
void AbstractParser::parseName(StringView view) { if (!view.isEmpty()) { auto dir = tryGetDir(view); if (!view.isEmpty()) { auto name = view.takeFirstWord(); nameDoorCommand(name.toQString(), dir); return; } } showSyntax("name <dir> <name>"); }
bool AbstractParser::parseExitFlags(StringView words) { if (words.isEmpty()) return false; const auto firstWord = words.takeFirstWord(); for (const ExitFlag flag : ALL_EXIT_FLAGS) { if (getParserCommandName(flag).matches(firstWord)) { return parseExitFlag(flag, words); } } return false; }
bool AbstractParser::parseDoorAction(StringView words) { if (words.isEmpty()) return false; const auto firstWord = words.takeFirstWord(); for (const DoorActionType dat : ALL_DOOR_ACTION_TYPES) { if (getParserCommandName(dat).matches(firstWord)) { return parseDoorAction(dat, words); } } return false; }
void AbstractParser::parseSetCommand(StringView view) { if (view.isEmpty()) { sendToUser(QString("Syntax: %1set prefix [punct-char]\r\n").arg(prefixChar)); return; } auto first = view.takeFirstWord(); if (Abbrev{"prefix", 3}.matches(first)) { if (view.isEmpty()) { showCommandPrefix(); return; } auto next = view.takeFirstWord(); if (next.size() == 3) { auto quote = next.takeFirstLetter(); const bool validQuote = quote == '\'' || quote == '"'; const auto prefix = next.takeFirstLetter().toLatin1(); if (validQuote && isValidPrefix(prefix) && quote == next.takeFirstLetter() && quote != prefix && setCommandPrefix(prefix)) { return; } } else if (next.size() == 1) { const auto prefix = next.takeFirstLetter().toLatin1(); if (setCommandPrefix(prefix)) { return; } } sendToUser("Invalid prefix.\r\n"); return; } sendToUser("That variable is not supported."); }
bool AbstractParser::parseLoadFlags(StringView words) { if (words.isEmpty()) return false; const auto firstWord = words.takeFirstWord(); if (!words.isEmpty()) return false; for (const RoomLoadFlag loadFlag : ALL_LOAD_FLAGS) { if (getParserCommandName(loadFlag).matches(firstWord)) { toggleRoomFlagCommand(loadFlag, RoomField::LOAD_FLAGS); return true; } } return false; }
void AbstractParser::parseHelp(StringView words) { if (words.isEmpty()) { showHelp(); return; } auto next = words.takeFirstWord(); if (Abbrev{"abbreviations", 2}.matches(next)) { showHelpCommands(true); return; } else if (Abbrev{"commands", 1}.matches(next)) { showHelpCommands(false); return; } auto &map = m_specialCommandMap; auto name = next.toQString().toStdString(); auto it = map.find(name); if (it != map.end()) { it->second.help(name); return; } if (Abbrev{"map", 1}.matches(next)) showMapHelp(); else if (Abbrev{"door", 1}.matches(next)) showDoorCommandHelp(); else if (Abbrev{"group", 1}.matches(next)) showGroupHelp(); else if (Abbrev{"exits", 2}.matches(next)) showExitHelp(); else if (Abbrev{"flags", 1}.matches(next)) showRoomSimpleFlagsHelp(); else if (Abbrev{"mobiles", 2}.matches(next)) showRoomMobFlagsHelp(); else if (Abbrev{"load", 2}.matches(next)) showRoomLoadFlagsHelp(); else if (Abbrev{"miscellaneous", 2}.matches(next)) showMiscHelp(); else { showHelp(); } }
bool AbstractParser::evalSpecialCommandMap(StringView args) { if (args.empty()) return false; auto first = args.takeFirstWord(); auto &map = m_specialCommandMap; const std::string key = first.toQString().toStdString(); auto it = map.find(key); if (it == map.end()) return false; // REVISIT: add # of calls to the record? ParserRecord &rec = it->second; const auto qs = QString::fromStdString(rec.fullCommand); const auto matched = std::vector<StringView>{StringView{qs}}; return rec.callback(matched, args); }
bool AbstractParser::parsePrint(StringView &input) { const auto syntax = [this]() { sendToUser("Print what? [dynamic | static | note]\r\n"); }; if (input.isEmpty()) { syntax(); return true; } const auto next = input.takeFirstWord(); if (Abbrev{"dynamic", 1}.matches(next)) { printRoomInfo(dynamicRoomFields); return true; } else if (Abbrev{"static", 1}.matches(next)) { printRoomInfo(staticRoomFields); return true; } else if (Abbrev{"note", 1}.matches(next)) { showNote(); return true; } else { syntax(); return true; } }