next up previous contents
Next: Действия Up: YACC - еще один Previous: Введение   Contents

Входные спецификации

Имена относятся либо к токенам, либо к нетерминалам. Компилятор Yacc требует, чтобы все токены были специально описаны, часто желательно, чтобы лексический анализатор был включен в файл входных спецификаций. Впрочем и другие подпрограммы туда тоже можно включать. Таким образом, файл входных спецификаций состоит из трех секций: объявлений (declarations); грамматики (правил/rules); программ (подпрограмм).

Секции отделяются друг от друга двойным процентом (%%). (Процент вообще используется Yaccом как специальный символ). Другими словами, файл входных спецификаций выглядит так:

declarations (объявления) %% rules (правила) %% programs (программы) Секция объявлений может быть пустой, кроме того, если пуста секция программ, можно опустить и второй разделитель (%%). Таким образом, самая короткая спецификация может выглядеть так:

%% rules Пробелы, табуляции и возвраты каретки игнорируются, но не должны появляться в именах и зарезервированых символах. Везде, где может стоять имя, может быть и комментарий (как в Си):

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

A : BODY ; здесь A - имя нетерминала, а BODY представляет собой последовательность из нуля или более имен и литералов. Двоеточие и точка с запятой - символы пунктуации Yacca. Имена могут быть произвольной длины и состоять из букв, точек, подчеркиваний и цифр, но не должны начинаться с цифры. Прописные и строчные буквы различаются. Имена, использованые в теле правила, могут быть именами токенов или нетерминалов. Литерал - это символ, заключенный в одиночные кавычки. Как и в Си бакслэш (\) является спецсимволом, а все Си-шные спецпоследовательности типа n и t воспринимаются.

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

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

A : B C D ; A : E F ; A : G ; могут быть записаны так:

A : B C D | E F | G ; или даже так:

A : B C D ; | E F ; | G ; Не обязательно, чтобы правила с одинаковой левой частью были написаны вместе (или рядом), но такая запись делает их более читаемыми и легкими для изменения. Если нетерминалу соответствует пустая строка, он может быть записан так:

empty : ; Имена токенов должны быть объявлены, что проще всего сделать, написав: %token name1 name2 . . . в секции объявлений.

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

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

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



2004-06-22