
- •Содержание
- •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.3.Старшинство операций
Есть ситуация, в которой приведенные выше методы разрешения конфликтов не подходят. Имеется в виду разбор арифметических выражений. Большинство конструкций, обычно используемых в арифметических выражениях, можно естественным образом описать при помощи понятия уровней старшинства (приоритетов) операций и информации о левой или правой ассоциативности. Применяя данный механизм, можно использовать неоднозначные грамматики с соответствующими правилами разрешения неоднозначностей для порождения алгоритмов разбора, которые быстрее и легче задавать, чем алгоритмы, построенные из однозначных грамматик. Основная идея заключается в том, чтобы записать грамматические правила для всех требуемых бинарных и унарных операций в виде:
expr : expr OP expr
или
expr : UNARY expr
В результате получается неоднозначная грамматика с очень большим числом конфликтов. В качестве метода разрешения неоднозначностей пользователь специфицирует приоритеты (степень связывания) всех операций и ассоциативность бинарных операций. Этой информации достаточно, чтобы дать возможность yacc'у разрешить конфликты и построить алгоритм разбора, реализующий заданные приоритеты и ассоциативности.
Приоритеты и ассоциативности связываются с лексемами в секции определений. Это делается в группе строк, начинающихся с ключевых слов yacc'а %left, %right или %nonassoc, за которыми следуют списки лексем. Считается, что все лексемы в одной строке имеют одни и те же приоритет и ассоциативность; строки указываются в порядке возрастания приоритета. Так, строки
%left '+' '-'
%left '*' '/'
задают приоритет и ассоциативность четырех арифметических операций. '+' и '-' левоассоциативны и имеют меньший приоритет, чем также левоассоциативные '*' и '/'. Для описания правоассоциативных операций используется ключевое слово %right, а для описания операций, подобных операции .LT. в Фортране, которые не являются ассоциативными, - ключевое слово %nonassoc. Например, выражение
A .LT. B .LT. C
некорректно в Фортране; поэтому такую операцию следует описать в yacc при помощи ключевого слова %nonassoc. Действие названных ключевых слов иллюстрирует спецификация
%right '='
%left '+' '-'
%left '*' '/'
%%
expr : expr '=' expr
| expr '+' expr
| expr '-' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| NAME
;
Ее можно использовать, чтобы входную цепочку
a = b = c * d - e - f * g
структурировать следующим образом:
a = (b = (((c * d) - e) - (f * g)))
что соответствует истинным приоритетам операций. При использовании данного механизма должен быть, вообще говоря, задан приоритет унарных операций. Иногда унарная и бинарная операции имеют одно и то же внешнее представление, но различные приоритеты. Примером является унарный и бинарный минус, -.
Унарному минусу можно придать тот же приоритет, что и умножению, или даже выше, в то время как у бинарного минуса приоритет меньше, чем у умножения. Ключевое слово %prec изменяет приоритет операции в пределах одного грамматического правила. Ключевое слово %prec указывается сразу за телом правила, перед действием или завершающей точкой с запятой; за ключевым словом следует имя лексемы или литерал. В результате приоритет правила становится таким же, как и у данной лексемы или литерала. Например, правила
%left '+' '-'
%left '*' '/'
%%
expr : expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| '-' expr %prec '*'
| NAME
;
можно использовать, чтобы установить унарному минусу тот же приоритет, что и у умножения. Лексему, описанную при помощи конструкций %left, %right или %nonassoc, можно (но не обязательно) описать и при помощи %token.
Приоритеты и ассоциативность yacc использует для того, чтобы разрешить конфликты разбора. Они задают следующие методы разрешения неоднозначностей:
Приоритеты и ассоциативность приписываются тем лексемам и литералам, для которых они заданы явно.
Грамматическому правилу сопоставляются приоритет и ассоциативность последней лексемы или литерала в теле правила. В случае использования конструкции %prec это сопоставление переопределяется. Некоторым правилам приоритет и ассоциативность могут не сопоставляться.
Если есть конфликт свертка-свертка или конфликт свертка-перенос, и входной символ или грамматическое правило не имеют приоритета и ассоциативности, то используется общий метод разрешения неоднозначностей, приведенный в начале раздела, и выдается информация о конфликтах.
Если есть конфликт свертка-перенос и как грамматическому правилу, так и входному символу сопоставлен приоритет и ассоциативность, то конфликт разрешается в пользу той операции перенос или свертка, которой соответствует больший приоритет. Если приоритеты равны, используется информация об ассоциативности. Левая ассоциативность обозначает свертку, правая - перенос, неассоциативность - ошибку.
Конфликты, разрешенные при помощи приведенного метода, не учитываются при подсчете сообщаемого yacc'ом числа конфликтов перенос-свертка и свертка-свертка. Это означает, что ошибки в спецификации приоритетов могут замаскировать ошибки во входной грамматике. Хорошо было бы воздерживаться от задания приоритетов или использовать их весьма осторожно, пока не приобретен определенный опыт. Чтобы убедиться, что получен именно тот алгоритм разбора, который требуется, следует изучить содержимое файла y.output.