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
run: $(NAME)
ASAN_OPTIONS=detect_leaks=0 ./$(NAME)
ASAN_OPTIONS=detect_leaks=0 ./$(NAME) $(filter-out $@,$(MAKECMDGOALS))
.PHONY: all clean fclean re

View File

@@ -34,10 +34,32 @@ void Server::print_epoll_events(unsigned int events)
//----------------------------------------------Send--------------------------------------------------------------------------------------------
//----------------------------------------------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::iterator it1;
@@ -406,9 +428,9 @@ void Server::clean_parsed(TOMLMap *root)
DBOUT << ">>> cleaning up: <<<" << std::endl;
for (it = root->begin(); it != root->end(); ++it)
{
/* DBOUT << RED << it->first */
/* << ": " << GREEN */
/* << *(it->second->toString()); */
DBOUT << RED << it->first
<< ": " << GREEN
<< *(it->second->toString());
clean_generic(it->second);
/* delete it->second; */

View File

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

View File

@@ -25,7 +25,7 @@
namespace config
{
TOMLParser::TOMLParser(const std::string filename) : tokenizer(filename)
TOMLParser::TOMLParser(char *filename) : tokenizer(filename)
{};
void TOMLParser::processMap(void)
@@ -35,7 +35,7 @@ namespace config
s_token current;
try { current = tokenizer.getToken(); }
catch (std::logic_error e)
catch (Tokenizer::NoMoreTokens &e)
{
std::cerr << e.what() << std::endl;
return;
@@ -43,11 +43,13 @@ namespace config
if (current.type == MAP_DECL)
{
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();
}
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; */
@@ -71,7 +73,7 @@ namespace config
{
s_token nextToken;
try { nextToken = tokenizer.getToken(); }
catch (std::logic_error e)
catch (Tokenizer::NoMoreTokens &e)
{
std::cerr << e.what() << std::endl;
break;
@@ -90,8 +92,11 @@ namespace config
}
std::string key = nextToken.value;
/* std::cerr << key << std::endl; */
DBOUT << RED << "key is " << key << ENDL;
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();
switch (nextToken.type)
{
@@ -126,8 +131,9 @@ namespace config
}
default:
{
throw UnexpectedToken(nextToken.value, key);
/* 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;
break;
}
@@ -138,13 +144,14 @@ namespace config
break;
if (nextToken.type != NEWLINE)
{
throw std::logic_error("EXPECTED newline");
// throw std::logic_error("EXPECTED newline");
throw ExpectedToken("newline", "parsing Hash Table");
}
}
else
{
throw std::logic_error("parseMap: no more tokens");
}
// else
// {
// throw std::logic_error("parseMap: no more tokens");
// }
}
node->setObject(mapObject);
return (node);
@@ -158,7 +165,7 @@ namespace config
s_token current;
try { current = tokenizer.getToken(); }
catch (std::logic_error e)
catch (Tokenizer::NoMoreTokens &e)
{
std::cerr << e.what() << std::endl;
return;
@@ -257,7 +264,9 @@ namespace config
}
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)
completed = true;
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);
@@ -313,7 +323,7 @@ namespace config
{
s_token current;
try { current = tokenizer.getToken(); }
catch (std::logic_error e)
catch (Tokenizer::NoMoreTokens &e)
{
std::cerr << e.what() << std::endl;
break;

View File

@@ -23,7 +23,7 @@ namespace config
toml_node *map_node, toml_node::e_type type);
public:
TOMLParser(const std::string filename);
TOMLParser(char *filename);
TOMLMap *parse(void);
toml_node *parseMap(void);
@@ -41,8 +41,52 @@ namespace config
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 ! */
/* TOMLMap *TOMLParser::parse(void); */
}

View File

@@ -38,18 +38,29 @@ namespace config
else
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())
{
std::cerr << "file didn't open" << std::endl;
throw std::logic_error("file didnt open");
}
}
bool Tokenizer::firstToken()
{
// 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);
else
return (false);
@@ -57,16 +68,15 @@ namespace config
struct s_token Tokenizer::getToken(void)
{
char c;
struct s_token token;
if (file.eof())
{
std::cout << "Tokens exhausted" << std::endl;
throw std::logic_error("Tokens exhausted");
DBOUT << RED << "Tokens exhausted" << ENDL;
throw NoMoreTokens();
}
prev_pos = file.tellg();
c = getWithoutWhiteSpace();
char c = getWithoutWhiteSpace();
if (firstToken() && config::istomlkey(c))
{
@@ -97,7 +107,7 @@ namespace config
{
token.type = MAPARRAY_DECL;
file.get(c);
while (c != ']')
while (c != ']' && config::istomlmapdecl(c))
{
token.value += c;
file.get(c);
@@ -105,7 +115,7 @@ namespace config
if (c == ']')
file.get(c);
if (c != ']')
throw std::logic_error("error in MAPARRAY_DECL");
throw InvalidToken("[[" + token.value);
}
else
{
@@ -118,7 +128,8 @@ namespace config
file.get(c);
}
if (c != ']')
throw std::logic_error("malformed MAP_DECL");
// throw std::logic_error("malformed MAP_DECL");
throw InvalidToken(token.value);
}
}
else if (c == '[')
@@ -130,7 +141,21 @@ namespace config
else if (c == '=')
token.type = ASSIGN;
else if (c == '\n')
{
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))
{
std::streampos prevCharPos;
@@ -162,6 +187,8 @@ namespace config
token.value += c;
file.get(c);
}
if (token.value != "false")
throw InvalidToken(token.value);
file.seekg(-1, std::ios_base::cur);
}
@@ -173,18 +200,65 @@ namespace config
token.value += c;
file.get(c);
}
if (token.value != "true")
throw InvalidToken(token.value);
file.seekg(-1, std::ios_base::cur);
}
else if (c == 'n')
{
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 == ',')
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;
DBOUT << YELLO << "GOT " << token.value << ", type: " << token.type << ENDL;
return (token);
}
char Tokenizer::getWithoutWhiteSpace(void)
{
char c = ' ';
@@ -192,9 +266,7 @@ namespace config
{
file.get(c);
if ((c == ' ') && !file.good())
{
throw std::logic_error("No more tokens!");
}
throw NoMoreTokens();
else if (!file.good())
return (c);
}

View File

@@ -27,7 +27,9 @@ namespace config
OPEN_BRACKET,
CLOSE_BRACKET,
MAP_DECL,
MAPARRAY_DECL
MAPARRAY_DECL,
COMMENT,
NO_TOK
};
struct s_token
@@ -41,6 +43,8 @@ namespace config
bool istomlkey(char c);
bool istomlmapdecl(char c);
class Tokenizer
{
private:
@@ -49,7 +53,7 @@ namespace config
e_token last_token;
public:
Tokenizer(std::string filename);
Tokenizer(char *filename);
char getWithoutWhiteSpace();
struct s_token getToken();
bool hasMoreTokens();
@@ -57,6 +61,37 @@ namespace config
void rollBackToken();
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) */

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);
TOMLMap *root = parser.parse();
/* config::display(root); */

View File

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

View File

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