Merge remote-tracking branch 'origin/parser' into fara

This commit is contained in:
Talyx
2022-02-14 21:08:19 +03:00
10 changed files with 230 additions and 47 deletions

View File

@@ -41,6 +41,6 @@ re:
$(MAKE) all $(MAKE) all
run: $(NAME) run: $(NAME)
ASAN_OPTIONS=detect_leaks=0 ./$(NAME) ASAN_OPTIONS=detect_leaks=0 ./$(NAME) $(filter-out $@,$(MAKECMDGOALS))
.PHONY: all clean fclean re .PHONY: all clean fclean re

View File

@@ -34,10 +34,32 @@ void Server::print_epoll_events(unsigned int events)
//----------------------------------------------Send-------------------------------------------------------------------------------------------- //----------------------------------------------Send--------------------------------------------------------------------------------------------
//----------------------------------------------Configuration----------------------------------------------------------------------------------- //----------------------------------------------Configuration-----------------------------------------------------------------------------------
void Server::readConfig(void) void Server::readConfig(char *filename)
{ {
TOMLMap *root = parse(); TOMLMap *root = NULL;
try
{
root = parse(filename);
}
catch (config::Tokenizer::NoMoreTokens &e)
{
std::cerr << RED << "FATAL: ";
std::cerr << e.what() << RESET << std::endl;
// root->clear();
// delete root;
// clean_parsed(root);
return;
}
catch (config::Tokenizer::InvalidToken &e)
{
std::cerr << RED << "FATAL: ";
std::cerr << e.what() << RESET << std::endl;
// clean_parsed(root);
// root->clear();
delete root;
return;
}
/* TOMLMap *map; */ /* TOMLMap *map; */
TOMLMap::iterator it1; TOMLMap::iterator it1;
@@ -406,9 +428,9 @@ void Server::clean_parsed(TOMLMap *root)
DBOUT << ">>> cleaning up: <<<" << std::endl; DBOUT << ">>> cleaning up: <<<" << std::endl;
for (it = root->begin(); it != root->end(); ++it) for (it = root->begin(); it != root->end(); ++it)
{ {
/* DBOUT << RED << it->first */ DBOUT << RED << it->first
/* << ": " << GREEN */ << ": " << GREEN
/* << *(it->second->toString()); */ << *(it->second->toString());
clean_generic(it->second); clean_generic(it->second);
/* delete it->second; */ /* delete it->second; */

View File

@@ -56,7 +56,7 @@ class Server
Server(); Server();
Server(std::string path); Server(std::string path);
void readConfig(void); void readConfig(char *filename);
void setupConfig(void); void setupConfig(void);
void start(void); void start(void);
void end(void); void end(void);

View File

@@ -25,7 +25,7 @@
namespace config namespace config
{ {
TOMLParser::TOMLParser(const std::string filename) : tokenizer(filename) TOMLParser::TOMLParser(char *filename) : tokenizer(filename)
{}; {};
void TOMLParser::processMap(void) void TOMLParser::processMap(void)
@@ -35,7 +35,7 @@ namespace config
s_token current; s_token current;
try { current = tokenizer.getToken(); } try { current = tokenizer.getToken(); }
catch (std::logic_error e) catch (Tokenizer::NoMoreTokens &e)
{ {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return; return;
@@ -43,11 +43,13 @@ namespace config
if (current.type == MAP_DECL) if (current.type == MAP_DECL)
{ {
if (tokenizer.getToken().type != NEWLINE) if (tokenizer.getToken().type != NEWLINE)
throw std::logic_error("no newline after MAP_DECL"); throw ExpectedToken("newline", current.value);
// throw std::logic_error("no newline after MAP_DECL");
map_node = parseMap(); map_node = parseMap();
} }
else else
throw std::logic_error("unexpected token in processMap"); // throw std::logic_error("unexpected token in processMap");
throw UnexpectedToken("", current.value);
/* std::cout << current.value << std::endl; */ /* std::cout << current.value << std::endl; */
@@ -71,7 +73,7 @@ namespace config
{ {
s_token nextToken; s_token nextToken;
try { nextToken = tokenizer.getToken(); } try { nextToken = tokenizer.getToken(); }
catch (std::logic_error e) catch (Tokenizer::NoMoreTokens &e)
{ {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
break; break;
@@ -90,8 +92,11 @@ namespace config
} }
std::string key = nextToken.value; std::string key = nextToken.value;
/* std::cerr << key << std::endl; */ /* std::cerr << key << std::endl; */
DBOUT << RED << "key is " << key << ENDL;
if (tokenizer.getToken().type != ASSIGN) if (tokenizer.getToken().type != ASSIGN)
throw std::logic_error("EXPECTED assign!"); throw ExpectedToken("assign", "after " + key);
// throw std::logic_error("EXPECTED assign! 1");
nextToken = tokenizer.getToken(); nextToken = tokenizer.getToken();
switch (nextToken.type) switch (nextToken.type)
{ {
@@ -126,8 +131,9 @@ namespace config
} }
default: default:
{ {
throw UnexpectedToken(nextToken.value, key);
/* throw std::logic_error("jopa in parseMap"); */ /* throw std::logic_error("jopa in parseMap"); */
std::cerr << "Unknown token, marking as complete" << std::endl; // std::cerr << "Unknown token, marking as complete" << std::endl;
completed = true; completed = true;
break; break;
} }
@@ -138,13 +144,14 @@ namespace config
break; break;
if (nextToken.type != NEWLINE) if (nextToken.type != NEWLINE)
{ {
throw std::logic_error("EXPECTED newline"); // throw std::logic_error("EXPECTED newline");
throw ExpectedToken("newline", "parsing Hash Table");
} }
} }
else // else
{ // {
throw std::logic_error("parseMap: no more tokens"); // throw std::logic_error("parseMap: no more tokens");
} // }
} }
node->setObject(mapObject); node->setObject(mapObject);
return (node); return (node);
@@ -158,7 +165,7 @@ namespace config
s_token current; s_token current;
try { current = tokenizer.getToken(); } try { current = tokenizer.getToken(); }
catch (std::logic_error e) catch (Tokenizer::NoMoreTokens &e)
{ {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return; return;
@@ -257,7 +264,9 @@ namespace config
} }
default: default:
{ {
throw std::logic_error("unkown token in parseArray"); // throw std::logic_error("unkown token in parseArray");
throw UnexpectedToken("entry " + current.value,
"in Array");
} }
} }
@@ -268,7 +277,8 @@ namespace config
else if (current.type == CLOSE_BRACKET) else if (current.type == CLOSE_BRACKET)
completed = true; completed = true;
else else
throw std::invalid_argument("Unexpected token in array!"); throw UnexpectedToken(current.value, ", when expected COMMA, or CLOSE_BRACKET");
// throw std::invalid_argument("Unexpected token in array!");
} }
} }
result->setArr(array); result->setArr(array);
@@ -313,7 +323,7 @@ namespace config
{ {
s_token current; s_token current;
try { current = tokenizer.getToken(); } try { current = tokenizer.getToken(); }
catch (std::logic_error e) catch (Tokenizer::NoMoreTokens &e)
{ {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
break; break;

View File

@@ -23,7 +23,7 @@ namespace config
toml_node *map_node, toml_node::e_type type); toml_node *map_node, toml_node::e_type type);
public: public:
TOMLParser(const std::string filename); TOMLParser(char *filename);
TOMLMap *parse(void); TOMLMap *parse(void);
toml_node *parseMap(void); toml_node *parseMap(void);
@@ -41,8 +41,52 @@ namespace config
toml_node *parseNil(void); toml_node *parseNil(void);
}; class ExpectedToken: public std::exception
{
protected:
std::string *msg;
public:
ExpectedToken(const std::string &missing, const std::string context)
{
msg = new std::string("Config file: ");
*msg += ("Expected " + missing + " at " + context);
}
virtual const char *what() const throw()
{
return (msg->c_str());
}
virtual ~ExpectedToken() throw()
{
delete msg;
}
};
class UnexpectedToken: public std::exception
{
protected:
std::string *msg;
public:
UnexpectedToken(const std::string &unexpected, const std::string context)
{
msg = new std::string("Config file: ");
*msg += ("Unexpected " + unexpected + " " + context);
}
virtual const char *what() const throw()
{
return (msg->c_str());
}
virtual ~UnexpectedToken() throw()
{
delete msg;
}
};
};
/* parse tha root ! */ /* parse tha root ! */
/* TOMLMap *TOMLParser::parse(void); */ /* TOMLMap *TOMLParser::parse(void); */
} }

View File

@@ -38,18 +38,29 @@ namespace config
else else
return (false); return (false);
} }
Tokenizer::Tokenizer(std::string filename)
bool istomlmapdecl(char c)
{ {
file.open(filename.c_str(), std::ios::in); if (isalnum(c) || c == '-' || c == '_' || c == '.')
return (true);
else
return (false);
}
Tokenizer::Tokenizer(char *filename)
{
last_token = NO_TOK;
file.open(filename, std::ios::in);
if (!file.good()) if (!file.good())
{ {
std::cerr << "file didn't open" << std::endl; std::cerr << "file didn't open" << std::endl;
throw std::logic_error("file didnt open");
} }
} }
bool Tokenizer::firstToken() bool Tokenizer::firstToken()
{ {
// doesn't account for indent! // doesn't account for indent!
if (file.tellg() == 0 || file.tellg() == 1 || (last_token == NEWLINE)) if (file.tellg() == 0 || file.tellg() == 1 || (last_token == NEWLINE || last_token == NO_TOK))
return (true); return (true);
else else
return (false); return (false);
@@ -57,16 +68,15 @@ namespace config
struct s_token Tokenizer::getToken(void) struct s_token Tokenizer::getToken(void)
{ {
char c;
struct s_token token; struct s_token token;
if (file.eof()) if (file.eof())
{ {
std::cout << "Tokens exhausted" << std::endl; DBOUT << RED << "Tokens exhausted" << ENDL;
throw std::logic_error("Tokens exhausted"); throw NoMoreTokens();
} }
prev_pos = file.tellg(); prev_pos = file.tellg();
c = getWithoutWhiteSpace(); char c = getWithoutWhiteSpace();
if (firstToken() && config::istomlkey(c)) if (firstToken() && config::istomlkey(c))
{ {
@@ -97,7 +107,7 @@ namespace config
{ {
token.type = MAPARRAY_DECL; token.type = MAPARRAY_DECL;
file.get(c); file.get(c);
while (c != ']') while (c != ']' && config::istomlmapdecl(c))
{ {
token.value += c; token.value += c;
file.get(c); file.get(c);
@@ -105,7 +115,7 @@ namespace config
if (c == ']') if (c == ']')
file.get(c); file.get(c);
if (c != ']') if (c != ']')
throw std::logic_error("error in MAPARRAY_DECL"); throw InvalidToken("[[" + token.value);
} }
else else
{ {
@@ -118,7 +128,8 @@ namespace config
file.get(c); file.get(c);
} }
if (c != ']') if (c != ']')
throw std::logic_error("malformed MAP_DECL"); // throw std::logic_error("malformed MAP_DECL");
throw InvalidToken(token.value);
} }
} }
else if (c == '[') else if (c == '[')
@@ -130,7 +141,21 @@ namespace config
else if (c == '=') else if (c == '=')
token.type = ASSIGN; token.type = ASSIGN;
else if (c == '\n') else if (c == '\n')
{
token.type = NEWLINE; token.type = NEWLINE;
do
file.get(c);
while (c == '\n' && !file.eof());
if (file.eof())
{
file.clear();
DBOUT << "cleared" <<ENDL;
}
else if (c != '\n')
file.seekg(-1, std::ios_base::cur);
}
else if (c == '-' || isdigit(c)) else if (c == '-' || isdigit(c))
{ {
std::streampos prevCharPos; std::streampos prevCharPos;
@@ -162,6 +187,8 @@ namespace config
token.value += c; token.value += c;
file.get(c); file.get(c);
} }
if (token.value != "false")
throw InvalidToken(token.value);
file.seekg(-1, std::ios_base::cur); file.seekg(-1, std::ios_base::cur);
} }
@@ -173,18 +200,65 @@ namespace config
token.value += c; token.value += c;
file.get(c); file.get(c);
} }
if (token.value != "true")
throw InvalidToken(token.value);
file.seekg(-1, std::ios_base::cur); file.seekg(-1, std::ios_base::cur);
} }
else if (c == 'n') else if (c == 'n')
{ {
token.type = NIL; token.type = NIL;
file.seekg(3, std::ios_base::cur); while (std::isalpha(c))
{
token.value += c;
file.get(c);
}
if (token.value != "null")
throw InvalidToken(token.value);
} }
else if (c == ',') else if (c == ',')
token.type = COMMA; token.type = COMMA;
else if (c == '#')
{
// consume all comments
do
file.get(c);
while (c != '\n' || file.eof());
DBOUT << "getting comment token" << ENDL;
if (last_token == NO_TOK || last_token == NEWLINE)
{
DBOUT << "getting first token instead of comment" << ENDL;
struct s_token actual;
actual.type = NEWLINE;
while (actual.type == NEWLINE)
actual = getToken();
DBOUT
<< "actual token: '"
<< actual.value << "', type: "
<< actual.type
<< ENDL;
token = actual;
}
else
token.type = NEWLINE;
}
else
{
while (!config::isspace(c) && (c != '\n'))
{
DBOUT << RED << "[" << c << "]" <<ENDL;
token.value += c;
file.get(c);
}
throw InvalidToken(token.value);
}
last_token = token.type; last_token = token.type;
DBOUT << YELLO << "GOT " << token.value << ", type: " << token.type << ENDL;
return (token); return (token);
} }
char Tokenizer::getWithoutWhiteSpace(void) char Tokenizer::getWithoutWhiteSpace(void)
{ {
char c = ' '; char c = ' ';
@@ -192,9 +266,7 @@ namespace config
{ {
file.get(c); file.get(c);
if ((c == ' ') && !file.good()) if ((c == ' ') && !file.good())
{ throw NoMoreTokens();
throw std::logic_error("No more tokens!");
}
else if (!file.good()) else if (!file.good())
return (c); return (c);
} }

View File

@@ -27,7 +27,9 @@ namespace config
OPEN_BRACKET, OPEN_BRACKET,
CLOSE_BRACKET, CLOSE_BRACKET,
MAP_DECL, MAP_DECL,
MAPARRAY_DECL MAPARRAY_DECL,
COMMENT,
NO_TOK
}; };
struct s_token struct s_token
@@ -41,6 +43,8 @@ namespace config
bool istomlkey(char c); bool istomlkey(char c);
bool istomlmapdecl(char c);
class Tokenizer class Tokenizer
{ {
private: private:
@@ -49,7 +53,7 @@ namespace config
e_token last_token; e_token last_token;
public: public:
Tokenizer(std::string filename); Tokenizer(char *filename);
char getWithoutWhiteSpace(); char getWithoutWhiteSpace();
struct s_token getToken(); struct s_token getToken();
bool hasMoreTokens(); bool hasMoreTokens();
@@ -57,6 +61,37 @@ namespace config
void rollBackToken(); void rollBackToken();
void set_last(e_token type); void set_last(e_token type);
class NoMoreTokens: public std::exception
{
public:
virtual const char *what() const throw()
{
return ("Config may be incomplete, expected more tokens (check EOL)");
}
};
class InvalidToken: public std::exception
{
protected:
std::string *msg;
public:
InvalidToken(const std::string &token)
{
msg = new std::string("Invalid token: '" + token + "'");
}
virtual const char *what() const throw()
{
return (msg->c_str());
}
virtual ~InvalidToken() throw()
{
delete msg;
}
};
}; };
/* struct s_token Tokenizer::getKey(void) */ /* struct s_token Tokenizer::getKey(void) */

View File

@@ -38,9 +38,9 @@ namespace config
} }
} }
TOMLMap *parse(void) TOMLMap *parse(char *filename)
{ {
std::string filename = "config/tester.toml"; // std::string fiцename = "config/simple.toml";
config::TOMLParser parser(filename); config::TOMLParser parser(filename);
TOMLMap *root = parser.parse(); TOMLMap *root = parser.parse();
/* config::display(root); */ /* config::display(root); */

View File

@@ -7,7 +7,7 @@
#include "TOMLNode.hpp" #include "TOMLNode.hpp"
#include "TOMLParser.hpp" #include "TOMLParser.hpp"
TOMLMap *parse(void); TOMLMap *parse(char *filename);
void display(TOMLMap *config); void display(TOMLMap *config);
#endif #endif

View File

@@ -10,10 +10,10 @@ int main(int argc, char **argv)
Server server; Server server;
server.readConfig(); server.readConfig(argv[1]);
server.setupConfig(); server.setupConfig();
server.start(); // server.start();
server.end(); server.end();
return (0); return (0);