
- •Министерство образования и науки рф
- •Основы построения трансляторов Курс лекций по дисциплине «Системное программное обеспечение» Красноярск 2010 г.
- •1. Место трансляторов в системном программном обеспечении. Основные фазы процесса трансляции
- •Генерация промежуточного представления
- •Генерация кода
- •Контрольные вопросы
- •2. Базовые понятия теории формальных языков и грамматик
- •2.1. Алфавиты, цепочки и языки. Основные понятия и определения
- •2.2. Представление языков
- •2.3. Грамматики
- •2.3.1. Формальное определение грамматики
- •2.3.2. Классификация грамматик и языков по Хомскому
- •2.3.3. Разбор цепочек
- •2.3.4. Преобразования грамматик
- •2.4. Задачи
- •3. Лексический анализ
- •Описание модельного языка
- •3.1. Сущность и задачи лексического анализа
- •3.2. Способы организации таблиц идентификаторов
- •Организация таблицы идентификаторов в виде неупорядоченного массива записей. Метод линейного поиска.
- •Организация таблицы идентификаторов в виде упорядоченного массива записей. Метод бинарного поиска.
- •Использование бинарного дерева поиска для построения таблицы идентификаторов.
- •Построение таблиц идентификаторов с использованием методов хеширования.
- •3.3. Методы и средства лексического анализа
- •3.4. Недетерминированный разбор
- •3.5 Разработка лексического анализатора для модельного языка Описание модельного паскалеподобного языка (м-языка):
- •Контрольные вопросы
- •4. Синтаксический и семантический анализ
- •4.1. Задачи и методы синтаксического анализа
- •4.2 Сущность метода рекурсивного спуска
- •Void error(); / функция обработки ошибок /
- •4.3. Условия применимости метода рекурсивного спуска
- •4.4. Синтаксический анализатор для м-языка
- •4.5. Семантический анализ
- •4.6. Семантический анализатор для м-языка
- •4.6.1. Обработка описаний
- •Int declare; / описан ? 1-"да", 0-"нет" /
- •Void ipush (int I); / значение I - в стек /
- •Int ipop (void); / из стека - целое /
- •4.6.2. Контроль контекстных условий в выражении
- •Void spush (char s); / значение s - в стек /
- •If (tid [I].Declare) / описан? /
- •4.6.3. Контроль контекстных условий в операторах
- •4.7. Задачи
- •5. Генерация внутреннего представления программ
- •5.1. Язык внутреннего представления программы
- •5.2 Синтаксически управляемый перевод
- •5.3 Генератор внутреннего представления программы на м-языке
- •5.4 Интерпретатор полиЗа для модельного языка
- •5.5 Задачи
- •Литература
2.3.3. Разбор цепочек
Цепочка принадлежит языку, порождаемому грамматикой, только в том случае, если существует ее вывод из цели этой грамматики. Процесс построения такого вывода (а, следовательно, и определения принадлежности цепочки языку) называется разбором.
С практической точки зрения наибольший интерес представляет разбор по контекстно-свободным (КС и УКС) грамматикам. Их порождающей мощности достаточно для описания большей части синтаксической структуры языков программирования, для различных подклассов КС-грамматик имеются хорошо разработанные практически приемлемые способы решения задачи разбора.
Рассмотрим основные понятия и определения, связанные с разбором по КС-грамматике.
Вывод цепочки (VT)* из S VN в КС-грамматике G = (VT, VN, P, S), называется левым (левосторонним), если в этом выводе каждая очередная сентенциальная форма получается из предыдущей путем замены самого левого нетерминала.
Вывод цепочки (VT)* из S VN в КС-грамматике G = (VT, VN, P, S), называется правым (правосторонним), если в этом выводе каждая очередная сентенциальная форма получается из предыдущей путем замены самого правого нетерминала.
В грамматике для одной и той же цепочки может быть несколько выводов, эквивалентных в том смысле, что в них в одних и тех же местах применяются одни и те же правила вывода, но в различном порядке.
Пример 2.8
Для цепочки a+b+a в грамматике
G = ({a,b}, {S,T}, {S T | T+S; T a|b}, S)
можно построить следующие выводы:
1) ST+ST+T+ST+T+Ta+T+Ta+b+Ta+b+a
2) ST+Sa+Sa+T+Sa+b+Sa+b+Ta+b+a
3) ST+ST+T+ST+T+TT+T+aT+b+aa+b+a
Здесь вывод (2) - левосторонний, вывод (3) - правосторонний, а вывод (1) не является ни левосторонним, ни правосторонним, но все эти выводы являются эквивалентными в указанном выше смысле.
Для КС-грамматик можно ввести удобное графическое представление вывода, называемое деревом вывода, причем для всех эквивалентных выводов деревья вывода совпадают.
Дерево называется деревом вывода (или деревом разбора) в КС-грамматике G = {VT, VN, P, S), если выполнены следующие условия:
1) каждая вершина дерева помечена символом из множества (VN VT ), при этом корень дерева помечен символом S; листья - символами из (VT );
2) если вершина дерева помечена символом A VN, а ее непосредственные потомки - символами a1, a2, ... , an, где каждое ai (VT VN), то A a1a2...an - правило вывода в этой грамматике;
3) если вершина дерева помечена символом A VN, а ее единственный непосредственный потомок помечен символом , то A - правило вывода в этой грамматике.
Дерево вывода в примере 2.8. для цепочки a+b+a в грамматике G представлено на рис. 2.3:
Рис. 2.3. Дерево вывода
КС-грамматика G называется неоднозначной, если существует хотя бы одна цепочка L(G), для которой может быть построено два или более различных деревьев вывода.
Это утверждение эквивалентно тому, что цепочка имеет два или более разных левосторонних (или правосторонних) выводов.
В противном случае грамматика называется однозначной.
Пример 2.9
Грамматика G = ({if, then, else, a, b}, {S}, P, S),
где P = {S if b then S else S | if b then S | a} является неоднозначной, так как в этой грамматике для цепочки if b then if b then a else a можно построить два дерева вывода.
Язык, порождаемый грамматикой, называется неоднозначным, если он не может быть порожден никакой однозначной грамматикой.
Если грамматика G – неоднозначна, это не означает, что язык L(G), порождаемый этой грамматикой, обязательно неоднозначный. Определенная нами неоднозначность - это свойство грамматики, а не языка, то есть для некоторых неоднозначных грамматик существуют эквивалентные им однозначные грамматики. Если грамматика используется для определения языка программирования, то она должна быть однозначной. В примере 2.9 разные деревья вывода предполагают соответствие else разным then. Если договориться, что else должно соответствовать ближайшему к нему then, и подправить грамматику G, то неоднозначность будет устранена:
S if b then S | if b then S’ else S | a
S’ if b then S’ else S’ | a
Проблема, порождает ли данная неоднозначная КС-грамматика однозначный язык (то есть, существует ли эквивалентная ей однозначная грамматика), является алгоритмически неразрешимой.
Однако можно указать некоторые виды правил вывода, которые приводят к неоднозначности:
A AA |
A AA |
A A | A |
A A | AA |
Пример 2.10
Язык L = {ai bj ck | i = j или j = k} является неоднозначным КС-языком.
Интуитивно это объясняется тем, что цепочки с i=j должны порождаться группой правил вывода, отличных от правил, порождающих цепочки с j=k. Но тогда, по крайней мере, некоторые из цепочек с i=j=k будут порождаться обеими группами правил и, следовательно, будут иметь по два разных дерева вывода. Доказательство того, что КС-язык L является неоднозначным, приведено в [3, стр. 235-236].
Одна из грамматик, порождающих L, такова:
G=({a, b, c}, {A, B, C, D, S}, Р, S), где
Р={ S AB | DC, A aA | B bBc | C cC | D aDb | }
Очевидно, что она неоднозначна.
Дерево вывода можно строить нисходящим либо восходящим способом.
При нисходящем разборе дерево вывода формируется от корня к листьям: на каждом шаге для вершины, помеченной нетерминальным символом, пытаются найти такое правило вывода, чтобы имеющиеся в нем терминальные символы “проектировались” на символы исходной цепочки.
Метод восходящего разбора заключается в том, что исходную цепочку пытаются “свернуть” к начальному символу S: на каждом шаге ищут подцепочку, которая совпадает с правой частью какого-либо правила вывода; если такая подцепочка находится, то она заменяется нетерминалом из левой части этого правила.
Если грамматика однозначная, то при любом способе построения будет получено одно и то же дерево разбора.