main.cxx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //
  2. // main.cpp
  3. // stateful_dice
  4. //
  5. // Created by Sam Jaffe on 12/18/18.
  6. // Copyright © 2018 Sam Jaffe. All rights reserved.
  7. //
  8. #include "exception.h"
  9. #include "terminal_helper.h"
  10. #include <fstream>
  11. #include <iostream>
  12. #include <map>
  13. #include <regex>
  14. void usage() {
  15. std::cout << "'help' : Print this message\n";
  16. std::cout << "'A := Dice' : Create a substitution pattern\n";
  17. std::cout << "'1d6+$Dex' : Roll 1d6 plus whatever value subs for 'Dex'\n";
  18. }
  19. void print_binding(std::pair<const std::string, std::string> const & pair,
  20. std::ostream & os = std::cout) {
  21. os << pair.first;
  22. if (pair.second == "") os << " is not defined\n";
  23. else os << " := " << pair.second << "\n";
  24. }
  25. class evaluator {
  26. public:
  27. void operator()(std::string const & str);
  28. private:
  29. using binding_t = std::map<std::string, std::string>;
  30. bool regex_search(char const * regex) {
  31. return std::regex_match(curr, match, std::regex(regex));
  32. }
  33. binding_t::value_type find_or(std::string const & key) const {
  34. auto it = bindings.find(key);
  35. return it == bindings.cend() ? binding_t::value_type(key, "") : *it;
  36. }
  37. void save(std::string const & file) const {
  38. using namespace std::placeholders;
  39. std::ofstream out(file);
  40. std::for_each(bindings.begin(), bindings.end(),
  41. std::bind(&print_binding, _1, std::ref(out)));
  42. }
  43. void load(std::string const & file) {
  44. std::ifstream in(file);
  45. while (std::getline(in, curr)) {
  46. if (regex_search(R"(^(\w+)\s*:=\s*(.*)$)")) {
  47. bindings[match[1]] = match[2];
  48. }
  49. }
  50. }
  51. private:
  52. std::string curr;
  53. std::smatch match;
  54. binding_t bindings;
  55. };
  56. void evaluator::operator()(std::string const & str) {
  57. curr = str;
  58. try {
  59. if (regex_search(R"(help|\?)")) {
  60. usage();
  61. } else if (regex_search(R"(^(\w+)\s*:=\s*(.*)$)")) {
  62. bindings[match[1]] = match[2];
  63. } else if (regex_search(R"(^show (\*|all))")) {
  64. std::for_each(bindings.begin(), bindings.end(), &print_binding);
  65. } else if (regex_search(R"(^show (\w+))")) {
  66. print_binding(find_or(match[1]));
  67. } else if (regex_search(R"(^unset (\*|all))")) {
  68. bindings.clear();
  69. } else if (regex_search(R"(^unset (\w+))")) {
  70. bindings.erase(match[1]);
  71. } else if (regex_search(R"(^save (.+))")) {
  72. save(match[1]);
  73. } else if (regex_search(R"(^load new (.+))")) {
  74. bindings.clear();
  75. load(match[1]);
  76. } else if (regex_search(R"(^load (.+))")) {
  77. load(match[1]);
  78. } else {
  79. while (regex_search(R"(.*(\$\w+).*)")) {
  80. curr.replace(match[1].first, match[1].second,
  81. find_or(match[1].str().substr(1)).second);
  82. }
  83. terminal::process_dice_string(curr);
  84. }
  85. } catch (dice::unexpected_token const & ut) {
  86. terminal::print_error_message(curr, ut);
  87. }
  88. }
  89. int main(int, const char **) {
  90. std::string line;
  91. std::cout << "> ";
  92. evaluator eval;
  93. while (std::getline(std::cin, line)) {
  94. eval(line);
  95. std::cout << "> ";
  96. }
  97. return 0;
  98. }