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

7. Декларация имени начального символа

%start <имя_начального_символа>

Директива отменяет действующий по умолчанию выбор в

качестве начального символа нетериминала, определяемого пер-

вым грамматическим правилом.

7.1. Секция программ

В секцию программ помещается описание пользовательских

процедур, которые должны быть включены в генерируемую прог-

рамму грамматического анализа. Любая из определяемых пользо-

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

программ спецификационного файла, либо присоединяться на

этапе вызова Си-компилятора для трансляции файла y.tab.c и

компоновки выходной программы. Перечислим процедуры, которые

одним из этих способов должны быть заданы:

- лексический анализатор - функция с именем yylex();

- все процедуры, вызовы которых содержатся в действиях,

связанных с грамматическими правилами;

- главная процедура main() при необходимости заменить ее

стандартный библиотечный вариант, который имеет вид

main() {return (yyparse();}

- процедура обработки ошибок yyerror() - также для замены

библиотечного варианта (его текст приводится ниже).

#include <stdio.h>

yyerror(s) char *s; {

fprintf(stderr, "%s\n", s);}

Для обеспечения корректной работы грамматического ана-

лизатора функция лексического анализа yylex должна быть сог-

ласована с конкретной спецификацией грамматики и удовлетво-

рять определенным требованиям. Основная задача функции yylex

состоит во вводе из входного потока ряда очередных символов

до выявления конструкции, соответствующей одной из лексем, и

возвращении номера типа этой лексемы. Для нелитеральных лек-

сем номером типа может служить объявленное в секции деклара-

ций имя лексемы (с помощью механизма #define yacc обеспечи-

вает замену его нужным номером), в случае литералов номером

типа является числовое значение символа (если оно не было

- 15 -

переопределено). Алгоритм поиска должен заключаться в

попытке нахождения сначала более сложных (нелитеральных)

лексем и лишь при несовпадении ни с одной из них текущих

элементов ввода возвращать номер типа литеральной лексемы

(любой однозначный символ, не начинающий ни одну из возмож-

ных лексем, сам образует лексему).

Приведем текст процедуры лексического анализа, распоз-

нающей идентификаторы и целые числа:

#include <stdio.h>

yylex() {char c;

while ((c=getc(stdin))==' '||c=='\n');

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

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

ungetc(c,stdin));

return (CONST);}

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

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

||c>='0'&&c<='9');

ungetc(c,stdin); return (NAME);}

return (c); }

Сложность лексического анализатора зависит от того,

какие структурные единицы взяты за основу при описании грам-

матических правил. Детализовав грамматику до отдельных сим-

волов, можно обойтись простейшим лексическим анализатором,

осуществляющим только их ввод:

yylex() {return (getchar());}

Однако, в этом случае число правил растет, а граммати-

ческий разбор оказывается менее эффективным. Поэтому пользо-

ватель обычно должен найти некоторый компромисс при выборе

набора лексем.

В процедуре лексического анализа кроме выделения лексем

можно предусмотреть некоторую обработку лексем определенных

типов, в частности, запоминание конкретных значений лексем.

Кроме того, эти значения обычно требуется передать граммати-

ческому анализатору. С этой целью нужное значение должно

быть присвоено внешней переменной целого типа с именем yyl-

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