- •1. Принципы работы yacc
- •2. Входные и выходные файлы, структура грамматического ана-
- •3. Процедура построения грамматического анализатора
- •4. Задание входной информации yacc
- •4.1. Структура спецификационного файла
- •4.2. Секция правил
- •4.3. Секция деклараций
- •5. Декларация имен лексем
- •6. Декларация приоритетов и ассоциативности лексем
- •7. Декларация имени начального символа
- •7.1. Секция программ
- •Val. Если функция yylex находится в отдельном файле, то эта
- •7.2. Действия с использованием псевдопеременных
- •8. Конфликты грамматического разбора
- •If '(' условие ')' оператор else
- •9. Структура информационного входного файла y.Output
- •10. Обработка ошибок при грамматическом разборе
- •11. Диагностика ошибок
- •0, Считаются восьмеричными, все остальные - десятичными.
- •Int base, regs[26]; /* в действиях */
- •1. Принципы работы yacc .............................. 3
4.3. Секция деклараций
Секция деклараций состоит из последовательности строк
двух видов: строк-директив и строк исходного текста.
Строки исходного текста без изменений копируются в
выходной файл y.tab.c и могут содержать операторы препроцес-
сора и описание внешних объектов. Область действия перемен-
ных, описанных в секции деклараций, распространяется на весь
спецификационный файл, т.е. они доступны как в операторах
действий, так и в процедурах, находящихся в секции программ.
Строки-директивы начинаются символом "%" (этот символ в
yacc играет роль своего рода esc-символа). Две специальные
директивы
- 12 -
%{
и
%}
ограничивают с двух сторон группы строк исходного текста.
Остальные директивы служат для задания дополнительной инфор-
мации о грамматике.
5. Декларация имен лексем
%token <список_имен_лексем>
Пользователь при описании грамматики решает, какие
конструкции целесообразнее непосредственно выделять из вход-
ного текста на этапе лексического анализа, и на уровне этих
конструкций (лексем) задает грамматические правила. Все виды
лексем, кроме литералов, обозначаются некоторыми именами и
под этими именами фигурируют в секции правил. Благодаря дек-
ларации имен лексем в директиве %token yacc отличает имена
лексем от имен нетерминальных символов. Однако, декларация
ни в коей мере не обеспечивает распознавания лексем, и поль-
зователю рекомендуется считать для себя директиву %token
напоминанием о необходимости построения лексического анали-
затора (разд.4.4) и руководствоваться этой директивой при
его написании. Пример декларации имен лексем:
%token IDENT CONST ЗНАК IF THEN GOTO
Заметим, что ключевые слова описываемого входного языка
часто бывает удобно считать лексемами. Имена лексем могут
совпадать с этими ключевыми словами, недопустимым является
лишь совпадение имен лексем с зарезервированными словами
языка Си. В примере во избежание недоразумений для имен лек-
сем использованы прописные буквы.
6. Декларация приоритетов и ассоциативности лексем
%left <список_лексем>
%right <список_лексем>
%nonassoc <список_лексем>
Лексемы в данных директивах задаются литералами или
именами. В последнем случае декларация приоритета заменяет
также декларацию имени лексемы, хотя в целях обеспечения
наглядности описания является желательным присутствие в
- 13 -
списке директивы %token всего набора имен лексем.
Содержательный смысл декларации приоритетов и ассоциа-
тивности выясняется в разделе 5 в связи с вопросом о разре-
шении конфликтов грамматического разбора. Использование
лексемы само по себе не требует задания ее приоритета или
ассоциативности.
При первом появлении лексемы или литерала в секции дек-
лараций за каждым из них может следовать неотрицательное
целое число, рассматриваемое как номер типа лексемы. По
умолчанию номера типов всех лексеМ определяются yacc следую-
щим образом:
- для литерала номером типа лексемы считается числовое
значение данного литерального символа, рассматриваемого
как однобайтовое целое число;
- лексемы,обозначенные именами, в соответствии с очеред-
ностью их объявления получают последовательные номера,
начиная с 257;
- специальная лексема error, зарезервированная для обра-
ботки ошибок (раздел 7), получает номер типа 256.
Для каждого имени лексемы независимо от того, переопре-
делен ли ее номер пользователем, yacc генерирует в выходном
файле y.tab.c оператор макропрепроцессора
#define <имя_лексемы> <номер_типа>
В случае переопределения номера типа литеральной лек-
семы также формируется оператор #define, например, директива
%left 'z' 258
породит оператор
#define z 258
Заметим, что возможно переопределение номеров лишь для
буквенных литералов.
При вызове yacc с флагом -d последовательность операто-
ров #define помещается также в информационный файл y.tab.h.
Переопределив при необходимости ряд номеров типов
лексем,пользователь должен проверить уникальность номеров у
всех используемых лексем.
- 14 -