Advertisement
Korotkodul

B.cpp

Sep 30th, 2024
10
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.33 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. #include "token.h"
  8. #include "variable.h"
  9.  
  10.  
  11. struct Token
  12. {
  13. char kind;
  14. double value;
  15. string name;
  16.  
  17. Token(char ch) : kind{ch}, value{0} {}
  18.  
  19. Token(char ch, double val) : kind{ch}, value{val} {}
  20.  
  21. Token(char ch, string id) : kind{ch}, name{id} {}
  22. };
  23.  
  24. class Token_stream
  25. {
  26. bool full{false};
  27. Token buffer{'\0'};
  28. istream& in;
  29.  
  30. public:
  31. Token_stream() : in{cin} {}
  32. Token_stream(istream& s) : in{ s } {}
  33.  
  34. Token get ();
  35. void putback (Token t);
  36.  
  37. void ignore (char);
  38.  
  39. };
  40.  
  41.  
  42. constexpr char quit = 'q';
  43. constexpr char print = ';';
  44. constexpr char number = '8';
  45. constexpr char name = 'a';
  46. constexpr char let = 'L';
  47.  
  48. const string prompt = "> ";
  49. const string result = "= ";
  50. const string declkey = "let";
  51. const string quitkey = "quit";
  52.  
  53.  
  54.  
  55.  
  56.  
  57. double get_value (const string& s)
  58. {
  59. for (const auto& var : var_table)
  60. {
  61. if (var.name == s)
  62. return var.value;
  63. }
  64.  
  65. error("get: undefined name ", s);
  66. }
  67.  
  68. void set_value (const string& s, double d)
  69. {
  70. for (auto& var : var_table)
  71. {
  72. if (var.name == s)
  73. {
  74. var.value = d;
  75. return;
  76. }
  77. }
  78.  
  79. error("set: undefined name ", s);
  80. }
  81.  
  82. bool is_declared (const string& s)
  83. {
  84. for (const auto& var : var_table)
  85. {
  86. if (var.name == s)
  87. return true;
  88. }
  89.  
  90. return false;
  91. }
  92.  
  93. double define_name (const string& var, double val)
  94. {
  95. if (is_declared(var))
  96. error(var, " declared twice");
  97.  
  98. var_table.push_back(Variable{var, val});
  99.  
  100. return val;
  101. }
  102.  
  103.  
  104. double expression (Token_stream& ts);
  105.  
  106. double primary (Token_stream& ts)
  107. {
  108. Token t = ts.get();
  109. switch (t.kind)
  110. {
  111. case '(':
  112. {
  113. double d = expression(ts);
  114. t = ts.get();
  115. if (t.kind != ')')
  116. error("'(' expected");
  117. return d;
  118. }
  119.  
  120. case '-':
  121. return -primary(ts);
  122. case '+':
  123. return +primary(ts);
  124.  
  125. case number:
  126. return t.value;
  127.  
  128. case name:
  129. return get_value(t.name);
  130.  
  131. default:
  132. error("primary expected");
  133. }
  134. }
  135.  
  136. double term (Token_stream& ts)
  137. {
  138. double left = primary(ts);
  139.  
  140. while (true)
  141. {
  142. Token t = ts.get();
  143.  
  144. switch (t.kind)
  145. {
  146. case '*':
  147. left *= primary(ts);
  148. break;
  149.  
  150. case '/':
  151. {
  152. double d = primary(ts);
  153. if (d == 0)
  154. error("divide by zero");
  155. left /= d;
  156. break;
  157. }
  158.  
  159. case '%':
  160. {
  161. double d = primary(ts);
  162. if (d == 0)
  163. error("'%': divide by zero");
  164. left = fmod(left, d);
  165. break;
  166. }
  167.  
  168. default:
  169. ts.putback(t);
  170. return left;
  171. }
  172. }
  173. }
  174.  
  175. double expression (Token_stream& ts)
  176. {
  177. double left = term(ts);
  178.  
  179. while (true)
  180. {
  181. Token t = ts.get();
  182.  
  183. switch (t.kind)
  184. {
  185. case '+':
  186. left += term(ts);
  187. break;
  188.  
  189. case '-':
  190. left -= term(ts);
  191. break;
  192.  
  193. default:
  194. ts.putback(t);
  195. return left;
  196. }
  197. }
  198. }
  199.  
  200. double declaration (Token_stream& ts)
  201. {
  202. Token t = ts.get();
  203. if (t.kind != name)
  204. error("name expected in declaration");
  205.  
  206. string var = t.name;
  207. if (is_declared(var))
  208. error(var, " declared twice");
  209.  
  210. t = ts.get();
  211. if (t.kind != '=')
  212. error("'=' missing in declaration of ", var);
  213.  
  214. return define_name(var, expression(ts));
  215. }
  216.  
  217. double statement (Token_stream& ts)
  218. {
  219. Token t = ts.get();
  220. switch (t.kind)
  221. {
  222. case let:
  223. return declaration(ts);
  224. default:
  225. ts.putback(t);
  226. return expression(ts);
  227. }
  228. }
  229.  
  230. void clean_up_mess (Token_stream& ts) { ts.ignore(print); }
  231.  
  232. void calculate ()
  233. {
  234. Token_stream ts;
  235. while (true)
  236. try
  237. {
  238. cout << prompt;
  239. Token t = ts.get();
  240. while (t.kind == print)
  241. t = ts.get();
  242. if (t.kind == quit)
  243. return;
  244.  
  245. ts.putback(t);
  246. cout << result << statement(ts) << endl;
  247. }
  248. catch (runtime_error& e)
  249. {
  250. cerr << e.what() << endl;
  251. clean_up_mess(ts);
  252. }
  253. }
  254.  
  255. int main ()
  256. try
  257. {
  258. define_name("pi", 3.141592653589793);
  259. define_name("e", 2.718281828459045);
  260.  
  261. calculate();
  262. }
  263. catch (exception& e)
  264. {
  265. cerr << "exception: " << e.what() << endl;
  266. return 1;
  267. }
  268. catch (...)
  269. {
  270. cerr << "Oops, unknown exception" << endl;
  271. return 2;
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement