week days 2.0

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 11.1
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 11.1

#include "std_lib_facilities.h"

vector<string> dayName;
vector<int> dayVal(7, 0);

void init_dayName() {
	dayName = { "Monday", "monday", "Mon",
		"Tuesday", "tuesday", "Tue",
		"Wednesday", "wednesday", "Wed",
		"Thursday", "thursday", "Thu",
		"Friday", "friday", "Fri",
		"Saturday", "saturday", "Sat",
		"Sunday", "sunday", "Sun" };
}

void calculate() {
	string day;
	int value;
	string falsevalue;
	bool check = true;

	cout << "Enter pairs of week-days and values seperated by blank space or exit "
		 << "and 0 to end entry: \n";

	while (check) {
		if (cin >> day >> value) {
			for (int i = 0; i < dayName.size(); i++) {
				if (day == dayName[i]) {
					dayVal[i / 3] += value;
				}
			}
			if (day == "exit" && value == 0) {
				check = false;
			}
		}
		else {
			cin.clear();
			cin >> falsevalue;
			error("Entered value illegal: ", falsevalue);
		}
	}

	for (int i = 0; i < dayVal.size(); i++) {
		cout << dayName[i * 3] << ": " << dayVal[i] << "\n";
	}
}


int main()
try
{
	init_dayName();
	calculate();
	keep_window_open(".");
}

catch (runtime_error e) {
	cout << e.what() << "\n";
	keep_window_open(".");
}
catch (...) {
	cout << "Extiting" << "\n";
	keep_window_open(".");
}
Output:
Enter pairs of week-days and values seperated by blank space or exitand 0 to end entry:
Monday 10
Tuesday 30
Friday 60
exit 0
Monday: 10
Tuesday: 30
Wednesday: 0
Thursday: 0
Friday: 60
Saturday: 0
Sunday: 0
Please enter . to exit

name age pairs 2.0

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 11.0
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 11.0

#include "std_lib_facilities.h"

vector<string> names;
string nameTemp;
vector<int> ages;
int ageTemp;
int ageInput;
int ageCheck = 0;
bool check = true;

void getNameVals() {
	while (check == true) {
		if (cin >> nameTemp >> ageTemp) {
			if (nameTemp == "noname" && ageTemp == 0) {
				check = false;
			}
			else {
				for (int i = 0; i < names.size(); i++) {
					if (names[i] == nameTemp) {
						error("This name already exists ", nameTemp);
					}
				}
				names.push_back(nameTemp);
				ages.push_back(ageTemp);
			}
		}
		else {
			error("Bad input");
		}
	}
}

void searchInt() {
	cout << "Enter an integer to look for\n";
	while (cin >> ageInput) {
		for (int i = 0; i < ages.size(); i++) {
			if (ages[i] == ageInput) {
				cout << "You entered: " << ageInput << ". Corresponding name is " << names[i] << "\n";
				ageCheck++;
				break;
			}
		}
		if (ageCheck == 0) {
			cout << ageInput << " . Could not be found in the list of ages.\n";
		}
		check = true;
	}
}

void calculate() {
	while (cin) {
		cin.clear();
		cout << "Enter name and age pairs to be collected, or 'noname' and '0' to end the entry.\n";
		getNameVals();
		searchInt();
	}

}

int main()
try
{
	calculate();
	keep_window_open(".");
}

catch (runtime_error e) {
	cout << e.what() << "\n";
	keep_window_open(".");
}
catch (...) {
	cout << "Exiting \n";
	keep_window_open(".");
}
Output:
Enter name and age pairs to be collected, or 'noname' and '0' to end the entry.
alfred 60
philipp 28
benjamin 25
isabell 31
noname 0
Enter an integer to look for
5
5 . Could not be found in the list of ages.
60
You entered: 60. Corresponding name is alfred

calculator 4.1 [integers only]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 10
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 10

#include "std_lib_facilities.h"

const char let = '#';
const char quitProg = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';
const char help = 'H';

struct Token {
	char kind;
	int value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, int val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get()
{
	if (full) {
		full = false; return buffer;
	}
	char ch;
	cin.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		cin.get(ch);
	}

	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		cin.unget();
		double val;
		cin >> val;
		int valInt = narrow_cast<double>(val);
		return Token(number, valInt);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch;
			}
			cin.unget(); //puts the most recently read character back into the stream
			if (s == "quit") return Token(quitProg);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			if (s == "help" || s == "Help") return Token(help);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' ');
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	int value;
	bool immutable;
	Variable(string n, int v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	int get(string);
	void set(string, int);
	bool is_declared(string);
	int declare(char);
	bool is_immutable(string);
};

Token_stream ts;
int expression();
int primary();

int Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0;
}

void Symbol_table::set(string s, int d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

int Symbol_table::declare(char kind)
{
	Token t = ts.get();
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	int d = expression();
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

int pow_function(Token _t) {
	_t = ts.get();
	if (_t.kind != '(') {
		error("'(' expected");
	}

	int x = expression();

	_t = ts.get();
	if (_t.kind != ',') {
		error("',' expected");
	}

	int n = expression();
	_t = ts.get();
	if (_t.kind == ')') {
		return pow(x, n);
	}
	else {
		error("Expected ')'");
	}
}

int sqrt_function(Token _t) {
	_t = ts.get();
	if (_t.kind != '(') {
		error("'(' expected");
	}
	ts.unget(_t);
	int d = primary();
	if (d < 0.0) {
		error("negative square root");
	}
	return sqrt(d);
}


Symbol_table st;

int primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		int d = expression();
		t = ts.get();
		if (t.kind != ')') error("')' expected");
		return d;
	}
	case '-':
	{
		return -primary();
	}
	case '+':
	{
		return primary();
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		return sqrt_function(t);
	}
	case power:
	{
		return pow_function(t);
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0;
	}
	}
}

int term()
{
	int left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary();
			break;
		}
		case '/':
		{
			int d = primary();
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		case '%':
		{
			int i1 = narrow_cast<double>(left);
			int i2 = narrow_cast<double>(primary());
			if (i2 == 0) error("%: divide by zero");
			left = i1%i2;
			break;
		}
		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

int expression()
{
	int left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left += term();
			break;
		}
		case '-':
		{
			left -= term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

int statement()
{
	Token t = ts.get();
	int d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}

	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	cout << "Welcome to my calculator.\n"
		<< "Just hit enter or ; at the end of your function to calculate.\n"
		<< "Enter help or Help for help or quit to exit the program.\n";
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == help) {
			cout << "You can use / *-+operators.\n"
				<< "Declaring variables using #, for example: # x = 5.\n";
		}
		else {
			if (t.kind == quitProg) {
				return;
			}
			ts.unget(t);
			cout << result << statement() << endl;
		}
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()

try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}
Output:
Welcome to my calculator.
Just hit enter or ; at the end of your function to calculate.
Enter help or Help for help or quit to exit the program.
> 8.5 + 4
= 12
>

calculator 4.0 [improved]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 9
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 9

#include "std_lib_facilities.h"

const char let = '#';
const char quitProg = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';
const char help = 'H';

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get()
{
	if (full) {
		full = false; return buffer;
	}
	char ch;
	cin.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		cin.get(ch);
	}

	switch (ch) {
		case '(':
		case ')':
		case '+':
		case '-':
		case '*':
		case '/':
		case '%':
		case ';':
		case '=':
		case 'k':
		case ',':
		{
			return Token(ch);
		}
		case '#':
		{
			return Token(let);
		}
		case '.':
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		{
			cin.unget();
			double val;
			cin >> val;
			return Token(number, val);
		}
		default:
		{
			if (isalpha(ch) || ch == '_') { //is ch a letter?
				string s;
				s += ch;
				while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
					s += ch;
				}
				cin.unget(); //puts the most recently read character back into the stream
				if (s == "quit") return Token(quitProg);
				if (s == "sqrt") return Token(sqroot);
				if (s == "pow") return Token(power);
				if (s == "const") return Token(constant);
				if (s == "reset") return Token(reset);
				if (s == "help" || s == "Help") return Token(help);
				return Token(name, s);
			}
			error("Bad token");
			return Token(' ');
		}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	double get(string);
	void set(string, double);
	bool is_declared(string);
	double declare(char);
	bool is_immutable(string);
};

Token_stream ts;
double expression();
double primary();

double Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0;
}

void Symbol_table::set(string s, double d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

double Symbol_table::declare(char kind)
{
	Token t = ts.get();
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression();
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

double pow_function(Token _t) {
	_t = ts.get();
	if (_t.kind != '(') {
		error("'(' expected");
	}

	double x = expression();

	_t = ts.get();
	if (_t.kind != ',') {
		error("',' expected");
	}

	double n = expression();
	_t = ts.get();
	if (_t.kind == ')') {
		return pow(x, n);
	}
	else {
		error("Expected ')'");
	}
}

double sqrt_function(Token _t) {
	_t = ts.get();
	if (_t.kind != '(') {
		error("'(' expected");
	}
	ts.unget(_t);
	double d = primary();
	if (d < 0.0) {
		error("negative square root");
	}
	return sqrt(d);
}


Symbol_table st;

double primary()
{
	Token t = ts.get();
	switch (t.kind) {
		case '(':
		{
			double d = expression();
			t = ts.get();
			if (t.kind != ')') error("')' expected");
			return d;
		}
		case '-':
		{
			return -primary();
		}
		case '+':
		{
			return primary();
		}
		case number:
		{
			return t.value;
		}
		case sqroot:
		{
			return sqrt_function(t);
		}
		case power:
		{
			return pow_function(t);
		}
		case name:
		{
			return st.get(t.name);
		}
		default:
		{
			error("primary expected");
			return 0.0;
		}
	}
}

double term()
{
	double left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary();
			break;
		}
		case '/':
		{
			double d = primary();
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		case '%':
		{
			int i1 = narrow_cast<int>(left);
			int i2 = narrow_cast<int>(primary());
			if (i2 == 0) error("%: divide by zero");
			left = i1%i2;
			break;
			/*
			double d = primary();
			if(d == 0) error("%: divide by zero");
			left = fmod(left,d);
			break;
			*/
		}

		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression()
{
	double left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left += term();
			break;
		}
		case '-':
		{
			left -= term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double statement()
{
	Token t = ts.get();
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}

	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	cout << "Welcome to my calculator.\n"
		<< "Just hit enter or ; at the end of your function to calculate.\n"
		<< "Enter help or Help for help or quit to exit the program.\n";
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == help) {
			cout << "You can use / *-+operators.\n"
				<< "Declaring variables using #, for example: # x = 5.\n";
		}
		else {
			if (t.kind == quitProg) {
				return;
			}
			ts.unget(t);
			cout << result << statement() << endl;
		}
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()

try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}

calculator grammar

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 8
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 8

/*
	Simple calculator

	Revision history:
		
		Revised by Philipp Siedler May 2017
		Revised by Bjarne Stroustrup November 2013
		Revised by Bjarne Stroustrup May 2007
		Revised by Bjarne Stroustrup August 2006
		Revised by Bjarne Stroustrup August 2004
		Originally written by Bjarne Stroustrup
			(bs@cs.tamu.edu) Spring 2004

	This program implements a basic expression calculator.
	Input from cin; output to cout;
	The grammar for input is:
	
	Calculation:
		Statement
		Print
		Quit
		Help
		Calculation Statement

	Statement:
		Declaration
		Expression
	
	Declaration:
		"let" Name "=" Expression
		"const" name "=" Expression

	Name:
		letter
		letter Sequence
		Sequence:
		letter
		digit
		"_"
		letter Sequence
		digit Sequence
		"_" Sequence

	Print:
		";" or '\n'
	
	Quit:
		"quit"
	
	Help
		"help" or "Help"

	Expression:
		Term
		Expression + Term
		Expression - Term

	Term:
		Primary
		Term * Primary
		Term / Primary
		Term % Primary

	Primary:
		Number
		"(" Expression ")"
		"-" Primary
		"+" Primary
		"sqrt(" Expression ")"
		"pow(" Expression "," Integer ")"
		Name
		Name "=" Expression
	
	Number:
		floating-point-literal

	Input comes from cin through the Token_stream called ts.
*/

calculator 3.6 [adding quit]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 7
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 7

#include "std_lib_facilities.h"

const char let = '#';
const char quitProg = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';
const char help = 'H';

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get()
{
	if (full) {
		full = false; return buffer;
	}
	char ch;
	cin.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		cin.get(ch);
	}

	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		cin.unget();
		double val;
		cin >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch; //Error 2: s = ch;
			}
			cin.unget(); //puts the most recently read character back into the stream
			if (s == "quit") return Token(quitProg); //Error 2: if (s == "quit") return Token(name);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			if (s == "help" || s == "Help") return Token(help);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' '); //Line missing
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	double get(string);
	void set(string, double);
	bool is_declared(string);
	double declare(char);
	bool is_immutable(string);
};

Token_stream ts;
double expression();

double Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0; //Line missing
}

void Symbol_table::set(string s, double d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

double Symbol_table::declare(char kind)
{
	Token t = ts.get();
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression();
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

Symbol_table st;

double primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		double d = expression();
		t = ts.get();
		if (t.kind != ')') error("')' expected"); //Error 3: if (t.kind != ')') error("'(' expected");
		return d; //Line missing
	}
	case '-':
	{
		return -primary();
	}
	case '+':
	{
		return primary();
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}
		ts.unget(t);
		double d = primary();
		if (d < 0.0) {
			error("negative square root");
		}
		return sqrt(d);
	}
	case power:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}

		double x = expression();

		t = ts.get();
		if (t.kind != ',') {
			error("',' expected");
		}

		int n = int(expression());

		if (n != expression()) {
			error("entry for n in pow(x,n) is no integer", expression());
		}

		t = ts.get();
		if (t.kind == ')') {
			cout << n << ", " << x << "\n";
			return pow(x, n);
		}
		else {
			error("Expected ')'");
		}
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0; //Line missing
	}
	}
}

double term()
{
	double left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary();
			break;
		}
		case '/':
		{
			double d = primary();
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression()
{
	double left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left += term();
			break;
		}
		case '-':
		{
			left -= term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double statement()
{
	Token t = ts.get();
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}

	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	cout << "Welcome to my calculator.\n"
		<< "Just hit enter or ; at the end of your function to calculate.\n"
		<< "Enter help or Help for help or quit to exit the program.\n";
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == help) {
			cout << "You can use / *-+operators.\n"
				<< "Declaring variables using #, for example: # x = 5.\n";
		}
		else {
			if (t.kind == quitProg) {
				return;
			}
			ts.unget(t);
			cout << result << statement() << endl;
		}
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()

try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}
Output:
Welcome to my calculator.
Just hit enter or ; at the end of your function to calculate.
Enter help or Help for help or quit to exit the program.
> 2 + 7
= 9
> Help
You can use / *-+operators.
Declaring variables using #, for example: # x = 5.
> quit

calculator 3.5 [adding help]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 6
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 6

#include "std_lib_facilities.h"

const char let = '#';
const char exitprog = 'E';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';
const char help = 'H';

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get()
{
	if (full) {
		full = false; return buffer;
	}
	char ch;
	cin.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		cin.get(ch);
	}

	switch (ch) {
	case 'h':
	case 'H':
	{
		return Token(help);
	}
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		cin.unget();
		double val;
		cin >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch; //Error 2: s = ch;
			}
			cin.unget(); //puts the most recently read character back into the stream
			if (s == "exit") return Token(exitprog); //Error 2: if (s == "quit") return Token(name);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' '); //Line missing
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	double get(string);
	void set(string, double);
	bool is_declared(string);
	double declare(char);
	bool is_immutable(string);
};

Token_stream ts;
double expression();

double Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0; //Line missing
}

void Symbol_table::set(string s, double d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

double Symbol_table::declare(char kind)
{
	Token t = ts.get();
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression();
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

Symbol_table st;

double primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		double d = expression();
		t = ts.get();
		if (t.kind != ')') error("')' expected"); //Error 3: if (t.kind != ')') error("'(' expected");
		return d; //Line missing
	}
	case '-':
	{
		return -primary();
	}
	case '+':
	{
		return primary();
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}
		ts.unget(t);
		double d = primary();
		if (d < 0.0) {
			error("negative square root");
		}
		return sqrt(d);
	}
	case power:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}

		double x = expression();

		t = ts.get();
		if (t.kind != ',') {
			error("',' expected");
		}

		int n = int(expression());

		if (n != expression()) {
			error("entry for n in pow(x,n) is no integer", expression());
		}

		t = ts.get();
		if (t.kind == ')') {
			cout << n << ", " << x << "\n";
			return pow(x, n);
		}
		else {
			error("Expected ')'");
		}
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0; //Line missing
	}
	}
}

double term()
{
	double left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary();
			break;
		}
		case '/':
		{
			double d = primary();
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression()
{
	double left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left += term();
			break;
		}
		case '-':
		{
			left -= term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double statement()
{
	Token t = ts.get();
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}

	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	cout << "Welcome to my calculator.\n"
		<< "Just hit enter or ; at the end of your function to calculate.\n"
		<< "Enter h or H for help.\n";
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == help) {
			cout << "You can use / *-+operators.\n"
				<< "Declaring variables using #, for example: # x = 5.\n";
		}
		else {
			if (t.kind == exitprog) {
				return;
			}
			ts.unget(t);
			cout << result << statement() << endl;
		}
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()

try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}
Output:
Welcome to my calculator.
Just hit enter or ; at the end of your function to calculate.
Enter h or H for help.
> 2 + 5
= 7
> H
You can use / *-+operators.
Declaring variables using #, for example: # x = 5.

calculator 3.4 [print token]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 5
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 5

#include "std_lib_facilities.h"

const char let = '#';
const char exitprog = 'E';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get()
{
	if (full) {
		full = false; return buffer;
	}
	char ch;
	cin.get(ch);

	while (isspace(ch)) {
		if (ch == '\n') return Token(print); // if newline detected, return print Token
		cin.get(ch);
	}

	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		cin.unget();
		double val;
		cin >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch; //Error 2: s = ch;
			}
			cin.unget(); //puts the most recently read character back into the stream
			if (s == "exit") return Token(exitprog); //Error 2: if (s == "quit") return Token(name);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' '); //Line missing
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	double get(string);
	void set(string, double);
	bool is_declared(string);
	double declare(char);
	bool is_immutable(string);
};

Token_stream ts;
double expression();

double Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0; //Line missing
}

void Symbol_table::set(string s, double d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

double Symbol_table::declare(char kind)
{
	Token t = ts.get();
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression();
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

Symbol_table st;

double primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		double d = expression();
		t = ts.get();
		if (t.kind != ')') error("')' expected"); //Error 3: if (t.kind != ')') error("'(' expected");
		return d; //Line missing
	}
	case '-':
	{
		return -primary();
	}
	case '+':
	{
		return primary();
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}
		ts.unget(t);
		double d = primary();
		if (d < 0.0) {
			error("negative square root");
		}
		return sqrt(d);
	}
	case power:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}

		double x = expression();

		t = ts.get();
		if (t.kind != ',') {
			error("',' expected");
		}

		int n = int(expression());
		t = ts.get();
		if (t.kind == ')') {
			return pow(x, n);
		}
		else {
			error("Expected ')'");
		}
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0; //Line missing
	}
	}
}

double term()
{
	double left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary();
			break;
		}
		case '/':
		{
			double d = primary();
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression()
{
	double left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left += term();
			break;
		}
		case '-':
		{
			left -= term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double statement()
{
	Token t = ts.get();
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}
	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == exitprog) {
			return;
		}
		ts.unget(t);
		cout << result << statement() << endl;
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()

try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}
Output:
> 5 + 2
= 7
>

calculator 3.3 [symbol table class]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 4
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 4

#include "std_lib_facilities.h"

const char let = '#';
const char exitprog = 'E';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

Token Token_stream::get()
{
	if (full) {
		full = false; return buffer;
	}
	char ch;
	cin >> ch;
	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		cin.unget();
		double val;
		cin >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch; //Error 2: s = ch;
			}
			cin.unget(); //puts the most recently read character back into the stream
			if (s == "exit") return Token(exitprog); //Error 2: if (s == "quit") return Token(name);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' '); //Line missing
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
	vector<Variable> var_table;
	double get(string);
	void set(string, double);
	bool is_declared(string);
	double declare(char);
	bool is_immutable(string);
};

Token_stream ts;
double expression();

double Symbol_table::get(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) {
			return var_table[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0; //Line missing
}

void Symbol_table::set(string s, double d)
{
	for (int i = 0; i <= var_table.size(); ++i) {
		if (var_table[i].name == s) {
			var_table[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
	for (int i = 0; i < var_table.size(); ++i) {
		if (var_table[i].name == s) return true;
	}
	return false;
}

double Symbol_table::declare(char kind)
{
	Token t = ts.get();
	if (t.kind != name) {
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression();
	if (is_declared(name))
		set(name, d);
	else
		var_table.push_back(Variable(name, d, (kind == constant)));
	return d;
}

bool Symbol_table::is_immutable(string s)
{
	for (int i = 0; i<int(var_table.size()); ++i)
		if (var_table[i].name == s && var_table[i].immutable) return true;
	return false;
}

Symbol_table st;

double primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		double d = expression();
		t = ts.get();
		if (t.kind != ')') error("')' expected"); //Error 3: if (t.kind != ')') error("'(' expected");
		return d; //Line missing
	}
	case '-':
	{
		return -primary();
	}
	case '+':
	{
		return primary();
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}
		ts.unget(t);
		double d = primary();
		if (d < 0.0) {
			error("negative square root");
		}
		return sqrt(d);
	}
	case power:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}

		double x = expression();

		t = ts.get();
		if (t.kind != ',') {
			error("',' expected");
		}

		int n = int(expression());

		t = ts.get();
		if (t.kind == ')') {
			return pow(x, n);
		}
		else {
			error("Expected ')'");
		}
	}
	case name:
	{
		return st.get(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0; //Line missing
	}
	}
}

double term()
{
	double left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary();
			break;
		}
		case '/':
		{
			double d = primary();
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression()
{
	double left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left += term();
			break;
		}
		case '-':
		{
			left -= term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double statement()
{
	Token t = ts.get();
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = st.declare(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}
	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == exitprog) {
			return;
		}
		ts.unget(t);
		cout << result << statement() << endl;
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()

try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}

calculator 3.2 [adding constants]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 7 Exercise 3
Using std_lib_facilities.h by Bjarne Stroustrup.

//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 7 Exercise 3

#include "std_lib_facilities.h"

struct Token {
	char kind;
	double value;
	string name;
	Token(char ch) :kind(ch), value(0) { }
	Token(char ch, double val) :kind(ch), value(val) { }
	Token(char ch, string val) :kind(ch), name(val) { } //Error 1: Line missing
};

class Token_stream {
	bool full;
	Token buffer;
public:
	Token_stream() :full(0), buffer(0) { }
	Token get();
	void unget(Token t) { buffer = t; full = true; }
	void ignore(char);
};

const char let = '#';
const char exitprog = 'E';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';

Token Token_stream::get()
{
	if (full) {
		full = false; return buffer;
	}
	char ch;
	cin >> ch;
	switch (ch) {
	case '(':
	case ')':
	case '+':
	case '-':
	case '*':
	case '/':
	case '%':
	case ';':
	case '=':
	case 'k':
	case ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	case '.':
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		cin.unget();
		double val;
		cin >> val;
		return Token(number, val);
	}
	default:
	{
		if (isalpha(ch) || ch == '_') { //is ch a letter?
			string s;
			s += ch;
			while (cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
				s += ch; //Error 2: s = ch;
			}
			cin.unget(); //puts the most recently read character back into the stream
			if (s == "exit") return Token(exitprog); //Error 2: if (s == "quit") return Token(name);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' '); //Line missing
	}
	}
}

void Token_stream::ignore(char c)
{
	if (full && c == buffer.kind) {
		full = false;
		return;
	}
	full = false;
	char ch;
	while (cin >> ch) {
		if (ch == c) return;
	}
}

struct Variable {
	string name;
	double value;
	bool immutable;
	Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

vector<Variable> names;

double get_value(string s)
{
	for (int i = 0; i < names.size(); ++i) {
		if (names[i].name == s) {
			return names[i].value;
		}
	}
	error("get: undefined name ", s);
	return 0.0; //Line missing
}

void set_value(string s, double d)
{
	for (int i = 0; i <= names.size(); ++i) {
		if (names[i].name == s) {
			names[i].value = d;
			return;
		}
	}
	error("set: undefined name ", s);
}

bool is_declared(string s)
{
	for (int i = 0; i<names.size(); ++i) {
		if (names[i].name == s) return true;
	}
	return false;
}

bool is_immutable(string s)
{
	for (int i = 0; i<int(names.size()); ++i)
		if (names[i].name == s && names[i].immutable) return true;
	return false;
}

Token_stream ts;

double expression();

double primary()
{
	Token t = ts.get();
	switch (t.kind) {
	case '(':
	{
		double d = expression();
		t = ts.get();
		if (t.kind != ')') error("')' expected"); //Error 3: if (t.kind != ')') error("'(' expected");
		return d; //Line missing
	}
	case '-':
	{
		return -primary();
	}
	case '+':
	{
		return primary();
	}
	case number:
	{
		return t.value;
	}
	case sqroot:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}
		ts.unget(t);
		double d = primary();
		if (d < 0.0) {
			error("negative square root");
		}
		return sqrt(d);
	}
	case power:
	{
		t = ts.get();
		if (t.kind != '(') {
			error("'(' expected");
		}

		double x = expression();

		t = ts.get();
		if (t.kind != ',') {
			error("',' expected");
		}

		int n = int(expression());

		t = ts.get();
		if (t.kind == ')') {
			return pow(x, n);
		}
		else {
			error("Expected ')'");
		}
	}
	case name:
	{
		return get_value(t.name);
	}
	default:
	{
		error("primary expected");
		return 0.0; //Line missing
	}
	}
}

double term()
{
	double left = primary();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case 'k':
		{
			left *= 1000;
			break;
		}
		case '*':
		{
			left *= primary();
			break;
		}
		case '/':
		{
			double d = primary();
			if (d == 0) error("divide by zero");
			left /= d;
			break;
		}
		default: {
			ts.unget(t);
			return left;
		}
		}
	}
}

double expression()
{
	double left = term();
	while (true) {
		Token t = ts.get();
		switch (t.kind) {
		case '+':
		{
			left += term();
			break;
		}
		case '-':
		{
			left -= term();
			break;
		}
		default:
		{
			ts.unget(t);
			return left;
		}
		}
	}
}

double declaration(char kind)
{
	Token t = ts.get();
	if (t.kind != name) { //if (t.kind != 'a')
		error("name expected in declaration");
	}

	string name = t.name;
	if (kind == let || kind == constant) {
		if (is_declared(name)) error(name, " declared twice");
	}
	else if (kind == reset) {
		if (!is_declared(name))
			error(name, " has not been declared");
		if (is_immutable(name))
			error(name, " is a constant");
	}
	else {
		error("unknown statement");
	}

	Token t2 = ts.get();
	if (t2.kind != '=') error("= missing in declaration of ", name);
	double d = expression();
	if (is_declared(name))
		set_value(name, d);
	else
		names.push_back(Variable(name, d, (kind == constant)));
	return d;
}

double statement()
{
	Token t = ts.get();
	double d;
	if (t.kind == let || t.kind == reset || t.kind == constant) {
		d = declaration(t.kind);
	}
	else {
		ts.unget(t);
		d = expression();
	}
	t = ts.get();
	if (t.kind != print) {
		error("Missing terminator");
	}
	return d;
}

void clean_up_mess()
{
	ts.ignore(print);
}

const string prompt = "> ";
const string result = "= ";

void calculate()
{
	while (true) try {
		cout << prompt;
		Token t = ts.get();
		while (t.kind == print) {
			t = ts.get();
		}
		if (t.kind == exitprog) {
			return;
		}
		ts.unget(t);
		cout << result << statement() << endl;
	}
	catch (runtime_error& e) {
		cerr << e.what() << endl;
		clean_up_mess();
	}
}

int main()

try {
	calculate();
	return 0;
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
	char c;
	while (cin >> c&& c != ';');
	return 1;
}
catch (...) {
	cerr << "exception\n";
	char c;
	while (cin >> c && c != ';');
	return 2;
}
Output:
> const x = 5;
= 5
> x + 6;
= 11
> reset x = 7;
x is a constant
>