Читать «Полный справочник по С++» онлайн - страница 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;