-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcalculator_flawed.cpp
151 lines (141 loc) · 3.09 KB
/
calculator_flawed.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <iostream>
#include <stdexcept>
#include <string>
// Token stuff
struct token
{
char kind; // what kind of token
double value; // for numbers: a value
// constructors
token(char ch)
: kind(ch)
, value(0)
{
}
token(char ch, double val)
: kind(ch)
, value(val)
{
}
};
token get() // read a token from the token_stream
{
// note that >> skips whitespace (space, newline, tab, etc.)
char ch;
std::cin >> ch;
switch (ch)
{
case '(':
case ')':
case ';':
case 'q':
case '+':
case '-':
case '*':
case '/':
return token(ch); // let each character represent itself
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
std::cin.putback(ch); // put digit back into the input stream
double val;
std::cin >> val; // read a floating-point number
return token('8', val); // let ‘8’ represent “a number”
}
default:
throw std::runtime_error("Bad token");
}
}
// declaration so that primary() can call expression()
double expression();
double primary() // Number or ‘(‘ Expression ‘)’
{
token t = get();
switch (t.kind)
{
case '(': // handle ‘(’expression ‘)’
{
double d = expression();
t = get();
if (t.kind != ')')
throw std::runtime_error("')' expected");
return d;
}
case '8': // we use ‘8’ to represent the “kind” of a number
return t.value; // return the number’s value
default:
throw std::runtime_error("primary expected");
}
}
// exactly like expression(), but for * and /
double term()
{
double left = primary(); // get the Primary
while (true)
{
token t = get(); // get the next Token ...
switch (t.kind)
{
case '*':
left *= primary();
break;
case '/':
{
double d = primary();
if (d == 0)
throw std::runtime_error("divide by zero");
left /= d;
break;
}
default:
return left; // return the value
}
}
}
// read and evaluate: 1 1+2.5 1+2+3.14 etc.
// return the sum (or difference)
double expression()
{
double left = term(); // get the Term
while (true)
{
token t = get(); // get the next token…
switch (t.kind) // ... and do the right thing with it
{
case '+':
left += term();
break;
case '-':
left -= term();
break;
default:
return left; // return the value of the expression
}
}
}
int main()
try
{
while (std::cin)
std::cout << "result: " << expression() << '\n';
return 0;
}
catch (std::runtime_error& e)
{
std::cerr << e.what() << std::endl;
return 1;
}
catch (...)
{
std::cerr << "exception \n";
return 2;
}