Материал: 12562633_1109924Ispol_zo

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

{ // Обработчик событий vert->value(b->yvalue()); horiz->value(b->xvalue());

CrossInformation();

}

static void cb_vert(Fl_Roller* r, void*)

{ // Обработчик событий

ClientArea->yvalue(r->value()); CrossInformation();

}

//функция проверяет, пересекаются ли два заданных

//отрезка

bool OterezokXOtrezok(Point Dot_11,Point

Dot_21,Point Dot_12,Point Dot_22)

{

. . . . . . . . . . . . .

return true;

return false;

}

static void cb_horiz(Fl_Roller* r, void*)

{

ClientArea->xvalue(r->value()); CrossInformation();

}

//Функция кнопки открытия файла

static void cb_btnfile(Fl_Button*, void*)

{

char *newfile =

fl_file_chooser("Открыть файл", "*.txt", ""); if (newfile!= NULL)

{

StartLoadPolygon(newfile);

}

ClientArea->xvalue(ClientArea->w()/2);

ClientArea->yvalue(ClientArea->h()/2); ClientArea->do_callback(); ClientArea->draw(); CrossInformation();

}

//Находится ли новая точка внутри многоугольника void CrossInformation()

{

char b[30];

int x=(int)(ClientArea->xvalue()); int y=(int)(ClientArea->yvalue());

26

if(NumPoint==0)

{

sprintf(b,"Файл не загружен");

}

else

{

if(DotIsInPoligon(Poly,NumPoint,x,y)) sprintf(b,"Точка внутри полигона");

else sprintf(b,"Точка снаружи полигона");

}

txtdispl->buffer()->text(b);

}

static void cb_btnext(Fl_Button*, void*)

{

exit(0);

}

int main(int argc, char **argv)

{

// Собственно создание интерфейсного окна

Fl_Window* w= new Fl_Window(450, 550);

ClientArea = new dwin(10, 10, 430, 430);

ClientArea->callback((Fl_Callback*)cb_brow); vert = new Fl_Roller(420,450, 20, 85); vert->callback((Fl_Callback*)cb_vert);

horiz = new Fl_Roller(10, 450, 400, 20); horiz->type(1); horiz->callback((Fl_Callback*)cb_horiz);

btnfile = new Fl_Button(10,510,190,25,”Загрузить"); btnfile->tooltip("Загрузить многоугольник"); btnfile->callback((Fl_Callback*)cb_btnfile);

btnext = new Fl_Button(220, 510, 190, 25, "Выход"); btnext->tooltip("Выход из программы"); btnext->callback((Fl_Callback*)cb_btnext); btnext->shortcut(FL_ALT+'x');

txtdispl = new Fl_Text_Display(10, 480,350,25); txtbuf=new Fl_Text_Buffer(10); txtdispl->buffer(txtbuf); w->insert((Fl_Widget&)*ClientArea, 0); w->show(argc, argv);

horiz->range(0, ClientArea->w()); vert->range(0, ClientArea->h()); horiz->step(1);

vert->step(1);

ClientArea->xbounds(0, ClientArea->w()); ClientArea->ybounds(0, ClientArea->h());

// Вход в цикл событий return Fl::run();

}

27

4. ИСПОЛЬЗОВАНИЕ СРЕДСТВ АВТОМАТИЧЕСКОЙ ГЕНЕРАЦИИ ПАРСЕРОВ

Для чего используется синтаксический анализ? Во-первых, достаточно часто возникает необходимость в приложениях просто осуществить вычисления по заданной формуле. Во-вторых, необходимость в крупных программных продуктах (офисные приложения, компиляторы, бухгалтерские программы) наличия возможности расширения программными средствами удобств пользователя заставляют разработчиков встраивать в приложения так называемые скрипт-языки.

И в том и в другом случаях не обойтись без программ синтаксического разбора (парсера). Но написание такой программы – долгий и утомительный труд, на котором вас подстерегают многочисленные отладочные проблемы.

К счастью, есть программы, автоматически генерирующие синтаксические распознаватели, да еще с возможностью генерации кода, описываемого на языке высокого уровня. Простейшими примерами являются программы yacc и bison. В ОС UNIX – это стандартные компоненты системы. Для DOS и Windows существуют их аналоги. К ним относится, например, программа pcyacc разработки фирмы Abraxas software.

Что же представляет из себя yacc?

Генератор распознавателей yacc

Yacc – это универсальные средства для структуризации исходных данных программ. Пользователь задает спецификацию (грамматику языка), которая включает:

множество правил, описывающих составные части исходных данных;

действия, выполняемые при применении правила;

определение или описание процедуры нижнего уровня, анализирующей исходные данные.

Yacc отображает спецификацию в функцию yyparse() на языке C, обрабатывающую входной поток данных. Эта функция является процедурой синтаксического разбора и при выполнении обращается к низкоуровневому сканеру входных данных (лексическому распознавателю). Сканер извлекает из входного потока элементарные конструкции языка – лексемы. Лексемы сопоставляются с правилами, описывающими структуру входного текста, то есть с грамматическими правилами.

Если правило оказывается подходящим, то выполняется ассоциированное с ним действие. Действие – это фрагмент программы на языке C. Действия могут возвращать значения, а также использовать значения, возвращаемые другими действиями, например сканером.

28

Имена обозначают лексемы или нетерминальные символы. YACC требует, чтобы имена лексем были указаны явно. Хотя лексический анализатор можно включить в файл спецификаций, определение его в отдельном файле, вероятно, более соответствует принципам модульного проектирования. Подобно лексическому анализатору, в файл спецификаций могут быть также включены и другие подпрограммы.

Таким образом, каждый файл спецификаций (yacc-программа) теоретически состоит из трех секций: определений, (грамматических) правил и подпрограмм.

Структура спецификации yacc

Секции отделяются двумя знаками процента %% (знак % используется в yacc-спецификациях как универсальный управляющий). Если используются все секции, полный файл спецификаций выглядит следующим образом:

определения

%%

правила

%%

подпрограммы

Секции определений и подпрограмм являются необязательными. Минимальная допустимая yacc-спецификация – это

%%

правила

%%

Пробелы, табуляции и переводы строки, которые встречаются вне имен и зарезервированных слов, игнорируются. Комментарии могут быть везде, где допустимо имя. Они оформляются как многострочный комментарий на языке Си: /*...*/

Секция правил

Секция правил составляется из одного или большего числа грамматических правил. Грамматическое правило имеет вид

нетерминал: определение;

где определение – это последовательность из нуля или нескольких альтернатив, разделенных метасимволом «ИЛИ», в роли которого выступает символ – вертикальная черта(|). Каждая альтернатива представляет набор имен и литералов. Каждые двоеточие и точка с запятой – знаки препинания yacc'а.

Имена могут иметь произвольную длину и должны состоять из букв, точек, подчеркиваний и цифр, однако имя не может начинаться с

29

цифры. Прописные и строчные буквы различаются. Имена, используемые в теле грамматического правила, могут представлять лексемы или нетерминальные символы.

Секция определений

Всекции определений можно объявлять: терминальные символы, начальный символ, операции,

типы нетерминалов.

Терминальные символы объявляются при помощи декларатора

%token: %token имя1 имя2.

Считается, что всякое имя, не описанное в секции определений, представляет нетерминальный символ. Каждый нетерминальный символ должен встретиться в левой части по крайней мере одного правила.

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

Из начального символа можно вывести любую правильную фразу языка. Можно явно объявить начальный символ в секции определений при помощи ключевого слова %start:

%start начальный_символ

Операции можно объявить деклараторами %left, %right, %noassoc:

%left '+' '-'

%left '*' '/' %right '='

%noassoc UNARYMINUS

Лексемы, встречающиеся в одном деклараторе, считаются равноприоритетными операциями.

Приоритет операций увеличивается от декларатора к декларатору. Например, операции „*‟ и „/‟ в приведенном примере имеют более высокий приоритет, чем „+‟ и „-„.

Тип нетерминального символа задается декларатором %type:

% type expr double

Секция процедур

В этой секции должна быть описана функция main(), вызывающая процедуру разбора, ее имя – yyparse(). Здесь же можно поместить подпрограммы обработки ошибок, служебные функции и лексический распознаватель (сканер).

30

Источник: https://studfile.net/preview/16710218/