Читать «Полный справочник по С++» онлайн - страница 447

Герберт Шилдт

Лучше изменить функцию serror() так, чтобы она выполняла выход из ф\нк-ции. Например, все компиляторы языка C++ содержат пару функций, называемых setjmp() и longjmpO. Эти функции позволяют программе передавать управление из одной функции в другую. Следовательно, с помощью функции lonjmpO функция setjmpO может выполнить передачу управления в безопасную точку программы, находящуюся за пределами синтаксического анализатора.

Кроме того, в программе синтаксического анализа можно применить механизм обработки исключительных ситуаций, реализуемый с помощью операторов try, catch И throw.

Если оставить этот код без изменения, на экран могут выдаваться многократные сообщения о синтаксических ошибках. В одних ситуациях это может быть нежелательным, а в других желательным, поскольку так можно выявить сразу несколько ошибок. Однако, как правило, блок синтаксического контроля в коммерческих программах является более изощренным.

В Создание обобщенного синтаксического анализатора

Две предыдущие версии программы предназначались для синтаксического анализа арифметических выражений типа double. Однако этим все многообразие выражений не исчерпывается. Кроме того, жестко заданный тип выражений ограничивает возможности синтаксического анализатора. К счастью, синтаксический анализатор можно представить в виде шаблонного класса, позволяющего обрабатывать выражения произвольных типов, как встроенных, так и пользовательских.

Рассмотрим обобщенную версию синтаксического анализатора.

// Обобщенный синтаксический анализатор.

♦include <iostream>

♦include <cstdlib>

♦include <cctype>

♦include <cstring> using namespace std;

enum types { DELIMITER = 1, VARIABLE, NUMBER}; const int NUMVARS = 26;

template cclass PType> class parser {

char *exp_ptr; char token[80] ; char tok_type;

PType vars[NUMVARS];

// Ссылается на выражение.

// Хранит текущую лексему.

// Хранит тип лексемы.

// Хранит значения переменных.

void eval_expl(PType kresult) void eval_exp2(PType kresult) void eval_exp3(PType kresult) void eval_exp4(PType kresult)

void eval_exp5(PType &result); void eval_exp6(PType &result); void atom(PType &result); void get_token(), putback(); void serrorlint error);

PType find_var(char *s); int isdelim(char c); public: parser();

PType eval_exp(char *exp);

};

// Конструктор класса parser.

template cclass PType> parsercPType>::parser()

{

int i ;

exp_ptr = NULL;

for(i=0; icNUMVARS; i++) vars[i] = (PType) 0;

}

// Отправная точка анализа.

template cclass PType> PType parsercPType>::eval_exp(char *exp) {

PType result;

exp_ptr = exp;

get_token(); if(!*token) {

serror(2); // Выражение пусто, return (PType) 0;

}

eval_expl(result);

if(*token) serror(O); // Последняя лексема должна быть

// нулевым символом.

return result;

// Присваивание.

template cclass РТуре> void parsercPType>::eval_expl(PType bresult) {