Читать «Полный справочник по С++» онлайн - страница 445
Герберт Шилдт
/* Программа, выполняющая рекурсивный нисходящий анализ выражений, содержащих переменные.
*/
♦include <iostream>
♦include <cstdlib>
♦include <cctype>
♦include <cstring> using namespace std;
enum types { DELIMITER = 1, VARIABLE, NUMBER};
const int NUMVARS = 26;
class parser {
char *exp_ptr; II Ссылается на выражение.
char token[80]; II Хранит текущую лексему.
char tok_type; // Хранит тип лексемы.
double vars[NUMVARS]; // Хранит значения переменных.
void eval_expl(double kresult); void eval_exp2 (double ^result) ,-void eval_exp3(double kresult); void eval_exp4(double kresult); void eval_exp5(double kresult); void eval_exp6(double ^result);
void atom(double kresult); void get_token () ,-void putbackO ; void serror(int error); double find_var(char *s); int isdelim(char c),-public: parser();
double eval_exp (char *exp) ,-
) ;
II Конструктор класса parser, parser::parser()
{
int i;
exp_ptr = NULL;
for(i=0; i<NUMVARS; i++) vars[i] = 0.0;
}
П Отправная точка анализа, double parser::eval_exp(char *exp)
{
double result;
exp_ptr = exp;
get_token(); if(!*token) {
serror(2); П Выражение пусто, return 0.0;
}
eval_expl(result) ;
if(*token) serror(O); II Последняя лексема должна быть
П нулевым символом.
return result;
П Присваивание.
void parser::eval_expl(double bresult) {
int slot;
char ttok_type;
char temp_token[80];
if(tok_type==VARIABLE) {
II Сохраняем старую лексему, strcpy(temp_token, token); ttok_type = tok_type;
II Вычисляем индекс переменной, slot = toupper(*token) - 'A';
get_token();
if(*token != '=1) {
putbackO; II Возвращаем текущую лексему.
// Восстанавливаем старую лексему -// присваивание не выполняется, strcpy(token, temp_token); tok_type = ttok_type;
}
else {
get_token(); // Извлекаем следующую часть выражения exp. eval_exp2(result); vars[slot] = result; return;
}
eval_exp2(result);
}
II Складываем или вычитаем два терма, void parser::eval_exp2(double ^result)
{
register char op;
double temp;
eval_exp3(result);
while((op = *token) == '+' || op == '-') {
get_token(),-eval_exp3(temp); switch(op) { case 1 - ' :
result = result - temp; break ,-case '+':
result = result + temp; break;
}
}
II Умножаем или делим два фактора, void parser::eval_exp3(double ^result)
{
register char op;
double temp;
eval_exp4(result) ;
while((op = *token) == '*' || op == '/' |] op == ’%') {
get_token(); eval_exp4(temp); switch(op) { case '*':
result = result * temp; break; case '/1:
result = result / temp; break; case '% 1:
result = (int) result % (int) temp;
break;
II Возведение в степень.
void parser::eval_exp4(double kresult)
{
doub1e temp, ex,-register int t;
eval_exp5(result) ; if(*token== 'л' ) { get_token() ,-eval_exp4(temp); ex = result; if(temp==0.0) { result = 1.0; return;
)
for(t=(int)temp-1; t>0; —t) result = result * (double)ex;
}
}
// Выполнение унарных операций + или -. void parser::eval_exp5(double ^result)
{
register char op; op = 0 ;
if((tok_type == DELIMITER) && *token=='+' || *token == '-') {
op = *token; get_token();
}
eval_exp6(result); if(op==,-,) result = -result;