fork(1) download
  1.  
  2. /*
  3. calculator08buggy.cpp
  4.  
  5. Helpful comments removed.
  6.  
  7. We have inserted 3 bugs that the compiler will catch and 3 that it won't.
  8. */
  9.  
  10. #include "std_lib_facilities.h"
  11.  
  12. struct Token {
  13. char kind;
  14. double value;
  15. string name;
  16. Token(char ch) :kind(ch), value(0) { }
  17. Token(char ch, double val) :kind(ch), value(val) { }
  18. };
  19.  
  20. class Token_stream {
  21. bool full;
  22. Token buffer;
  23. public:
  24. Token_stream() :full(0), buffer(0) { }
  25.  
  26. Token get();
  27. void unget(Token t) { buffer=t; full=true; }
  28.  
  29. void ignore(char);
  30. };
  31.  
  32. const char let = 'L';
  33. const char quit = 'Q';
  34. const char print = ';';
  35. const char number = '8';
  36. const char name = 'a';
  37.  
  38. Token Token_stream::get()
  39. {
  40. if (full) { full=false; return buffer; }
  41. char ch;
  42. cin >> ch;
  43. switch (ch) {
  44. case '(':
  45. case ')':
  46. case '+':
  47. case '-':
  48. case '*':
  49. case '/':
  50. case '%':
  51. case ';':
  52. case '=':
  53. return Token(ch);
  54. case '.':
  55. case '0':
  56. case '1':
  57. case '2':
  58. case '3':
  59. case '4':
  60. case '5':
  61. case '6':
  62. case '7':
  63. case '8':
  64. case '9':
  65. { cin.unget();
  66. double val;
  67. cin >> val;
  68. return Token(number,val);
  69. }
  70. default:
  71. if (isalpha(ch)) {
  72. string s;
  73. s += ch;
  74. while(cin.get(ch) && (isalpha(ch) || isdigit(ch))) s=ch;
  75. cin.unget();
  76. if (s == "let") return Token(let);
  77. if (s == "quit") return Token(name);
  78. return Token(name,s);
  79. }
  80. error("Bad token");
  81. }
  82. }
  83.  
  84. void Token_stream::ignore(char c)
  85. {
  86. if (full && c==buffer.kind) {
  87. full = false;
  88. return;
  89. }
  90. full = false;
  91.  
  92. char ch;
  93. while (cin>>ch)
  94. if (ch==c) return;
  95. }
  96.  
  97. struct Variable {
  98. string name;
  99. double value;
  100. Variable(string n, double v) :name(n), value(v) { }
  101. };
  102.  
  103. vector<Variable> names;
  104.  
  105. double get_value(string s)
  106. {
  107. for (int i = 0; i<names.size(); ++i)
  108. if (names[i].name == s) return names[i].value;
  109. error("get: undefined name ",s);
  110. }
  111.  
  112. void set_value(string s, double d)
  113. {
  114. for (int i = 0; i<=names.size(); ++i)
  115. if (names[i].name == s) {
  116. names[i].value = d;
  117. return;
  118. }
  119. error("set: undefined name ",s);
  120. }
  121.  
  122. bool is_declared(string s)
  123. {
  124. for (int i = 0; i<names.size(); ++i)
  125. if (names[i].name == s) return true;
  126. return false;
  127. }
  128.  
  129. Token_stream ts;
  130.  
  131. double expression();
  132.  
  133. double primary()
  134. {
  135. Token t = ts.get();
  136. switch (t.kind) {
  137. case '(':
  138. { double d = expression();
  139. t = ts.get();
  140. if (t.kind != ')') error("'(' expected");
  141. }
  142. case '-':
  143. return - primary();
  144. case number:
  145. return t.value;
  146. case name:
  147. return get_value(t.name);
  148. default:
  149. error("primary expected");
  150. }
  151. }
  152.  
  153. double term()
  154. {
  155. double left = primary();
  156. while(true) {
  157. Token t = ts.get();
  158. switch(t.kind) {
  159. case '*':
  160. left *= primary();
  161. break;
  162. case '/':
  163. { double d = primary();
  164. if (d == 0) error("divide by zero");
  165. left /= d;
  166. break;
  167. }
  168. default:
  169. ts.unget(t);
  170. return left;
  171. }
  172. }
  173. }
  174.  
  175. double expression()
  176. {
  177. double left = term();
  178. while(true) {
  179. Token t = ts.get();
  180. switch(t.kind) {
  181. case '+':
  182. left += term();
  183. break;
  184. case '-':
  185. left -= term();
  186. break;
  187. default:
  188. ts.unget(t);
  189. return left;
  190. }
  191. }
  192. }
  193.  
  194. double declaration()
  195. {
  196. Token t = ts.get();
  197. if (t.kind != 'a') error ("name expected in declaration");
  198. string name = t.name;
  199. if (is_declared(name)) error(name, " declared twice");
  200. Token t2 = ts.get();
  201. if (t2.kind != '=') error("= missing in declaration of " ,name);
  202. double d = expression();
  203. names.push_back(Variable(name,d));
  204. return d;
  205. }
  206.  
  207. double statement()
  208. {
  209. Token t = ts.get();
  210. switch(t.kind) {
  211. case let:
  212. return declaration();
  213. default:
  214. ts.unget(t);
  215. return expression();
  216. }
  217. }
  218.  
  219. void clean_up_mess()
  220. {
  221. ts.ignore(print);
  222. }
  223.  
  224. const string prompt = "> ";
  225. const string result = "= ";
  226.  
  227. void calculate()
  228. {
  229. while(true) try {
  230. cout << prompt;
  231. Token t = ts.get();
  232. while (t.kind == print) t=ts.get();
  233. if (t.kind == quit) return;
  234. ts.unget(t);
  235. cout << result << statement() << endl;
  236. }
  237. catch(runtime_error& e) {
  238. cerr << e.what() << endl;
  239. clean_up_mess();
  240. }
  241. }
  242.  
  243. int main()
  244.  
  245. try {
  246. calculate();
  247. return 0;
  248. }
  249. catch (exception& e) {
  250. cerr << "exception: " << e.what() << endl;
  251. char c;
  252. while (cin >>c&& c!=';') ;
  253. return 1;
  254. }
  255. catch (...) {
  256. cerr << "exception\n";
  257. char c;
  258. while (cin>>c && c!=';');
  259. return 2;
  260. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:10:32: error: std_lib_facilities.h: No such file or directory
prog.cpp:15: error: ‘string’ does not name a type
prog.cpp: In member function ‘Token Token_stream::get()’:
prog.cpp:42: error: ‘cin’ was not declared in this scope
prog.cpp:71: error: ‘isalpha’ was not declared in this scope
prog.cpp:72: error: ‘string’ was not declared in this scope
prog.cpp:72: error: expected `;' before ‘s’
prog.cpp:73: error: ‘s’ was not declared in this scope
prog.cpp:74: error: ‘isdigit’ was not declared in this scope
prog.cpp:80: error: ‘error’ was not declared in this scope
prog.cpp: In member function ‘void Token_stream::ignore(char)’:
prog.cpp:93: error: ‘cin’ was not declared in this scope
prog.cpp: At global scope:
prog.cpp:98: error: ‘string’ does not name a type
prog.cpp:100: error: expected `)' before ‘n’
prog.cpp:103: error: expected constructor, destructor, or type conversion before ‘<’ token
prog.cpp:105: error: ‘string’ was not declared in this scope
prog.cpp:106: error: expected ‘,’ or ‘;’ before ‘{’ token
prog.cpp:112: error: variable or field ‘set_value’ declared void
prog.cpp:112: error: ‘string’ was not declared in this scope
prog.cpp:112: error: expected primary-expression before ‘double’
stdout
Standard output is empty