|
|
@@ -9,19 +9,99 @@
|
|
|
#include "exception.h"
|
|
|
#include "terminal_helper.h"
|
|
|
|
|
|
+#include <fstream>
|
|
|
#include <iostream>
|
|
|
+#include <map>
|
|
|
+#include <regex>
|
|
|
|
|
|
-void eval(std::string const & str) {
|
|
|
+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(std::pair<const std::string, std::string> const & pair,
|
|
|
+ std::ostream & os = std::cout) {
|
|
|
+ os << pair.first;
|
|
|
+ if (pair.second == "") os << " is not defined\n";
|
|
|
+ else os << " := " << pair.second << "\n";
|
|
|
+}
|
|
|
+
|
|
|
+class evaluator {
|
|
|
+public:
|
|
|
+ void operator()(std::string const & str);
|
|
|
+
|
|
|
+private:
|
|
|
+ using binding_t = std::map<std::string, std::string>;
|
|
|
+
|
|
|
+ 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, _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 {
|
|
|
- terminal::process_dice_string(str);
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ terminal::process_dice_string(curr);
|
|
|
+ }
|
|
|
} catch (dice::unexpected_token const & ut) {
|
|
|
- terminal::print_error_message(str, ut);
|
|
|
+ terminal::print_error_message(curr, ut);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
int main(int, const char **) {
|
|
|
std::string line;
|
|
|
std::cout << "> ";
|
|
|
+ evaluator eval;
|
|
|
while (std::getline(std::cin, line)) {
|
|
|
eval(line);
|
|
|
std::cout << "> ";
|