upd: first version of lexer

This commit is contained in:
2023-12-13 08:59:59 +00:00
parent 132eeded36
commit 2d18a302f2
7 changed files with 545 additions and 8 deletions

View File

@ -19,11 +19,16 @@ class UserDataBase {
class BookDataBase {
DriveArray<BookItemClass> full_book_data;
String2Index indexer;
String2Index keyword2index;
public:
void Open(std::string file_name);
};
class LogDataBase {
DriveArray<FinanceItemClass> finance_data;
DriveArray<OperationLogItemClass> operation_log_data;
public:
void Open(std::string file_name);
};
#endif // PROTECTOR_DATABASE_HPP

View File

@ -9,11 +9,42 @@
class BookStoreEngineClass {
std::string config_dir;
UserDataBase user_data_base;
BookDataBase book_data_base;
LogDataBase log_data_base;
bool is_server;
public:
BookStoreEngineClass() = delete;
BookStoreEngineClass(std::string __config_dir, bool __is_server);
std::vector<std::string> Execute(const std::string &cmd,
std::stack<std::string> &login_stack);
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteSu(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteLogout(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteRegister(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecutePasswd(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteUserAdd(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteDelete(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteShow(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteBuy(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteSelect(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteMOdify(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteImport(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteShowFinance(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteLog(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
std::vector<std::string> ExecuteReport(const std::string &cmd,
std::stack<std::pair<std::string, std::string>> &login_stack);
};
#endif // PROTECTOR_ENGINE_H

View File

@ -4,7 +4,27 @@
#include <sstream>
#include <string>
#include <vector>
bool CommandSuLexer(const std::string &command, std::string &user_id,
std::string &password);
bool CommandLogoutLexer(const std::string &command);
bool CommandRegisterLexer(const std::string &command, std::string &user_id,
std::string &password, std::string &username);
bool CommandPasswdLexer(const std::string &command, std::string &user_id,
std::string &old_password, std::string &new_password);
bool CommandUseraddLexer(const std::string &command, std::string &user_id,
std::string &password, int &privilege,
std::string &username);
bool CommandDeleteLexer(const std::string &command, std::string &user_id);
bool CommandShowLexer(const std::string &command, std::string &ISBN,
std::string &name, std::string &author,
std::string &keyword);
bool CommandBuyLexer(const std::string &command, std::string &ISBN,
int &quantity);
bool CommandSelectLexer(const std::string &command, std::string &ISBN);
bool CommandModifyLexer(const std::string &command, std::string &ISBN,
std::string &name, std::string &author,
std::string &keyword, double &price);
bool CommandImportLexer(const std::string &command, int &quantity,
double &total_cost);
bool CommandShowfinanceLexer(const std::string &command,int &count);
#endif // PROTECTOR_LEXER_H

View File

@ -5,6 +5,7 @@
#include <stack>
#include <string>
#include <unordered_map>
#include <utility>
#include "bs-utility.h"
#include "engine.h"
@ -12,7 +13,7 @@ void BookStoreMain(bool is_server, std::string config_dir) {
BookStoreEngineClass engine(config_dir, is_server);
std::ios::sync_with_stdio(false);
if (!is_server) {
std::stack<std::string> login_stack;
std::stack<std::pair<std::string, std::string>> login_stack;
std::string cmd;
while (std::getline(std::cin, cmd)) {
auto result = std::move(engine.Execute(cmd, login_stack));

View File

@ -3,4 +3,14 @@
void UserDataBase::Open(std::string file_name) {
full_user_data.OpenFile(file_name + ".full");
user_name2index.OpenFile(file_name + ".n2i");
}
void BookDataBase::Open(std::string file_name) {
full_book_data.OpenFile(file_name + ".full");
indexer.OpenFile(file_name + ".n2i");
}
void LogDataBase::Open(std::string file_name) {
finance_data.OpenFile(file_name + ".finance");
operation_log_data.OpenFile(file_name + ".log");
}

View File

@ -1,5 +1,6 @@
#include "engine.h"
#include <cctype>
#include <stack>
#include <string>
#include <unordered_map>
@ -10,10 +11,15 @@ BookStoreEngineClass::BookStoreEngineClass(std::string __config_dir,
bool __is_server) {
config_dir = __config_dir;
user_data_base.Open(config_dir + "user");
book_data_base.Open(config_dir + "book");
log_data_base.Open(config_dir + "log");
is_server = __is_server;
}
std::vector<std::string> BookStoreEngineClass::Execute(
const std::string &cmd, std::stack<std::string> &login_stack) {
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
for (int i = 0; i < cmd.length(); i++)
if (std::isspace(cmd[i]) && cmd[i] != ' ')
return std::vector<std::string>({"Invalid"});
static std::unordered_map<std::string, OperationType> operation_map = {
{"su", OperationType::__Ksu},
{"logout", OperationType::__Klogout},
@ -42,38 +48,123 @@ std::vector<std::string> BookStoreEngineClass::Execute(
}
switch (operation_map[head]) {
case OperationType::__Ksu: {
return ExecuteSu(cmd, login_stack);
}
case OperationType::__Klogout: {
return ExecuteLogout(cmd, login_stack);
}
case OperationType::__Kuseradd: {
return ExecuteUserAdd(cmd, login_stack);
}
case OperationType::__Kregister: {
return ExecuteRegister(cmd, login_stack);
}
case OperationType::__Kdelete: {
return ExecuteDelete(cmd, login_stack);
}
case OperationType::__Kpasswd: {
return ExecutePasswd(cmd, login_stack);
}
case OperationType::__Kselect: {
return ExecuteSelect(cmd, login_stack);
}
case OperationType::__Kmodify: {
return ExecuteMOdify(cmd, login_stack);
}
case OperationType::__Kimport: {
return ExecuteImport(cmd, login_stack);
}
case OperationType::__Kshow: {
ss >> head;
if (head == "finance") goto dst_showfinance;
return ExecuteShow(cmd, login_stack);
}
case OperationType::__Kshowfinance: {
dst_showfinance:;
return ExecuteShowFinance(cmd, login_stack);
}
case OperationType::__Kbuy: {
return ExecuteBuy(cmd, login_stack);
}
case OperationType::__Kreport: {
throw FatalError("report Not implemented", 2);
// throw FatalError("report Not implemented", 2);
return ExecuteReport(cmd, login_stack);
}
case OperationType::__Klog: {
throw FatalError("log Not implemented", 3);
// throw FatalError("log Not implemented", 3);
return ExecuteLog(cmd, login_stack);
}
}
throw FatalError("Unknown Command", 5);
return std::vector<std::string>({cmd});
}
std::vector<std::string> BookStoreEngineClass::ExecuteSu(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteLogout(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteRegister(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecutePasswd(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteUserAdd(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteDelete(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteShow(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteBuy(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteSelect(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteMOdify(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteImport(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteShowFinance(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteLog(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}
std::vector<std::string> BookStoreEngineClass::ExecuteReport(
const std::string &cmd, std::stack<std::pair<std::string, std::string>> &login_stack) {
return std::vector<std::string>();
}

View File

@ -1,4 +1,210 @@
#include "lexer.h"
// clang-format off
/**
* @brief Lexer for command "su"
*
* @param command The command to be parsed
* @param user_id The user_id to be logged in
* @param password The password to be logged in
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* su [UserID] ([Password])?
*/
// clang-format on
bool CommandSuLexer(const std::string &command, std::string &user_id,
std::string &password) {
static std::basic_regex main_pattern(
R"(^ *su +(?:[0-9a-zA-Z_]{1,30}) +(?:[0-9a-zA-Z_]{1,30})? *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
user_id = "";
password = "";
ss >> user_id;
ss >> password;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "logout"
*
* @param command The command to be parsed
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* logout
*/
// clang-format on
bool CommandLogoutLexer(const std::string &command) {
static std::basic_regex main_pattern(R"(^ *logout *$)",
std::regex_constants::optimize);
return std::regex_match(command, main_pattern);
}
// clang-format off
/**
* @brief Lexer for command "register"
*
* @param command The command to be parsed
* @param user_id The user_id to be registered
* @param password The password to be registered
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* register [UserID] [Password] [Username]
*/
// clang-format on
bool CommandRegisterLexer(const std::string &command, std::string &user_id,
std::string &password, std::string &username) {
static std::basic_regex main_pattern(
R"(^ *register +(?:[0-9a-zA-Z_]{1,30}) +(?:[0-9a-zA-Z_]{1,30}) +(?:[^\s]{1,30}) *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
user_id = "";
password = "";
username = "";
ss >> user_id;
ss >> password;
ss >> username;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "passwd"
*
* @param command The command to be parsed
* @param user_id The user_id to be changed password
* @param old_password The old password
* @param new_password The new password
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* passwd [UserID] ([CurrentPassword])? [NewPassword]
*/
// clang-format on
bool CommandPasswdLexer(const std::string &command, std::string &user_id,
std::string &old_password, std::string &new_password) {
static std::basic_regex main_pattern(
R"(^ *passwd +(?:[0-9a-zA-Z_]{1,30}) +(?:[0-9a-zA-Z_]{1,30})? +(?:[0-9a-zA-Z_]{1,30}) *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
user_id = "";
old_password = "";
new_password = "";
ss >> user_id;
ss >> old_password;
ss >> new_password;
if (new_password == "") {
new_password = old_password;
old_password = "";
}
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "useradd"
*
* @param command The command to be parsed
* @param user_id The user_id to be added
* @param password The password to be added
* @param privilege The privilege to be added
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* useradd [UserID] [Password] [Privilege] [Username]
*/
// clang-format on
bool CommandUseraddLexer(const std::string &command, std::string &user_id,
std::string &password, int &privilege,
std::string &username) {
static std::basic_regex main_pattern(
R"(^ *useradd +(?:[0-9a-zA-Z_]{1,30}) +(?:[0-9a-zA-Z_]{1,30}) +[0-9] +(?:[^\s]{1,30}) *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
user_id = "";
password = "";
privilege = 0;
username = "";
ss >> user_id;
ss >> password;
ss >> privilege;
ss >> username;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "delete"
*
* @param command The command to be parsed
* @param user_id The user_id to be deleted
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* delete [UserID]
*/
// clang-format on
bool CommandDeleteLexer(const std::string &command, std::string &user_id) {
static std::basic_regex main_pattern(
R"(^ *delete +(?:[0-9a-zA-Z_]{1,30}) *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
user_id = "";
ss >> user_id;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "show"
*
* @param command The command to be parsed
* @param ISBN The ISBN of the book to be shown
* @param name The name of the book to be shown
* @param author The author of the book to be shown
* @param keyword The keyword of the book to be shown
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* show (-ISBN=[ISBN] | -name="[BookName]" | -author="[Author]" | -keyword="[Keyword]")?
*/
// clang-format on
bool CommandShowLexer(const std::string &command, std::string &ISBN,
std::string &name, std::string &author,
std::string &keyword) {
@ -6,7 +212,6 @@ bool CommandShowLexer(const std::string &command, std::string &ISBN,
R"(^ *show(?: +-ISBN=(?:\S{1,20})| +-name=\"(?:[^\s"]{1,60})\"| +-author=\"(?:[^\s"]{1,60})\"| +-keyword=\"(?:[^\s"]{1,60})\")* *$)",
std::regex_constants::optimize);
std::smatch results;
bool has_ISBN = false;
bool has_name = false;
bool has_author = false;
@ -15,7 +220,7 @@ bool CommandShowLexer(const std::string &command, std::string &ISBN,
name = "";
author = "";
keyword = "";
if (std::regex_match(command, results, main_pattern)) {
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
@ -39,6 +244,180 @@ bool CommandShowLexer(const std::string &command, std::string &ISBN,
} else
return false;
}
for (int i = 0; i < keyword.length(); i++)
if (keyword[i] == '|') return false;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "buy"
*
* @param command The command to be parsed
* @param ISBN The ISBN of the book to be bought
* @param quantity The quantity of the book to be bought
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* buy [ISBN] [Quantity]
*/
// clang-format on
bool CommandBuyLexer(const std::string &command, std::string &ISBN,
int &quantity) {
static std::basic_regex main_pattern(
R"(^ *buy +(?:\S{1,20}) +[0-9]{1,10} *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
ISBN = "";
quantity = 0;
ss >> ISBN;
ss >> quantity;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "select"
*
* @param command The command to be parsed
* @param ISBN The ISBN of the book to be selected
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* select [ISBN]
*/
// clang-format on
bool CommandSelectLexer(const std::string &command, std::string &ISBN) {
static std::basic_regex main_pattern(R"(^ *select +(?:\S{1,20}) *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
ISBN = "";
ss >> ISBN;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "modify"
*
* @param command The command to be parsed
* @param ISBN The ISBN of the book to be modified
* @param name The name of the book to be modified
* @param author The author of the book to be modified
* @param keyword The keyword of the book to be modified
* @param price The price of the book to be modified
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* modify (-ISBN=[ISBN] | -name="[BookName]" | -author="[Author]" | -keyword="[Keyword]" | -price=[Price])+
*/
// clang-format on
bool CommandModifyLexer(const std::string &command, std::string &ISBN,
std::string &name, std::string &author,
std::string &keyword, double &price) {
static std::basic_regex main_pattern(
R"(^ *modify(?: +-ISBN=(?:\S{1,20})| +-name=\"(?:[^\s"]{1,60})\"| +-author=\"(?:[^\s"]{1,60})\"| +-keyword=\"(?:[^\s"]{1,60})\"| +-price=[0-9]{1,10}\.[0-9]{2})+ *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
ISBN = "";
name = "";
author = "";
keyword = "";
price = 0;
while (ss >> token) {
if (token[1] == 'I') {
ISBN = token.substr(6);
} else if (token[1] == 'n') {
name = token.substr(6 + 1, token.size() - 7 - 1);
} else if (token[1] == 'a') {
author = token.substr(8 + 1, token.size() - 9 - 1);
} else if (token[1] == 'k') {
keyword = token.substr(9 + 1, token.size() - 10 - 1);
} else if (token[1] == 'p') {
price = std::stod(token.substr(7));
} else
return false;
}
for (int i = 0; i < keyword.length(); i++)
if (keyword[i] == '|') return false;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "import"
*
* @param command The command to be parsed
* @param quantity The quantity of the book to be imported
* @param total_cost The total cost of the book to be imported
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* import [Quantity] [TotalCost]
*/
// clang-format on
bool CommandImportLexer(const std::string &command, int &quantity,
double &total_cost) {
static std::basic_regex main_pattern(
R"(^ *import +[0-9]{1,10} +[0-9]{1,10}\.[0-9]{2} *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
quantity = 0;
total_cost = 0;
ss >> quantity;
ss >> total_cost;
return true;
} else
return false;
}
// clang-format off
/**
* @brief Lexer for command "showfinance"
*
* @param command The command to be parsed
* @param count The count of the finance to be shown
*
* @return true if the command is valid
*
* @note The command is valid if and only if it follows the following grammar:
* show finance ([Count])?
*/
// clang-format on
bool CommandShowfinanceLexer(const std::string &command, int &count) {
static std::basic_regex main_pattern(
R"(^ *show +finance(?: +[0-9]{1,10})? *$)",
std::regex_constants::optimize);
if (std::regex_match(command, main_pattern)) {
std::stringstream ss(command);
std::string token;
ss >> token;
count = -1;
ss >> count;
return true;
} else
return false;