// // main.cpp // stateful_dice // // Created by Sam Jaffe on 12/18/18. // Copyright © 2018 Sam Jaffe. All rights reserved. // #include #include #include #include #include "dice-roll/exception.h" void usage() { std::cout << "'help' : Print this message\n"; std::cout << "'A := Dice' : Create a substitution pattern\n"; std::cout << "'1d6+$Dex' : Roll 1d6 plus whatever value subs for 'Dex'\n"; } void print_binding_os(std::pair const & pair, std::ostream & os) { os << pair.first; if (pair.second == "") os << " is not defined\n"; else os << " := " << pair.second << "\n"; } void print_binding(std::pair const & pair) { print_binding_os(pair, std::cout); } class evaluator { public: evaluator(std::string const & path = "") { if (!path.empty()) { load(path); } } void operator()(std::string const & str); private: using binding_t = std::map; bool regex_search(char const * regex) { return std::regex_match(curr, match, std::regex(regex)); } binding_t::value_type find_or(std::string const & key) const { auto it = bindings.find(key); return it == bindings.cend() ? binding_t::value_type(key, "") : *it; } void save(std::string const & file) const { using namespace std::placeholders; std::ofstream out(file); std::for_each(bindings.begin(), bindings.end(), std::bind(&print_binding_os, _1, std::ref(out))); } void load(std::string const & file) { std::ifstream in(file); while (std::getline(in, curr)) { if (regex_search(R"(^(\w+)\s*:=\s*(.*)$)")) { bindings[match[1]] = match[2]; } } } private: std::string curr; std::smatch match; binding_t bindings; }; void evaluator::operator()(std::string const & str) { curr = str; try { if (regex_search(R"(help|\?)")) { usage(); } else if (regex_search(R"(^(\w+)\s*:=\s*(.*)$)")) { bindings[match[1]] = match[2]; } else if (regex_search(R"(^show (\*|all))")) { std::for_each(bindings.begin(), bindings.end(), &print_binding); } else if (regex_search(R"(^show (\w+))")) { print_binding(find_or(match[1])); } else if (regex_search(R"(^unset (\*|all))")) { bindings.clear(); } else if (regex_search(R"(^unset (\w+))")) { bindings.erase(match[1]); } else if (regex_search(R"(^save (.+))")) { save(match[1]); } else if (regex_search(R"(^load new (.+))")) { bindings.clear(); load(match[1]); } else if (regex_search(R"(^load (.+))")) { load(match[1]); } else { while (regex_search(R"(.*(\$\w+).*)")) { curr.replace(match[1].first, match[1].second, find_or(match[1].str().substr(1)).second); } auto d = dice::from_string(curr); auto rs = dice::roller()(d); std::cout << std::make_pair(d, rs) << '\n'; } } catch (dice::unexpected_token const & ut) { std::cerr << "Error in roll: '" << curr << "': " << ut.what() << "\n"; std::cerr << " " << ut.pointer(str.size() + 1) << std::endl; } } int main(int argc, const char * argv[]) { std::string line; std::cout << "> "; evaluator eval(argc > 1 ? argv[1] : ""); while (std::getline(std::cin, line)) { eval(line); std::cout << "> "; } return 0; }