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 | // Code derived from Stroustrup's PPP2 book
// § 6.5.4 Primary expressions
// -and beginning on p 203
/*------------------------------------------------------------------------------
Note: One of the goals behind the textbook's teaching for this section is to
use an incremental approach for the student's understanding of all the various
problems to be solved when creating a working calculator program.
-As such, some of the examples from Ch 6 are non-working if left as-is.
-This example is one of those.
-The actual definition of the function declaration:
get_token()
is being left till later on in the examples (so the build's linker step
will fail therefore). For now, these are just placeholders for the ideas.
A working example is already created for the classroom so you can look ahead.
------------------------------------------------------------------------------*/
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;
void error(const char* s) { throw runtime_error(s); }
class Token {
public:
Token(char ch) : kind{ch} {}
Token(char ch, double val) : kind{ch}, value{val} {}
char kind = '0';
double value = 0.0;
};
Token get_token(); // read a token from cin - (TBD!)
double expression(); // fwd-declaration so that primary() can call expression()
double primary()
{
Token t = get_token();
switch (t.kind) {
case '(': { // handle '(' expression ')'
double d = expression();
t = get_token();
if (t.kind != ')')
error("')' expected");
return d;
break;
}
case '8': // we use '8' to represent a number
return t.value; // return the number's value
break;
default:
error("primary expected");
// shouldn't reach here
return 0.0;
}
}
double term()
{
double left = primary();
Token t = get_token();
while (true) {
switch (t.kind) {
case '*': left *= primary(); break;
case '/': {
double d = primary();
if (d == 0)
error("divide by zero");
left /= d;
break;
}
default: return left;
}
t = get_token();
}
}
double expression()
{
double left = term();
Token t = get_token();
while (true) {
switch (t.kind) {
case '+': left += term(); break;
case '-': left -= term(); break;
default: return left;
}
t = get_token();
}
}
int main()
try {
expression();
} catch (exception& e) {
cerr << e.what() << '\n';
return 1;
} catch (...) {
cerr << "exception \n";
return 2;
}
|
build & run:
g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p203a.cpp && ./a.out