Автоматизация разработки программ На примере синтаксического анализатора для калькулятор Постановка задачи Калькулятор с использованием функций, выражений любого типа сложности и имепнованных регистров хранения Наличие графического интерфейса Ограниченный срок исполнения Тема 13 Автоматизация разработки программ 2 Декомпозиция Структурная декомпозиция приводит к следующим модулям Графический интерфейс – требование заказчика Анализ и вычисление выражения (строки текста) Передача данных из интерфейса в расчетный модуль и наоборот Тема 13 Автоматизация разработки программ 3 Графический интерфейс Представляется наиболее сложным Автоматизируем разработку применением визуального проектирования Легкий в освоении FLTK и fluid позволяют сделать интерфейс за несколько десятков минут… Тема 13 Автоматизация разработки программ 4 Интерфейс калькулятора Тема 13 Автоматизация разработки программ 5 Главная «сложность» позади Что дальше? В строке окна текстового ввода мы получаем выражение, которое нужно вычислить… (после написания callback’ов, см. след.слайд) Вычисление требует разбора строки с учетом приоритетов операций Тема 13 Автоматизация разработки программ 6 Напишем обработчики кнопок Тема 13 Автоматизация разработки программ 7 Синтаксический разбор Всегда считался сложным Пока не появились средства автоматизации (yacc, bison, eli) Для их использования нужно описать грамматику используемых выражений Тема 13 Автоматизация разработки программ 8 Определим структуру элемента стека разбора typedef struct Symbol { char *name; short type; union { double val; double (*ptr)(); }u; struct Symbol *next; } Symbol; Symbol *symlist =0; Тема 13 Автоматизация разработки программ 9 Определим списки используемых констант и функций static struct { char *name; double cval; } Const[]= { "PI", 3.1415926536, "E", 2.718281828459, "RAD",57.2958, 0,0 }; static struct { char *name; double (*func)(); } Funcs[]= { "sin",sin, "cos",cos, "tan",tan, "sqrt",Sqrt, "abs",fabs, 0,0 }; %} Тема 13 Автоматизация разработки программ 10 Определим состав лексем и операций %token <val> NUM %token <sym> VAR FUNC UNDF %type <val> expr assign %type <val> prog %right '=' %left '+' '-' %left '*' '/' %right '^' %left UNMIN %% Тема 13 Автоматизация разработки программ 11 Определим грамматику prog: '\n' | expr '\n' | prog expr '\n' { printf("!\n"); } { $$=$1; printf("=>%lf\n",$$); { $$=$2; printf("->%lf\n",$$); ; assign: VAR '=' expr ; expr: NUM | VAR | FUNC '(' expr ')' | expr '+' expr | expr '-' expr | expr '*' expr { { { { { { { } } $$ = $1->u.val=$3; $1->type=VAR; } $$ = $1; } $$ = $1->u.val; } $$ = (($1->u.ptr)($3)); } $$ = $1+$3; } $$ = $1 - $3; } $$ = $1*$3; } Тема 13 Автоматизация разработки программ 12 Окончание грамматики | expr '/' expr | | | | ; { if ($3!=0) $$ = $1/$3; else { printf(" Zero divide\n"); $$=$1; } } expr '^' expr { $$ = pow($1,$3); } '-' expr %prec UNMIN { $$ = -$2; } assign '(' expr ')' { $$ = $2; } %% Тема 13 Автоматизация разработки программ 13 Лексический распознаватель yylex() { int c; Symbol *s; char sbuf[100], *p=sbuf; while((c=getchar())==' '); if (c==EOF) return 0; if(isalpha(c)) { do *p++=c; while (((c=getchar())!=EOF) && isalnum(c)); ungetc(c,stdin); *p='\0'; if ((s=lookup(sbuf))==0) s=install(sbuf,UNDF,0.0); yylval.sym=s; return ((s->type==UNDF) ? VAR : s->type); } if (c=='.' || isdigit(c)) { ungetc(c,stdin); scanf("%lf",&yylval); eturn NUM; }; return c; Тема 13 Автоматизация } разработки программ 14 Переделка лексического распознавателя В данном варианте лексический парсер вводит информацию из потока stdin, переделаем его для ввода из символьной строки. Саму строку, считанную в массив типа extern по callback’у кнопки «calc!» считываем до символа с нулевым кодом. Выделенные красным цветом строки в грамматики переделаем так, чтобы вывод помещался не в stdout, а в строку типа extern и оттуда был доступен для графического интерфейса Тема 13 Автоматизация разработки программ 15 Компоновка При компоновке мы сталкиваемся с различным представлением символов в GSD языков C и C++. Будем исправлять это в файле y.tab.c после компиляции yacc’ем. Автоматизируем и эту работу, поручив ее программе sed. Тема 13 Автоматизация разработки программ 16 Еще нужно почитать про Make Yacc Autoconf Тема 13 Автоматизация разработки программ 17