w72er | 18 Январь, 2010 08:56
Код калькулятора, приведенный в главе 6, применяется повсеместно в книге Бьерна Страуструпа "Язык программирования c++".
/*
program:
END //это конец ввода
expr_list
expr_list: //список выражений
expression PRINT //PRINT - это точка с запятой
expression PRINT expr_list
expression: //выражение
expression + term
expression - term
term
term: //терм
term / primary
term * primary
primary
primary: //первичное выражение
NUMBER //число
NAME //имя
NAME = expression
-primary
(expression)
Терминальные символы распознаются лексическим анализатором,
get_token(); Нетерминальные символы распознаются синтаксическим
анализатором, expr(), term(), prim(); Как только оба (под)выражения
определены вычисляется значение выражения.
*/
#include <iostream>
#include <string>
#include <map>
#include <cctype>
using namespace std;
enum Token_value {
NAME, NUMBER, END,
PLUS = '+', MINUS = '-', MUL = '*', DIV = '/',
PRINT = ';', ASSIGN = '=', LP = '(', RP = ')'
};
Token_value curr_tok = PRINT;
double number_value; //численное значение
string string_value; //строковое значение
map<string, double> table;
int no_of_errors;
int error(const string& s)
{
no_of_errors++;
cerr << "ошибка: " << s << '\n';
return 1;
}
Token_value get_token()
{
char ch = 0;
cin >> ch;
switch (ch) {
case 0:
return curr_tok = END;
case ';':
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
return curr_tok = Token_value(ch);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
cin.putback(ch);
cin >> number_value;
return curr_tok = NUMBER;
default:
if (isalpha(ch)) {
cin.putback(ch);
cin >> string_value;
return curr_tok = NAME;
}
error("неправильная лексема");
return curr_tok = PRINT;
}
}
double expr(bool);
double prim(bool get) //первичные выражения
{
if (get) get_token();
switch (curr_tok) {
case NUMBER:
{
double v = number_value;
get_token();
return v;
}
case NAME:
{
double& v = table[string_value];
if (get_token() == ASSIGN) v = expr(true);
return v;
}
case MINUS:
return -prim(true);
case LP:
{
double e = expr(true);
if (curr_tok != RP) return error("ожидалась )");
get_token(); //пропустить ")"
return e;
}
default:
return error("ожидалось первичное выражение");
}
}
double term(bool get) //умножение и деление
{
double left = prim(get);
for (;;)
switch (curr_tok) {
case MUL:
left *= prim(true);
break;
case DIV:
if (double d = prim(true)) {
left /= prim(true);
break;
}
return error("деление на 0");
default:
return left;
}
}
double expr(bool get)
{
double left = term(get);
for (;;)
switch (curr_tok) {
case PLUS:
left += term(true);
break;
case MINUS:
left -= term(true);
break;
default:
return left;
}
}
int main()
{
table["pi"] = 3.14;
table["e"] = 2.72;
while (cin) {
get_token();
if (curr_tok == END) break;
if (curr_tok == PRINT) continue;
cout << expr(false) << '\n';
}
return no_of_errors;
}
| « | Февраль 2012 | » | ||||
|---|---|---|---|---|---|---|
| Пн | Вт | Ср | Чт | Пт | Сб | Вс |
| 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 | ||||