AstNode* Parser::parseStatement() { if (isKeyword(currentTokenValue())) { if (currentTokenValue() == "function") { return parseFunction(); } else if (currentTokenValue() == "for") { return parseFor(); } else if (currentTokenValue() == "if") { return parseIf(); } else if (currentTokenValue() == "while") { return parseWhile(); } else if (currentTokenValue() == "print") { return parsePrint(); } else if (currentTokenValue() == "int") { return parseDeclaration(VT_INT); } else if (currentTokenValue() == "double") { return parseDeclaration(VT_DOUBLE); } else if (currentTokenValue() == "string") { return parseDeclaration(VT_STRING); } else if (currentTokenValue() == "return") { return parseReturn(); } else { cout << "unhandled keyword " << currentTokenValue() << endl; assert(false); return 0; } } if (currentToken() == tLBRACE) { return parseBlock(true); } if ((currentToken() == tIDENT) && isAssignment(lookaheadToken(1))) { return parseAssignment(); } return parseExpression(); }
void AbstractParser::initSpecialCommandMap() { auto &map = m_specialCommandMap; map.clear(); auto add = [this](Abbrev abb, const ParserCallback &callback, const HelpCallback &help) { addSpecialCommand(abb.getCommand(), abb.getMinAbbrev(), callback, help); }; const auto makeSimpleHelp = [this](const std::string &help) { return [this, help](const std::string &name) { sendToUser(QString("Help for %1%2:\r\n %3\r\n\r\n") .arg(prefixChar) .arg(QString::fromStdString(name)) .arg(QString::fromStdString(help))); }; }; qInfo() << "Adding special commands to the map..."; // help is important, so it comes first add(cmdHelp, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseHelp(rest); return true; }, // TODO: create a parse tree, and show all of the help topics. makeSimpleHelp("Provides help.")); add(cmdMapHelp, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->showMapHelp(); return true; }, makeSimpleHelp("Help for mapping console commands.")); add(cmdDoorHelp, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->showDoorCommandHelp(); return true; }, makeSimpleHelp("Help for door console commands.")); add(cmdGroupHelp, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->showGroupHelp(); return true; }, makeSimpleHelp("Help for group manager console commands.")); // door actions for (const DoorActionType x : ALL_DOOR_ACTION_TYPES) { if (auto cmd = getParserCommandName(x)) add(cmd, [this, x](const std::vector<StringView> & /*s*/, StringView rest) { return parseDoorAction(x, rest); }, makeSimpleHelp("Sets door action: " + std::string{cmd.getCommand()})); } for (const DoorFlag x : ALL_DOOR_FLAGS) { if (auto cmd = getParserCommandName(x)) add(getParserCommandName(x), [this, x](const std::vector<StringView> & /*s*/, StringView rest) { return parseDoorFlag(x, rest); }, makeSimpleHelp("Sets door flag: " + std::string{cmd.getCommand()})); } for (const ExitFlag x : ALL_EXIT_FLAGS) { if (auto cmd = getParserCommandName(x)) add(cmd, [this, x](const std::vector<StringView> & /*s*/, StringView rest) { return parseExitFlag(x, rest); }, makeSimpleHelp("Sets exit flag: " + std::string{cmd.getCommand()})); } #define ADD_FIELD_CMDS(X) \ do { \ for (const auto x : DEFINED_ROOM_##X##_TYPES) { \ if (auto cmd = getParserCommandName(x)) { \ auto type = RoomField::X##_TYPE; \ add(cmd, \ [this, x, type](const std::vector<StringView> & /*s*/, StringView rest) { \ if (!rest.isEmpty()) \ return false; \ setRoomFieldCommand(x, type); \ return true; \ }, \ makeSimpleHelp("Sets " #X " flag: " + std::string{cmd.getCommand()})); \ } \ } \ } while (false) ADD_FIELD_CMDS(LIGHT); ADD_FIELD_CMDS(SUNDEATH); ADD_FIELD_CMDS(PORTABLE); ADD_FIELD_CMDS(RIDABLE); ADD_FIELD_CMDS(ALIGN); #undef ADD_FIELD_CMDS for (const RoomMobFlag x : ALL_MOB_FLAGS) { if (auto cmd = getParserCommandName(x)) { add(cmd, [this, x](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; toggleRoomFlagCommand(x, RoomField::MOB_FLAGS); return true; }, makeSimpleHelp("Sets room mob flag: " + std::string{cmd.getCommand()})); } } for (const RoomLoadFlag x : ALL_LOAD_FLAGS) { if (auto cmd = getParserCommandName(x)) add(cmd, [this, x](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; toggleRoomFlagCommand(x, RoomField::LOAD_FLAGS); return true; }, makeSimpleHelp("Sets room load flag: " + std::string{cmd.getCommand()})); } // misc commands add(cmdBack, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->doBackCommand(); return true; }, makeSimpleHelp("Delete prespammed commands from queue.")); add(cmdDirections, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseDirections(rest); return true; }, makeSimpleHelp("Prints directions to matching rooms.")); add(cmdGroupKick, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseGroupKick(rest); return true; }, makeSimpleHelp("Kick [player] from the group.")); add(cmdGroupLock, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->doGroupLockCommand(); return true; }, makeSimpleHelp("Toggle the lock on the group.")); add(cmdGroupTell, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseGroupTell(rest); return true; }, makeSimpleHelp("Send a grouptell with the [message].")); add(cmdMarkCurrent, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->doMarkCurrentCommand(); return true; }, makeSimpleHelp("Highlight the room you are currently in.")); add(cmdName, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseName(rest); return true; }, makeSimpleHelp( "Arguments: <dir> <name>; Sets the name of door in direction <dir> with <name>.")); add(cmdNote, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseNoteCmd(rest); return true; }, makeSimpleHelp("Sets the note for the current room.")); add(cmdRemoveDoorNames, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->doRemoveDoorNamesCommand(); return true; }, makeSimpleHelp( "Removes all secret door names from the current map (WARNING: destructive)!")); add(cmdSearch, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseSearch(rest); return true; }, makeSimpleHelp("Highlight matching rooms on the map.")); add(cmdSet, [this](const std::vector<StringView> & /*s*/, StringView rest) { this->parseSetCommand(rest); return true; }, [this](const std::string &name) { const char help[] = "Subcommands:\r\n" "\tprefix # Displays the current prefix.\r\n" "\tprefix <punct-char> # Changes the current prefix.\r\n" "\r\n" // REVISIT: Does it actually support LATIN-1 punctuation like the degree symbol? "Note: <punct-char> may be any ASCII punctuation character,\r\n" " which can be optionally single- or double-quoted.\r\n" "\r\n" "Examples to set prefix:\r\n" "\tprefix / # slash character\r\n" "\tprefix '/' # single-quoted slash character\r\n" "\tprefix \"/\" # double-quoted slash character\r\n" "\tprefix ' # bare single-quote character\r\n" "\tprefix \"'\" # double-quoted single-quote character\r\n" "\tprefix \" # bare double-quote character\r\n" "\tprefix '\"' # single-quoted double-quote character\r\n" "\r\n" "Note: Quoted versions do not allow escape codes,\r\n" "so you cannot do ''', '\\'', \"\"\", or \"\\\"\"."; sendToUser(QString("Help for %1%2:\r\n%3\r\n\r\n") .arg(prefixChar) .arg(QString::fromStdString(name)) .arg(QString::fromStdString(help))); }); add(cmdTime, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->showMumeTime(); return true; }, makeSimpleHelp("Displays the current MUME time.")); add(cmdTrollExit, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->toggleTrollMapping(); return true; }, makeSimpleHelp("Toggles troll-only exit mapping for direct sunlight.")); add(cmdVote, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; this->openVoteURL(); return true; }, makeSimpleHelp("Launches a web browser so you can vote for MUME on TMC!")); /* print commands */ add(cmdPrint, [this](const std::vector<StringView> & /*s*/, StringView rest) { return parsePrint(rest); }, makeSimpleHelp("There is no help for this command yet.")); add(cmdPDynamic, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; printRoomInfo(dynamicRoomFields); return true; }, makeSimpleHelp("Prints current room description.")); add(cmdPStatic, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; printRoomInfo(staticRoomFields); return true; }, makeSimpleHelp("Prints current room description without movable items.")); add(cmdPNote, [this](const std::vector<StringView> & /*s*/, StringView rest) { if (!rest.isEmpty()) return false; showNote(); return true; }, makeSimpleHelp("Print the note in the current room.")); qInfo() << "Total commands + abbreviations: " << map.size(); }