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 | // Code derived from Stroustrup's PPP2 book
// § 6.8.3 Reading numbers
// -and beginning on p 214
#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;
};
//------------------------------------------------------------------------------
class Token_stream {
public:
Token_stream(); // make a Token_stream that reads from cin
Token get(); // get a Token
void putback(Token t); // put a Token back
private:
bool full; // is there a Token in the buffer?
Token buffer; // here is where we keep a Token put back using putback()
};
//------------------------------------------------------------------------------
Token_stream::Token_stream() : full{false}, buffer{0} // no Token in buffer
{
}
//------------------------------------------------------------------------------
// read a token from cin
Token Token_stream::get()
{
if (full) { // check if we already have a Token ready
full = false;
return buffer;
}
char ch;
cin >> ch;
// clang-format off
switch (ch) {
case ';':
case 'q':
case '(': case ')': case '+': case '-': case '*': case '/':
return Token{ch};
break;
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
cin.putback(ch); // put digit back into the input stream
double val;
cin >> val; // read a floating-point number
return Token{'8', val}; // let '8' represent "a number"
break;
}
default:
error("Bad token");
return Token{'K'}; // invalid, shouldn't reach here
}
// clang-format on
}
//------------------------------------------------------------------------------
void Token_stream::putback(Token t)
{
if (full)
error("putback() into a full buffer");
buffer = t; // copy t to buffer
full = true; // buffer is now full
}
//------------------------------------------------------------------------------
int main()
try {
Token_stream ts;
Token t{')'};
ts.putback(t);
Token u = ts.get();
if (u.kind != t.kind || u.value != t.value)
error("Error in token stream logic");
} 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_p214.cpp && ./a.out