Skip to content

Instantly share code, notes, and snippets.

@emadflash
Created July 31, 2021 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emadflash/62a01ff48d771c0e97f052909e73f579 to your computer and use it in GitHub Desktop.
Save emadflash/62a01ff48d771c0e97f052909e73f579 to your computer and use it in GitHub Desktop.
#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