- •Содержание
- •1.Рабочая программа
- •2.Модуль Вводный
- •3.Модуль Формальные грамматики и языки
- •3.1.Языки и цепочки символов. Способы задания языков
- •3.1.1.Цепочки символов. Операции над цепочками символов
- •3.1.2.Понятие языка. Формальное определение языка
- •3.1.3.Способы задания языков
- •3.1.4.Синтаксис и семантика языка
- •3.2.Определение грамматики
- •3.2.1.Особенности языков программирования
- •3.2.2.Определение грамматики. Форма Бэкуса—Наура
- •3.2.3.Принцип рекурсии в правилах грамматики
- •3.2.4.Другие способы задания грамматик
- •3.3.Классификация языков и грамматик
- •3.3.1.Классификация грамматик
- •3.3.2.Классификация языков
- •3.4.Контроль
- •4.Модуль Распознаватели, механизм вывода цепочек символов
- •4.1.Цепочки вывода. Сентенциальная форма.
- •4.1.1.Сентенциальная форма грамматики. Язык, заданный грамматикой
- •4.1.2.Левосторонний и правосторонний выводы
- •4.1.3.Однозначные и неоднозначные грамматики
- •4.1.4.Эквивалентность и преобразование грамматик
- •4.2.Распознаватели. Задача разбора
- •4.2.1.Общая схема распознавателя
- •4.2.2.Виды распознавателей
- •4.2.3.Классификация распознавателей по типам языков
- •4.3.Контроль
- •5.Модуль Регулярные грамматики и языки
- •5.1.Регулярные языки и грамматики
- •5.2.Леволинейные и праволинейные грамматики. Автоматные грамматики
- •5.3.Алгоритм преобразования регулярной грамматики к автоматному виду
- •5.4.Конечные автоматы
- •5.4.1.Определение конечного автомата
- •5.4.2.Детерминированные и недетерминированные конечные автоматы
- •5.4.3.Преобразование конечного автомата к детерминированному виду
- •5.5.Контроль
- •6.Модуль Контекстно-свободные грамматики и языки
- •6.1.Контекстно-свободные языки
- •6.1.1.Распознаватели кс-языков. Автоматы с магазинной памятью. Определение мп-автомата
- •6.2.Классы кс-языков и грамматик. Класс ll(k) грамматик.
- •6.3.Принципы построения распознавателей для ll(k)-грамматик
- •6.4.Левая факторизация
- •6.5.Удаление левой рекурсии
- •6.6.Алгоритм разбора для ll(1)-грамматик
- •6.7.Алгоритм построения множества first(1,a)
- •6.8.Алгоритм построения множества follow(1,a)
- •6.9.Восходящие распознаватели кс-языков без возвратов
- •6.9.1.Определение lr(k)-грамматики
- •6.10.Принципы построения распознавателей для lr(k)-грамматик
- •6.10.1.Грамматики простого предшествования
- •6.11.Распознаватели для lr(0) и lr(1) грамматик
- •6.11.1.Распознаватель для lr(0)-грамматики
- •6.11.2.Распознаватель для lr(1) грамматики
- •6.12.Контроль
- •7.Модуль Инструментальные средства для построения трансляторов
- •7.1.Инструментальные средства для построения компиляторов
- •7.1.1.Построитель лексических анализаторов Lex
- •7.2.Контроль
- •8.Модуль Особенности программирование трансляторов
- •8.1.Использование значений произвольных типов, алгоритм разбора
- •8.1.1.Алгоритм синтаксического разбора
- •8.1.2.Семантический стек
- •8.2.Неоднозначности и конфликты
- •8.3.Старшинство операций
- •8.4.Дополнительные возможности программ yacc и lex
- •8.4.1.Обработка ошибок
- •8.5.Совместное использование lex и yacc
- •8.5.1.Кодировка лексем и интерфейс
- •8.5.2.Сборка yacc-программ
- •8.6.Советы по подготовке спецификаций
- •8.6.1.Стиль
- •8.6.2.Использование левой рекурсии
- •8.6.3.Уловки анализа лексики
- •8.6.4.Входной синтаксис yacc'а
- •8.7.Контроль
- •9.Модуль Заключение
- •10.Обеспечение лабораторного практикума
- •11.Дополнительная информация. Примеры
- •11.4.Пример простейшего интерпретатора формул
- •11.5.Простой пример
- •11.6.Более сложный пример
- •11.7.Генераторы лексических и синтаксических анализаторов
- •11.8.Генераторы лексических и синтаксических анализаторов на java
- •11.9.Пакеты для разработки компиляторов
- •Список сокращений
- •Литература
- •Приложения Приложение 1. Учебно–методическая карта дисциплины “Системное программное обеспечение. Синтаксические анализаторы”
- •Приложение 2. Вопросы для зачета по дисциплине “Системное программное обеспечение. Синтаксические анализаторы”
- •Приложение 3. Методические указания к лабораторным работам по дисциплине «Системное программное обеспечение. Синтаксические анализаторы»
- •Порядок выполнения работы:
- •Контрольные вопросы
- •Лексический анализатор lex. Анализ структуры программ
- •Краткая теория:
- •Рассмотрим примеры:
- •Краткая теория:
- •Порядок выполнения работы:
- •Контрольные вопросы
- •Лексический анализатор lex, синтаксический анализатор yacc. Алгебраические вычисления
- •Порядок выполнения работы:
- •Контрольные вопросы
- •Лексический анализатор lex и синтаксический анализатор yacc. Изображение геометрических фигур
- •Краткая теория:
- •Создание метафайла и работа сним
- •Порядок выполнения работы:
- •Контрольные вопросы
- •Приложение 4. Организация рейтингового контроля по дисциплине «Системное программное обеспечение. Синтаксические анализаторы»
8.4.Дополнительные возможности программ yacc и lex
8.4.1.Обработка ошибок
Обработка ошибок - это чрезвычайно сложная область; многие связанные с ней проблемы являются семантическими. Когда ошибка найдена, может потребоваться, например, очистить память, в которой хранилось дерево разбора, удалить или изменить содержимое таблицы символов и (или), чаще всего, установить переключатели, препятствующие дальнейшему формированию выходных данных.
Далеко не всегда приемлемо при обнаружении ошибки вообще прекратить обработку. Полезнее продолжить сканирование исходного текста для того, чтобы обнаружить и другие синтаксические ошибки. При этом возникает проблема нейтрализации ошибки и возобновления разбора. Широкий класс алгоритмов нейтрализации достигает цели, пропуская несколько лексем во входной цепочке и пытаясь найти состояние, в котором можно возобновить разбор исходного текста.
Чтобы позволить пользователю как-то управлять данным процессом, в yacc'е зарезервирована лексема с именем error. Это имя можно использовать в грамматических правилах. Оно используется для указания мест, где ожидаются ошибки и может потребоваться их нейтрализация. Алгоритм разбора очищает стек, пока не окажется в состоянии, в котором допустима лексема error. Затем он поступает так, будто лексема error является текущей предварительно просмотренной, и выполняет действие, оказавшееся текущим. Предварительно просмотренная лексема затем устанавливается равной лексеме, которая вызвала ошибку. Если специальных "ошибочных" правил не задано, после того, как ошибка обнаружена, обработка прекращается.
Чтобы предотвратить каскад сообщений об ошибках, алгоритм разбора после их обнаружения остается в некорректном состоянии, пока успешно не прочитаны и не обработаны три лексемы. Если ошибка обнаруживается, когда разбор уже находится в некорректном состоянии, сообщение не выдается, и входная лексема молча отбрасывается.
Например, правило вида
stat : error
означает, что при синтаксической ошибке алгоритм разбора пытается перескочить оператор, в котором встретилась ошибка. Более точно, алгоритм продолжает сканирование, обнаруживает, что три лексемы за оператором могут оказаться допустимыми, и начинает обработку с первой из них. Если начало операторов недостаточно отчетливо выделяется, алгоритм может по ошибке стартовать с середины оператора и закончиться обнаружением второй ошибки, на самом деле не существовавшей.
Со специальными "ошибочными" правилами такого вида могут быть ассоциированы действия, которые могут пытаться заново инициализировать таблицы и т.д.
Такие правила, как предыдущее, универсальны, но ими трудно управлять. Правила, подобные
stat : error ';'
несколько удобнее. Здесь, когда возникает ошибка, алгоритм пытается перескочить оператор, переходя на следующую точку с запятой. Все лексемы после ошибочной и до следующей точки с запятой пропускаются. После того как точка с запятой найдена, для данного правила делается свертка и выполняется связанное с ним действие по нейтрализации ошибки.
Еще одна форма error правила возникает в интерактивных приложениях, где может потребоваться разрешить после ошибки перенабрать строку. Пример
input : error '\n'
{
printf ("Перенаберите последнюю строку: ");
}
input
{
$$ = $4;
}
;
показывает, как это можно сделать. Такой подход имеет, однако, и недостатки. Алгоритм должен корректно обработать три входные лексемы перед тем, как вернется в корректное состояние. Если перенабранная строка содержит ошибки в первых двух лексемах, алгоритм молча удалит их, что, конечно, неприемлемо. Имеется механизм, который принуждает алгоритм разбора завершить нейтрализацию ошибок. Включенный в действие оператор
yyerrok ;
возвращает алгоритм в нормальное состояние. Последний пример можно переписать в виде:
input : error '\n'
{
yyerrok;
printf ("Перенаберите последнюю строку: ");
}
input
{
$$ = $4;
}
;
Как упоминалось выше, сразу после символа error предварительно просмотренная лексема равна входной лексеме, на которой была обнаружена ошибка. Иногда это неуместно; задачу выбора корректного места для возобновления разбора может взять на себя действие, соответствующее правилу, содержащему error. В этом случае предыдущая предварительно просмотренная лексема должна быть очищена. Оператор
yyclearin ;
помещенный в действие, даст желаемый результат. Предположим, например, что действие после error должно вызывать некоторую замысловатую процедуру нейтрализации (определенную пользователем), пытающуюся возобновить разбор с начала следующего корректного оператора. Предполагается, что после того, как вызвана данная процедура, следующая лексема, возвращаемая yylex() – это первая лексема в корректном операторе. Старая недопустимая лексема должна быть отброшена и установлено состояние error. К цели ведет правило, подобное следующему:
stat : error
{
resynch ();
yyerrok;
yyclearin;
}
;
Продемонстрированные методы, возможно, грубоваты, но позволяют просто и довольно эффективно нейтрализовывать большинство ошибок. Более того, пользователь может управлять теми действиями, по обработке ошибок которых требуют другие фрагменты программы.
