Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Yacc.docx
Скачиваний:
13
Добавлен:
20.03.2016
Размер:
121.86 Кб
Скачать

11. Диагностика ошибок

yacc выдает ряд сообщений об ошибках в случае невозмож-

ности построения грамматического анализатора. В тексте сооб-

щения, предваряемом заголовком "ошибка:", содержится указа-

ние причины ошибки и номер просматриваемой в момент ее появ-

ления строки спецификационного файла. Перечислим основные

типы фиксируемых yacc ошибок:

неверно заданные флаги командной строки;

невозможность открытия входного или временных файлов;

отсутствие файла /usr/lib/yaccpar с текстом процедуры

yyparse;

неверная структура спецификационного файла;

ошибки в задании директив;

синтаксические ошибки в описании грамматических правил,

незавершенность комментариев, строк символов и дейст-

вий;

- 32 -

некорректное использование псевдопеременных;

неопределенные нетерминальные символы;

нарушение количественных ограничений (по числу терми-

нальных или нетерминальных символов, грамматических

правил, состояний и проч.).

- 33 -

Приложение 1

Ниже приведен полный входной файл для yacc, реализующий

небольшой настольный калькулятор; калькулятор имеет 26

регистров, помеченных буквами от a до z и разрешает исполь-

зовать арифметические выражения, содержащие операции +, -,

*, /, % (остаток от деления), & (побитовое и), | (побитовое

или) и присваивание. Как и в Си, целые числа, начинающиеся с

0, Считаются восьмеричными, все остальные - десятичными.

В примере демонстрируются способы использования приори-

тетов для разрешения конфликтов, а также простые операции по

восстановлению из состояния ошибки. Калькулятор работает в

интерактивном режиме с построчным формированием выхода.

%token DIGIT LETTER /* имена лексем */

%left '|' /* задание приоритетов */

%left '&' /* операций */

%left '+' '-'

%left '*' '/' '%'

%left UMINUS /* установка приоритета

операции унарный минус */

%{ /* oписания, используемые */

Int base, regs[26]; /* в действиях */

%}

%% /* начало секции правил */

list:

| list stat '\n'

| list stat error '\n' {yyerrok; }

stat:

expr {printf("%d\n",$1);}

| LETTER '=' expr {regs[$1]=$3; }

expr:

'(' expr ')' { $$=$2; }

| expr '+' expr { $$=$1+$3; }

| expr '-' expr { $$=$1-$3; }

| expr '*' expr { $$=$1*$3; }

| expr '/' expr { $$=$1/$3; }

| expr '%' expr { $$=$1%$3; }

| expr '&' expr { $$=$1&$3; }

| expr '|' expr { $$=$1|$3; }

| '-' expr %prec UMINUS { $$= -$2; }

| LETTER { $$=regs[$1]; }

| number;

number:

DIGIT { $$=$1; base=10;

if($1==0) base=8; }

- 34 -

| number DIGIT {$$=base*$1+$2; }

%% /* начало секции программ */

/*

* Программа лексического анализа

* для строчных латинских букв

* возвращает LETTER,

* значение yylval от 0 до 25;

* для цифр - DIGIT,

* значение yylval от 0 до 9;

* остальные символы возвращаются

* непосредственно

*/

yylex()

{

int c;

while( (c=getchar()) == ' ' );

if( c>='a' && c<='z' ) {

yylval = c - 'a';

return(LETTER);

}

if( c>='0' && c<='9' ) {

yylval = c - '0';

return(DIGIT);

}

return(c);

}

- 35 -

Приложение 2

Анализ и преобразование в матричную форму входных дан-

ных для задачи линейного программирования.

Входная информация из обычной алгебраической формы:

c1X1+c2X2+...+cnXn -> min(max)

a11x1+a12X2+...+a1nXn=b1

am1X1+am2X2+...+amnXn=bm

преобразуется в матричную:

C: c1 c2 ... cn

A: a11 a12 ... a1n

...

am1 am2 ... amn

B: b1 b2 ... bm

Одновременно изменяются знаки коэффициентов при неизвестных

в ограничениях с отрицательным свободным членом, а также

знаки коэффициентов линейного функционала в случае его мак-

симизации. С иллюстративной целью допускаются некоторые

варианты синтаксической записи. Предусмотрена возможность

повторного задания ошибочных строк.

%token число Xi оптим

%%

злп:функционал '\n' система_ограничений

{final();}

| система_ограничений функционал '\n'

{ final();}

функционал: линейная_функция {stf();}

/* По умолчанию - минимизация */

| оптим '(' линейная_функция ')'

{if($1) conv(); stf();}

/* В случае максимизации выполнить conv() */

| линейная_функция '-''>' оптим

{if($4) conv();stf();}

линейная_функция: элем1

| линейная_функция элем ;

элем: знак число Xi {stc($1*$2,$3); }

| знак Xi '*' число { stc($1*$4,$2);}

| знак Xi { stc($1,$2);}

/* Формы записи коэффициентов */

элем1: элем

| число Xi { stc($1,$2);}

| Xi '*' число { stc($3,$1);}

- 36 -

| Xi { stc(1,$1); }

знак: '+' {$$=1; }

| '-' {$$= -1;}

система_ограничений: ограничение '\n'

| система_ограничений ограничение '\n'

| система_ограничений error '\n'

{aclear();yyerrok;

printf("повторите последнюю строку\n");}

/* В случае ошибки: стирание инф. о строке,

восстановление и выдача подсказки */

ограничение: линейная_функция '=' число

{ stcb($3);}

| линейная_функция '=' знак число

{ if($3<0) conv(); stcb($4);}

/* Если bi<0, выполнить conv() */

%%

#include "stdio.h"

#define MAXM 100 /* предельное число */

#define MAXN 100 /* ограничений и перем.*/

int c[MAXN],b[MAXM],a[MAXM+1][MAXN],

neqs,nx,x[MAXN];

/* Лексический анализатор возвращает:

* для целых чисел - число,

* yylval равно знач. числа;

* для идент.вида xi, i=1,2,...XI*

* yylval равно его порядк. номеру;

* для max/min - оптим,

* yylval равно соответственно 1 или 0

*/

yylex() {

char c,i;

while((c=getc(stdin))==' ');

switch(c) {

case'0':

case'1':

case'2':

case'3':

case'4':

case'5':

case'6':

case'7':

case'8':

case'9': yylval=c-'0';

while((c=getc(stdin))<='9'&&c>='0')

yylval=yylval*10+c-'0';

ungetc(c,stdin); return(число);

- 37 -

case'm': if((c=getc(stdin))=='i') yylval=0;

else if(c=='a') yylval=1;

else return('m');

while((c=getc(stdin))<='z'&&c>='a');

ungetc(c,stdin); return(оптим);

case'X':

case'x': if((c=getc(stdin))<'0' || c>'9')

return('x');

yylval=0;

while(c<='9'&&c>='0')

{yylval=yylval*10+c-'0';c=getc(stdin);}

ungetc(c,stdin);

for(i=0;i<nx;i++)

if(x[i]==yylval){yylval=i;return(Xi);}

x[nx]=yylval; yylval=nx++;return(Xi);

}

return(c);

}

/* Печать условия задачи в матричной форме */

final() {

char i,j;

printf("c:\n");

for(i=0;i<nx;i++) printf("%8d",c[i]);

printf("\na:\n");

for(i=0;i<neqs;i++) {

for(j=0;j<nx;j++) printf("%8d",a[i][j]);

printf("\n"); }

printf("b:\n");

for(i=0;i<neqs;i++) printf("%8d",b[i]);

}

/* Изменение знаков коэффициентов */

conv() {

char i;

for(i=0;i<nx;i++) a[neqs][i]*=(-1);

}

/* Запоминание коэффициентов функционала */

stf() {

char i;

for(i=0;i<nx;i++)

{ c[i]=a[neqs][i]; a[neqs][i]=0; }

}

/* Запоминание очередного коэффициента */

stc(nmb,adr) {

a[neqs][adr]=nmb; }

/* Запоминание свободного члена */

stcb(nmb) {

b[neqs++]=nmb; }

- 38 -

/* Стирание ошибочной строки*/

aclear(){

char i;

for(i=0;i<nx;i++)

a[neqs][i]=0;

}

- 39 -

Приложение 3

Формальное описание структуры спецификационного файла.

файл_спецификаций:

секция_деклараций '%''%'

'\n' секция_правил '%''%'

'\n' секция_программ

| секция_деклараций '%''%'

'\n' секция_правил ;

секция_деклараций:

| секция_деклараций дир_или_описание

'\n' ;

дир_или_описание:

'%''{''\n'ВНЕШНИЕ_ОПИСАНИЯ

'\n''%''}'

| '%''s''t''a''r''t' ИДЕНТИФИКАТОР

| '%''t''o''k''e''n'список_им_лексем

| ассоциативность список_лексем ;

ассоциативность:

'%''l''e''f''t'

| '%'''r''i''g''h''t'

| '%''n''o''n''a''s''s''o''c' ;

список_им_лексем:

| декл_имени_лексемы

| список_им_лексем

декл_имени_лексемы ;

список_лексем:

декл_лексемы

| список_лексем декл_лексемы ;

декл_имени_лексемы:

ИДЕНТИФИКАТОР

| ИДЕНТИФИКАТОР ЦЕЛОЕ_БЕЗ_ЗНАКА;

декл_лексемы:

декл_лексемы

| декл_литерала;

декл_литерала:

ЛИТЕРАЛ

| ЛИТЕРАЛ ЦЕЛОЕ_БЕЗ_ЗНАКА;

секция_правил:

набор_правил

| '%''{''\n'СИ_ОПЕРАТОРЫ'\n''%''}'

'\n' набор_правил '\n' ;

набор_правил:

правило

| набор_правил ';' правило ;

правило:

левая_часть ':' альтернатива

| правило '|' альтернатива ;

левая_часть: ИДЕНТИФИКАТОР ;

альтернатива:

- 40 -

правая_часть

| правая_часть изм_приор

| правая_часть изм_приор действие

| правая_часть действие ;

правая_часть:

| правая_часть лит_или_идент

| правая_часть действие лит_или_идент;

изм_приор:

секция_программ:

ПРОГРАММНЫЕ_КОМПОНЕНТЫ ;

При описании структуры спецификационного файла не рас-

шифровывались некоторые исходные конструкции, совпадающие с

аналогичными конструкциями Си: идентификатор, литерал, целое

без знака. Не описаны также и более сложные конструкции,

являющиеся фрагментами Си-программ, переносимыми в текст

анализатора (внешние описания, Си-операторы). Под расширен-

ными Си-операторами понимаются операторы с возможным исполь-

зованием псевдопеременных. ПРОГРАММНЫЕ_КОМПОНЕНТЫ включают

операторы препроцессора, описания внешних переменных и функ-

ций (возможный состав их приводится в разделе 4.3).

- 41 -

СОДЕРЖАНИЕ

. Аннотация ......................................... 2

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]