Created
July 31, 2021 14:03
-
-
Save emadflash/62a01ff48d771c0e97f052909e73f579 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <optional> | |
#include <iterator> | |
#include <fstream> | |
#include <cassert> | |
#include <map> | |
const char* filename = "mfclib/source/file.c"; | |
namespace Utils { | |
auto trim(std::string& s) -> std::string { | |
// start here | |
} | |
} // namespace Utils | |
namespace ParserEnum { | |
enum Enums { | |
SEE_COMMENT_BEGIN, | |
SEE_TODO, | |
SEE_COMMENT_END, | |
SEE_LEFT_PAREN, | |
SEE_RIGHT_PAREN, | |
}; | |
std::map<Enums, std::string_view> state_map = { | |
{ Enums::SEE_COMMENT_BEGIN, "//" }, | |
{ Enums::SEE_TODO, "TODO" }, | |
{ Enums::SEE_COMMENT_END, "TODO" }, | |
{ Enums::SEE_LEFT_PAREN, "(" }, | |
{ Enums::SEE_RIGHT_PAREN, ")" }, | |
}; | |
auto get(Enums x) -> std::optional<std::string> { | |
auto _found = state_map.find(x); | |
if (_found != state_map.end()) { | |
return std::make_optional<std::string>(_found->second); | |
} else { | |
return {}; | |
} | |
} | |
} // namespace ParserEnum; | |
namespace Parser { | |
auto is_vaild_t_find = [](auto It) -> std::optional<decltype(It)> { | |
auto _end = It + 4; | |
if (std::string(It, _end) == "TODO") { | |
return std::make_optional<decltype(It)>(_end);; | |
} | |
return {}; | |
}; | |
enum ContentsEnum { | |
AUTHOR_NAME, | |
DATA, | |
}; | |
struct Contents { | |
std::string author_name, data; | |
//bool has(ParserState& s, ContentsEnum c) const { | |
//bool _ret {}; | |
//switch(c) { | |
//case AUTHOR_NAME: | |
//_ret = bool(s.visit_paren); | |
//break; | |
//case DATA: | |
//_ret = true; | |
//break; | |
//deafult: | |
//break; | |
//} | |
//return _ret; | |
//} | |
}; | |
template <typename It=std::string::iterator> | |
struct ParserState { | |
bool is_match_todo {}; | |
bool is_more_; // additional info provided | |
bool visit_paren_left {}; | |
bool visit_paren_right {}; | |
bool visit_paren {}; | |
It marker_left_paren; | |
It marker_right_paren; | |
It marker_todo_end; | |
}; | |
///////////////////////////////////////////////// | |
// Parses single line containing "TODO" crap // | |
///////////////////////////////////////////////// | |
template<typename It> | |
auto parse(It begin, It end) -> std::optional<Contents> { | |
Contents contents; | |
ParserState state; | |
It _begin = begin; | |
while(_begin != end) { | |
if (*_begin == 'T' and state.is_match_todo == false) { | |
auto _next_t = is_vaild_t_find(_begin); | |
if (_next_t.has_value()) { | |
state.is_match_todo = true; // TODO match | |
_begin = _next_t.value(); | |
state.marker_todo_end = _begin; | |
continue; | |
} | |
_begin++; | |
} | |
else if (state.is_match_todo) { | |
// HACK(madflash) Can't compare char to string, so we need to pull out single char. | |
if (*_begin == ParserEnum::get(ParserEnum::Enums::SEE_LEFT_PAREN).value()[0] | |
and state.visit_paren == false | |
and state.visit_paren_left == false) { | |
_begin = std::next(_begin); | |
state.marker_left_paren = _begin; | |
state.visit_paren_left = true; | |
} | |
else if (*_begin == ParserEnum::get(ParserEnum::Enums::SEE_RIGHT_PAREN).value()[0] | |
and state.visit_paren_left == true | |
and state.visit_paren_right == false) { | |
contents.author_name = std::string(state.marker_left_paren, _begin); | |
state.marker_right_paren = std::next(_begin) + 1; | |
contents.data = std::string(state.marker_right_paren, end); | |
state.visit_paren_right = true; | |
state.visit_paren = true; | |
_begin = state.marker_right_paren; | |
goto DONE; | |
} | |
} | |
_begin++; | |
} | |
if (state.visit_paren_left && not state.visit_paren) return {}; | |
else if(not state.visit_paren_left) { | |
contents.data = std::string(state.marker_todo_end, end); | |
return std::make_optional<Contents>(contents); | |
} | |
DONE: | |
return std::make_optional<Contents>(contents); | |
} | |
} // namespace Parser | |
int main(int argc, char** argv) { | |
std::ifstream file { filename }; | |
if (!file.good()) { | |
std::cerr << "ERROR: reading file: " << filename; | |
std::exit(EXIT_FAILURE); | |
} | |
std::string line; | |
while(getline(file, line)) { | |
auto _begin = line.begin(); | |
auto _end = line.end(); | |
while(_begin != _end) { | |
auto combine_bytes = std::string(_begin, std::next(_begin) + 1); | |
if (combine_bytes == ParserEnum::get(ParserEnum::Enums::SEE_COMMENT_BEGIN)) { | |
auto status = Parser::parse(line.begin(), line.end()); | |
if (status.has_value()) { | |
std::cout << status.value().author_name << "\n"; | |
std::cout << status.value().data << "\n"; | |
} else { | |
std::cout << "DEBUG: NO LINE\n"; | |
} | |
} else { | |
} | |
_begin++; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment