Опубликован: 23.07.2006 | Доступ: свободный | Студентов: 2213 / 889 | Оценка: 4.28 / 4.17 | Длительность: 21:37:00
Специальности: Системный архитектор
Лекция 8:

Грамматики и YACC

Секция описаний процедур

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

Пользователь должен предоставить две процедуры:

  • процедуру int yylex (void) , которая реализует лексический анализ и возвращает лексический класс лексемы
  • процедуру int yyerror (char * s) , которая вызывается построенным анализатором в случае возникновения ошибки во входной цепочке

YACC создает процедуру int yyparse (void) , возвращающую код завершения ( 0 или 1 ).

Опишем некоторые параметры программы YACC:

  • Cf - созданный анализатор будет помещен в файл f
  • Df - будет построен заголовочный файл с именем f
  • v - в файл с именем yy.lrt будет выведен протокол, т.е. управляющая таблица анализатора

Пример

Воспользуемся YACC для реализации калькулятора, т.е. программы, которая вычисляет значение константной арифметической формулы.

Уточним формулировку задачи. Входной поток содержит множество формул, каждая из которых занимает отдельную строчку входного потока. Требуется вычислить значение каждой формулы.

Формула может содержать целые числа, операции +, -, *, / (для вычисления целочисленного частного). Например, для входного потока

(5+3)*7
3+4/2-5/3
будут выведены значения
56
4

Пример (продолжение)

Пример (продолжение)

int yylex (void)
{       int ch;
         while ((ch = getchar ()) == ' ');
         if (isdigit (ch))
         { ungetc (c, stdin); scanf (%i, &yylval); 
            return NUMBER_LC;}
          return ch;
}

Начнем с описания функции yylex .

int yylex (void)
{
int ch;
/* пропускаем пробелы в начале строки */
while ((ch = getchar ()) == ' ');

if (isdigit (ch))
{
ungetc (ch, stdin); 
scanf (%i, &yylval);
return NUMBER_LC;
}

return ch;
}

Функция yylex вычисляет пару значений, одно из которых лексический класс, а другое связанный с ним атрибут. Если лексический класс функция yylex возвращает в качестве своего значения, то атрибут передается анализатору через присваивание переменной yylval . Иначе говоря, то значение, которое присваивается переменной yylval , это значение терминального символа NUMBER.

Пример (продолжение)

В секции определений определен терминал NUMBER_LC, который имеет тип int, нетерминал expression, также имеющий тип int, и правила ассоциативности операций, которые могут быть использованы в формуле. Нетерминал lines не должен определяться в этой секции, поскольку он не имеет значения.

%union
   {
            int VALUE;
   }

%token  <VALUE> NUMBER_LC

%type <VALUE> expression 

%left '+' '-'
%left '*' '/'

%start expression                 /* аксиома грамматики */

%%