Операционная система UNIX. Руководство программиста

     

ОСНОВНЫЕ СПЕЦИФИКАЦИИ


Имена обозначают лексемы или нетерминальные символы. yacc требует, чтобы имена лексем были указаны явно. Хотя лексический анализатор можно включить в файл спецификаций, определение его в отдельном файле, вероятно, более соответствует принципам модульного проектирования. Подобно лексическому анализатору, в файл спецификаций могут быть также включены и другие подпрограммы. Таким образом, каждый файл спецификаций теоретически состоит из трех секций: определений, (грамматических) правил и подпрограмм. Секции отделяются двумя знаками процента %% (знак % используется в yacc-спецификациях как универсальный управляющий).

Если используются все секции, полный файл спецификаций выглядит следующим образом:

определения

%% правила

%% подпрограммы

Секции определений и подпрограмм являются необязательными. Минимальная допустимая yacc-спецификация - это

%% правила

Пробелы, табуляции и переводы строки, которые встречаются вне имен и зарезервированных слов, игнорируются. Комментарии могут быть везде, где допустимо имя. Они заключаются в "скобки" /*...*/, как в языке C.

Секция правил составляется из одного или большего числа грамматических правил. Грамматическое правило имеет вид:

нтс : тело ;

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

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

Литерал - это знак, заключенный в одиночные кавычки, '. Как и в языке C, в качестве управляющего используется знак \, восприни-маются также все принятые в C управляющие последовательности. Например, yacc трактует перечисленные ниже последовательности следующим образом:



'\n' перевод строки

'\r' возврат каретки

'\'' одинарная кавычка ' '\\' обратная наклонная черта \ '\t' табуляция


'\b' забой

'\f' переход к новой странице

'\xxx' xxx в восьмеричной записи

По ряду технических причин символ NULL (\0 или 0) нельзя использовать в грамматических правилах.

Если есть несколько грамматических правил с одной и той же левой частью, то, чтобы избежать переписывания левой части, можно использовать вертикальную черту, |. Перед вертикальной чертой точку с запятой ставить не нужно. Например, грамматические правила

A : B C D ; A : E F ; A : G ;

с использованием вертикальной черты могут быть заданы для yacc'а в виде

A : B C D | E F | G ;

Не обязательно, чтобы грамматические правила с одной и той же левой частью появлялись в секции правил все вместе, однако такая запись облегчает чтение спецификации и ее модификацию.

Если нетерминал сопоставляется с пустой цепочкой, это можно выразить следующим образом:

epsilon : ;

yacc истолковывает пустое место после двоеточия как нетерминальный символ, называемый epsilon.

Имена, представляющие лексемы, должны быть описаны. Проще всего это сделать, поместив в секции определений конструкцию вида

%token имя1 имя2 ...

Считается, что всякое имя, не описанное в секции определений, представляет нетерминальный символ. Каждый нетерминальный символ должен встретиться в левой части по крайней мере одного правила.

Из всех нетерминальных символов особую роль играет начальный символ. По умолчанию начальным считается символ, стоящий в левой части первого грамматического правила в секции правил. Можно (и желательно) явно объявить начальный символ в секции определений при помощи ключевого слова %start:

%start начальный_символ

О конце входного текста процедуре разбора сигнализирует специальная лексема, называемая маркером конца. Маркер конца представляется нулем или отрицательным числом. Если прочитанные лексемы, исключая маркер конца, образуют конструкцию, сопоставляющуюся с начальным символом, то после того, как найден маркер конца и исходный текст принят, процедура разбора возвращает управление вызвавшей ее процедуре. Если маркер конца встречается в любом другом контексте, это ошибка.

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




Содержание раздела