Advertisement
Korotkodul

calculator2

Sep 23rd, 2024 (edited)
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.41 KB | None | 0 0
  1. //
  2. // This is example of starting code from Chapter 7.8 "Variables" of
  3. // "Software - Principles and Practice using C++" by Bjarne Stroustrup
  4. //
  5.  
  6. #include <std_lib_facilities.h>
  7.  
  8. struct Token
  9. {
  10. char kind;
  11. double value;
  12. string name;
  13.  
  14. Token(char ch) : kind{ch}, value{0} {}
  15.  
  16. Token(char ch, double val) : kind{ch}, value{val} {}
  17.  
  18. Token(char ch, string id) : kind{ch}, name{id} {}
  19. };
  20.  
  21. class Token_stream
  22. {
  23. bool full{false};
  24. Token buffer{'\0'};
  25.  
  26. public:
  27. Token_stream() {}
  28.  
  29. Token get ();
  30. void putback (Token t);
  31.  
  32. void ignore (char);
  33. };
  34.  
  35. void Token_stream::putback(Token t)
  36. {
  37. if (full)
  38. error("putback() into a full buffer");
  39.  
  40. buffer = t;
  41. full = true;
  42. }
  43.  
  44. constexpr char quit = 'q';
  45. constexpr char print = ';';
  46. constexpr char number = '8';
  47. constexpr char name = 'a';
  48. constexpr char let = 'L';
  49.  
  50. const string prompt = "> ";
  51. const string result = "= ";
  52. const string declkey = "let";
  53. const string quitkey = "quit";
  54.  
  55. Token Token_stream::get()
  56. {
  57. if (full)
  58. {
  59. full = false;
  60. return buffer;
  61. }
  62.  
  63. char ch;
  64. cin >> ch;
  65.  
  66. switch (ch)
  67. {
  68. case '(':
  69. case ')':
  70. case '+':
  71. case '-':
  72. case '*':
  73. case '/':
  74. case '%':
  75. case print:
  76. case '=':
  77. return Token{ch};
  78.  
  79. case '.':
  80. case '0':
  81. case '1':
  82. case '2':
  83. case '3':
  84. case '4':
  85. case '5':
  86. case '6':
  87. case '7':
  88. case '8':
  89. case '9':
  90. {
  91. cin.putback(ch);
  92. double val;
  93. cin >> val;
  94. return Token{number, val};
  95. }
  96.  
  97. default:
  98. if (isalpha(ch))
  99. {
  100. string s;
  101. s += ch;
  102. while (cin.get(ch) && (isalpha(ch) || isdigit(ch)))
  103. s += ch;
  104. cin.putback(ch);
  105.  
  106. if (s == declkey)
  107. return Token{let};
  108.  
  109. if (s == quitkey)
  110. return Token{quit};
  111.  
  112. return Token{name, s};
  113. }
  114. error("bad token");
  115. }
  116. }
  117.  
  118. void Token_stream::ignore(char c)
  119. {
  120. if (full && c == buffer.kind)
  121. {
  122. full = false;
  123. return;
  124. }
  125. full = false;
  126.  
  127. for (char ch; cin >> ch;)
  128. {
  129. if (ch == c)
  130. return;
  131. }
  132. }
  133.  
  134. struct Variable
  135. {
  136. string name;
  137. double value;
  138.  
  139. Variable(string n, double v) : name{n}, value{v} {}
  140. };
  141.  
  142. vector<Variable> var_table;
  143.  
  144. double get_value (const string& s)
  145. {
  146. for (const auto& var : var_table)
  147. {
  148. if (var.name == s)
  149. return var.value;
  150. }
  151.  
  152. error("get: undefined name ", s);
  153. }
  154.  
  155. void set_value (const string& s, double d)
  156. {
  157. for (auto& var : var_table)
  158. {
  159. if (var.name == s)
  160. {
  161. var.value = d;
  162. return;
  163. }
  164. }
  165.  
  166. error("set: undefined name ", s);
  167. }
  168.  
  169. bool is_declared (const string& s)
  170. {
  171. for (const auto& var : var_table)
  172. {
  173. if (var.name == s)
  174. return true;
  175. }
  176.  
  177. return false;
  178. }
  179.  
  180. double define_name (const string& var, double val)
  181. {
  182. if (is_declared(var))
  183. error(var, " declared twice");
  184.  
  185. var_table.push_back(Variable{var, val});
  186.  
  187. return val;
  188. }
  189.  
  190. Token_stream ts;
  191.  
  192. double expression ();
  193.  
  194. double primary ()
  195. {
  196. Token t = ts.get();
  197. switch (t.kind)
  198. {
  199. case '(':
  200. {
  201. double d = expression();
  202. t = ts.get();
  203. if (t.kind != ')')
  204. error("'(' expected");
  205. return d;
  206. }
  207.  
  208. case '-':
  209. return -primary();
  210. case '+':
  211. return +primary();
  212.  
  213. case number:
  214. return t.value;
  215.  
  216. case name:
  217. return get_value(t.name);
  218.  
  219. default:
  220. error("primary expected");
  221. }
  222. }
  223.  
  224. double term ()
  225. {
  226. double left = primary();
  227.  
  228. while (true)
  229. {
  230. Token t = ts.get();
  231.  
  232. switch (t.kind)
  233. {
  234. case '*':
  235. left *= primary();
  236. break;
  237.  
  238. case '/':
  239. {
  240. double d = primary();
  241. if (d == 0)
  242. error("divide by zero");
  243. left /= d;
  244. break;
  245. }
  246.  
  247. case '%':
  248. {
  249. double d = primary();
  250. if (d == 0)
  251. error("'%': divide by zero");
  252. left = fmod(left, d);
  253. break;
  254. }
  255.  
  256. default:
  257. ts.putback(t);
  258. return left;
  259. }
  260. }
  261. }
  262.  
  263. double expression ()
  264. {
  265. double left = term();
  266.  
  267. while (true)
  268. {
  269. Token t = ts.get();
  270.  
  271. switch (t.kind)
  272. {
  273. case '+':
  274. left += term();
  275. break;
  276.  
  277. case '-':
  278. left -= term();
  279. break;
  280.  
  281. default:
  282. ts.putback(t);
  283. return left;
  284. }
  285. }
  286. }
  287.  
  288. double declaration ()
  289. {
  290. Token t = ts.get();
  291. if (t.kind != name)
  292. error("name expected in declaration");
  293.  
  294. string var = t.name;
  295. if (is_declared(var))
  296. error(var, " declared twice");
  297.  
  298. t = ts.get();
  299. if (t.kind != '=')
  300. error("'=' missing in declaration of ", var);
  301.  
  302. return define_name(var, expression());
  303. }
  304.  
  305. double statement ()
  306. {
  307. Token t = ts.get();
  308. switch (t.kind)
  309. {
  310. case let:
  311. return declaration();
  312. default:
  313. ts.putback(t);
  314. return expression();
  315. }
  316. }
  317.  
  318. void clean_up_mess () { ts.ignore(print); }
  319.  
  320. void calculate ()
  321. {
  322. while (true)
  323. try
  324. {
  325. cout << prompt;
  326. Token t = ts.get();
  327. while (t.kind == print)
  328. t = ts.get();
  329. if (t.kind == quit)
  330. return;
  331.  
  332. ts.putback(t);
  333. cout << result << statement() << endl;
  334. }
  335. catch (runtime_error& e)
  336. {
  337. cerr << e.what() << endl;
  338. clean_up_mess();
  339. }
  340. }
  341.  
  342. int main ()
  343. try
  344. {
  345. define_name("pi", 3.141592653589793);
  346. define_name("e", 2.718281828459045);
  347.  
  348. calculate();
  349. }
  350. catch (exception& e)
  351. {
  352. cerr << "exception: " << e.what() << endl;
  353. return 1;
  354. }
  355. catch (...)
  356. {
  357. cerr << "Oops, unknown exception" << endl;
  358. return 2;
  359. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement