
- •Теория вычислительных процессов и структур
- •1. Предварительные математические сведения
- •1.2. Операции над множествами Объединение множеств
- •Пересечение множеств
- •Разность множеств
- •1.3. Множества цепочек
- •1.4. Языки
- •1.5. Алгоритмы
- •1.6. Некоторые понятия теории графов
- •2. Введение в компиляцию
- •2.1. Задание языков программирования
- •2.2. Синтаксис и семантика
- •2.3. Процесс компиляции
- •2.4. Лексический анализ
- •2.5. Работа с таблицами
- •2.6. Синтаксический анализ
- •2.7. Генератор кода
- •Алгоритм.
- •2.8. Оптимизация кода
- •2.9. Исправление ошибок
- •2.10. Резюме
- •3. Теория языков
- •3.1. Способы определения языков
- •3.2. Грамматики
- •Пример.
- •3.3. Грамматики с ограничениями на правила
- •3.4. Распознаватели
- •3.5. Регулярные множества, их распознавание
- •3.6. Регулярные множества и конечные автоматы
- •3.7. Графическое представление конечных автоматов
- •3.8. Конечные автоматы и регулярные множества
- •3.9. Минимизация конечных автоматов
- •3.10. Контекстно-свободные языки
- •3.10.1. Деревья выводов
- •3.10.2. Преобразование кс–грамматик
- •3.10.3. Грамматика без циклов
- •3.10.4. Нормальная форма Хомского
- •3.10.5. Нормальная формула Грейбах
- •3.11. Автоматы с магазинной памятью
- •3.11.1. Основные определения
- •3.11.2. Эквивалентность мп-автоматов и кс-грамматик
- •4.1. Эквивалентность мп-автоматов и кс-грамматик
- •4.2. Ll(1)-грамматики
- •4.3. Ll(1)-таблица разбора
- •5. Синтаксический анализ снизу вверх
- •5.1. Разбор снизу вверх
- •5.2. Lr(1) - таблица разбора
- •5.3. Построение lr – таблицы разбора
- •5.4. Сравнение ll – и lr – методов разбора
- •6. Включение действий в синтаксис
- •6.1. Получение четверок
- •6.2. Работа с таблицей символов
- •7. Проектирование компиляторов
- •7.1. Число проходов
- •7.2. Таблицы символов
- •Identifier, type.
- •Int procedure rehash(int n)
- •Int procedure rehash(int n)
- •7.3. Таблица видов
- •8. Распределение памяти
- •8.1. Стек времени прогона
- •Integer a, b, X, y
- •Int table[1:10, -5:5].
- •8.2. Методы вызова параметров
- •8.3. Обстановка выполнения процедур
- •8.4. «Куча»
- •8.5. Счетчик ссылок
- •8.6. Сборка мусора
- •9. Генерация кода
- •(Тип – адреса, номер - блока, смещение).
- •9.2. Структура данных для генерации кода
- •9.3. Генерация кода для типичных конструкций
- •9.3.1. Присвоение
- •9.3.2. Условные зависимости
- •If b then c else d
- •9.3.3. Описание идентификаторов
- •9.3.4. Циклы
- •9.3.5. Вход и выход из блока
- •9.3.6. Прикладные реализации
- •9.4. Проблемы, связанные с типами
- •9.5. Время компиляции и время прогона
- •10. Исправление и диагностика ошибок
- •10.1. Типы ошибок
- •10.2. Лексические ошибки
- •10.3. Ошибки в употреблении скобок
- •Begin end
- •Case esac
- •10.4. Синтаксические ошибки
- •10.5. Методы исправления синтаксических ошибок
- •End begin
- •10.6. Предупреждения
- •10.7. Сообщения о синтаксических ошибках
- •10.8. Контекстно-зависимые ошибки
- •Identifier xyz not declared
- •Identifier blank alredy declared in block
- •10.9. Ошибки, связанные с употреблением типов
- •Int I; char c;
- •10.10. Ошибки, допускаемые во время прогона
- •10.11. Ошибки, связанные с нарушением ограничений
10.2. Лексические ошибки
Задача лексического анализатора – сгруппировать последовательность литер в символы исходного языка. При этом он работает исключительно с локальной информацией. В его распоряжении имеется небольшой объем памяти, и он не осуществляет предварительного просмотра. В тех случаях, когда лексический анализатор окажется не в состоянии сгруппировать какие-либо последовательности литер в символы (лексемы), будут возникать ошибки. Лексические ошибки можно разделить на следующие группы.
Одна из литер оказывается недействительной, т.е. она не может быть включена ни в один из символов. В таком случае лексический анализатор либо игнорирует эту литеру, либо заменяет ее какой-либо другой.
При попытке собрать выделенное слово языка выясняется, что последовательность букв не соответствует ни одному из этих слов. В этом случае можно воспользоваться алгоритмом подбора слова, чтобы идентифицировать слово, имеющее несколько другое написание. Например, realabпредставить какreal ab.
Собирая числа, лексический анализатор может испытывать затруднения с последовательностью вида 42.34.41. Возможное решение здесь – допустить, какая бы ошибка не была, что предполагалось одно число, и предупредить программиста, что вместо этого числа принято конкретное число по умолчанию.
Отсутствие в программе какой-либо литеры приводит к тому, что лексический анализатор не может отделить один символ от другого. Например, если в А+Впропущен знак «+», то лексический анализатор просто пропустит идентификаторАВ, не оповещая об ошибке на этой стадии. Однако отсутствие знака «+» в 1+А вызовет ошибку, хотя лексический анализатор не будет знать, к какой группе ошибок отнести 1А– к недопустимым идентификаторам или еще чему-либо.
Обычно проблему для лексического анализатора создают недостающие кавычки строки символов
string food=”BREFD
Следовательно, в остальной части программы открывающие и закрывающие кавычки могут быть перепутаны. В результате обрушится лавина сообщений об ошибках. «Смышленый» анализатор смог бы обнаружить неправдоподобную последовательность литер внутри кавычек (например, end) и исправить ошибку, поставив в нужном месте кавычки.
Многие компиляторы завершают свою работу тем проходом, где обнаружена ошибка. Однако современная тенденция построения компиляторов базируется на принципе обнаружения максимального числа ошибок. Таким образом желательно, чтобы компилятор продвинулся в своей работе как можно дальше. Поэтому лексический анализатор должен передать следующему проходу (фазе) последовательность действительных символов (а необязательно действительную последовательность символов). Для правильных в лексическом смысле программ это не представляет трудностей. При лексически неправильных программах приходится или игнорировать последовательность символов, или включать дополнительные. Может потребоваться изменить написание символов, разбить строки на действительные символы. Игнорировать последовательность литер - самое простое средство, но оно практически всегда приводит к возникновению синтаксических ошибок. Методы исправления лексическим анализатором недопустимых входов зависят от обстоятельств, и на практике их выбор определяется компилируемым языком.