Advertisement
575

Untitled

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