fork(1) download
  1. #include <string>
  2. #include <vector>
  3. #include <sstream>
  4. #include <cctype>
  5. #include <unordered_map>
  6. #include <iostream>
  7. #include <iomanip>
  8. #include <stdexcept>
  9.  
  10. struct token {
  11. std::string text;
  12. enum tok_type {type_none,
  13. type_integer,
  14. type_double,
  15. type_add,
  16. type_sub,
  17. type_mul,
  18. type_div,
  19. type_mod,
  20. type_oparen,
  21. type_cparen,
  22. type_string,
  23. } type;
  24. int line;
  25. int off;
  26. token(std::string te, tok_type ty, int l, int o)
  27. :text(te), type(ty), line(l), off(o)
  28. {}
  29. };
  30.  
  31. void error(const char* message, const token& found)
  32. {
  33. std::stringstream ss;
  34. ss << message;
  35. ss << " at line " << found.line << " character " << found.off;
  36. ss << " found \"" << found.text << "\".";
  37. throw std::runtime_error(ss.str());
  38. }
  39.  
  40. token get_next_token(std::istream& str, int& line, int& off) {
  41. int c = str.get();
  42. ++off;
  43. while(std::isspace(c)) {
  44. if (c=='\n') {++line; off=0;};
  45. c = str.get();
  46. ++off;
  47. }
  48. switch (c) {
  49. case EOF: return token("",token::type_none, line, off);
  50. case '+': return token("+",token::type_add, line, off);
  51. case '-': return token("-",token::type_sub, line, off);
  52. case '*': return token("*",token::type_mul, line, off);
  53. case '/': return token("/",token::type_div, line, off);
  54. case '%': return token("/",token::type_mod, line, off);
  55. case '(': return token("(",token::type_oparen, line, off);
  56. case ')': return token(")",token::type_cparen, line, off);
  57. case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
  58. {
  59. token t("",token::type_integer, line, off);
  60. t.text.push_back(char(c));
  61. int n = str.peek();
  62. while(n>='0' && n<='9') {
  63. n = str.get();
  64. ++off;
  65. t.text.push_back(char(n));
  66. n = str.peek();
  67. }
  68. if (n=='.') {
  69. t.type = token::type_double;
  70. n = str.get();
  71. ++off;
  72. t.text.push_back(char(n));
  73. n = str.peek();
  74. while(n>='0' && n<='9') {
  75. n = str.get();
  76. ++off;
  77. t.text.push_back(char(n));
  78. n = str.peek();
  79. }
  80. }
  81. return t;
  82. }
  83. default:
  84. token t("",token::type_string, line, off);
  85. t.text.push_back(char(c));
  86. if (!std::isalnum(c) && c!='_')
  87. error("invalid character", t);
  88. int n = str.peek();
  89. while(std::isalnum(n) || n=='_') {
  90. ++off;
  91. n = str.get();
  92. t.text.push_back(char(n));
  93. n = str.peek();
  94. }
  95. return t;
  96. }
  97. }
  98.  
  99. std::istream& operator>>(std::istream& str, std::vector<token>& r) {
  100. int line=0;
  101. int off=0;
  102. r.clear();
  103. do {
  104. r.push_back(get_next_token(str, line, off));
  105. } while(r.back().type);
  106. return str;
  107. }
  108.  
  109. typedef std::vector<token>::const_iterator token_iter;
  110. typedef std::unordered_map<std::string, double> variable_map;
  111. double do_term(token_iter& next, const variable_map& vars);
  112.  
  113. double do_value(token_iter& next, const variable_map& vars) {
  114. if (next->type==token::type_none) error("Expected value", *next);
  115. if (next->type == token::type_string) {
  116. auto it = vars.find(next->text);
  117. if (it == vars.end()) error("Unknown variable name", *next);
  118. ++next;
  119. return it->second;
  120. } else if(next->type == token::type_integer || next->type == token::type_double) {
  121. std::stringstream ss(next->text);
  122. double r;
  123. ss >> r;
  124. ++next;
  125. return r;
  126. } else if (next->type == token::type_oparen) {
  127. double r = do_term(++next, vars);
  128. if (next->type != token::type_cparen) error("expected closing param", *next);
  129. ++next;
  130. return r;
  131. } else error("Expected value", *next); return 0.0;
  132. }
  133.  
  134. double do_factor(token_iter& next, const variable_map& vars) {
  135. double lhs = do_value(next, vars);
  136. while(next->type == token::type_mul
  137. || next->type == token::type_div
  138. || next->type == token::type_mod)
  139. {
  140. token::tok_type op = next->type;
  141. double rhs = do_value(++next, vars);
  142. switch(op) {
  143. case token::type_mul:
  144. lhs *= rhs;
  145. break;
  146. case token::type_div:
  147. if (rhs == 0) error("division by zero", *next);
  148. lhs /= rhs;
  149. break;
  150. case token::type_mod:
  151. if (rhs == 0) error("modulo by zero", *next);
  152. lhs /= rhs;
  153. break;
  154. default: error("parser error", *next);
  155. }
  156. }
  157. return lhs;
  158. }
  159.  
  160. double do_term(token_iter& next, const variable_map& vars) {
  161. double lhs = do_factor(next, vars);
  162. while(next->type == token::type_add
  163. || next->type == token::type_sub)
  164. {
  165. token::tok_type op = next->type;
  166. double rhs = do_factor(++next, vars);
  167. switch(op) {
  168. case token::type_add: lhs += rhs; break;
  169. case token::type_sub: lhs -= rhs; break;
  170. default: error("parser error", *next);
  171. }
  172. }
  173. return lhs;
  174. }
  175.  
  176. int main() {
  177. try {
  178. variable_map vars;
  179. vars["ar"] = 3.14159;
  180. vars["var"] = -.5;
  181. std::vector<token> tokens;
  182. //std::cout << "goal:\n87635+23754*ar+ar*var*0.895+(ar-var)+ar*ar+var*var =162272.684176\n";
  183. //std::cout << "input:\n";
  184. std::cin >> tokens;
  185. if (tokens.empty())
  186. throw std::runtime_error("failed to read any tokens!");
  187. token_iter it = tokens.begin();
  188. double r = do_term(it, vars);
  189. if (it != tokens.end()-1)
  190. error("parser error", *it);
  191. std::cout << std::setprecision(14) << r;
  192. } catch(const std::exception& rhs) {
  193. std::cerr << rhs.what();
  194. }
  195. return 0;
  196. }
Success #stdin #stdout 0s 3036KB
stdin
87635+23754*ar+ar*var*0.895+(ar-var)+ar*ar+var*var
stdout
162272.6841762