Давайте создадим компилятор!
Добавить в закладки К обложке
- Введение - Страница 1
- Основа - Страница 3
- Синтаксический анализ выражений - Страница 4
- Одиночные цифры - Страница 5
- Выражения с двумя цифрами - Страница 6
- Общая форма выражения - Страница 8
- Использование стека - Страница 9
- Умножение и деление - Страница 10
- Круглые скобки - Страница 11
- Унарный минус - Страница 12
- Слово об оптимизации - Страница 13
- Снова выражения - Страница 15
- Переменные - Страница 16
- Функции - Страница 17
- Подробнее об обработке ошибок - Страница 18
- Присваивание - Страница 19
- Многосимвольные токены - Страница 20
- Пробелы - Страница 21
- Интерпретаторы - Страница 23
- Интерпретатор - Страница 25
- Немного философии - Страница 27
- Управляющие конструкции - Страница 30
- План - Страница 31
- Немного основ - Страница 32
- Оператор IF - Страница 34
- Оператор WHILE - Страница 35
- Оператор LOOP - Страница 36
- Цикл FOR - Страница 37
- Оператор DO - Страница 38
- Оператор BREAK - Страница 39
- Заключение - Страница 41
- Булевы выражения - Страница 43
- План - Страница 44
- Грамматика - Страница 45
- Операторы отношений - Страница 46
- Исправление грамматики - Страница 47
- Синтаксический анализатор - Страница 48
- Объединение с управляющими конструкциями - Страница 52
- Добавление присваиваний - Страница 53
- Лексический анализ - Страница 54
- Лексический анализ - Страница 55
- Конечные автоматы и альтернативы - Страница 56
- Эксперименты по сканированию - Страница 57
- Пробел - Страница 58
- Конечные автоматы - Страница 59
- Новые строки - Страница 60
- Операторы - Страница 61
- Списки, запятые и командные строки - Страница 62
- Становится интересней - Страница 63
- Возвращение символа - Страница 65
- Распределенные сканеры против централизованных - Страница 66
- Объединение сканера и парсера - Страница 67
- Заключение - Страница 72
- Немного философии - Страница 73
- Дорога домой - Страница 74
- Почему это так просто? - Страница 76
- Здесь нет ничего сложного! - Страница 77
- Заключение - Страница 80
- Вид сверху - Страница 81
- Верхний уровень - Страница 82
- Структура Паскаля - Страница 83
- Расширение - Страница 84
- Объявления - Страница 85
- Структура Си - Страница 87
- Представление «TINY» - Страница 90
- Подготовка - Страница 91
- Объявления - Страница 93
- Объявления и идентификаторы - Страница 94
- Инициализаторы - Страница 95
- Таблица идентификаторов - Страница 96
- Выполнимые утверждения - Страница 97
- Булева логика - Страница 99
- Управляющие структуры - Страница 101
- Лексический анализ - Страница 103
- Многосимвольные имена переменных - Страница 105
- Снова операторы отношений - Страница 106
- Ввод/Вывод - Страница 107
- Заключение - Страница 108
- Пересмотр лексического анализа - Страница 113
- Предпосылка - Страница 114
- Проблема - Страница 115
- Решение - Страница 116
- Исправление компилятора - Страница 118
- Заключение - Страница 119
- Разное - Страница 124
- Точки с запятой - Страница 125
- Синтаксический сахар - Страница 126
- Работа с точками с запятой - Страница 127
- Компромисс - Страница 128
- Комментарии - Страница 129
- Односимвольные разделители - Страница 130
- Многосимвольные разделители - Страница 132
- Односторонние комментарии - Страница 133
- Заключение - Страница 134
- Процедуры - Страница 135
- Последнее отклонение - Страница 136
- Основы - Страница 137
- Основа для экспериментов - Страница 138
- Объявление процедуры - Страница 140
- Вызов процедуры - Страница 142
- Передача параметров - Страница 143
- Семантика параметров - Страница 145
- Передача по значению - Страница 147
- Что неправильно? - Страница 149
- Передача по ссылке - Страница 151
- Локальные переменные - Страница 152
- Заключение - Страница 154
- Типы - Страница 155
- Что будет дальше? - Страница 156
- Таблица идентификаторов - Страница 157
- Добавление записей - Страница 159
- Распределение памяти - Страница 160
- Объявление типов - Страница 161
- Присваивания - Страница 162
- Трусливый выход - Страница 164
- Более приемлемое решение - Страница 165
- Литеральные аргументы - Страница 167
- Аддитивные выражения - Страница 168
- Почему так много процедур? - Страница 170
- Мультипликативные выражения - Страница 171
- Умножение - Страница 172
- Деление - Страница 173
- Завершение - Страница 174
- Приводить или не приводить - Страница 175
- Заключение - Страница 177
- Назад в будущее - Страница 178
- Новое начало, старое направление - Страница 179
- Начинаем заново? - Страница 181
- Модуль INPUT - Страница 182
- Модуль OUTPUT - Страница 184
- Модуль ERROR - Страница 185
- Лексический и синтаксический анализ - Страница 186
- Модуль SCANNER - Страница 188
- Решения, решения - Страница 189
- Синтаксический анализ - Страница 191
- Ссылки - Страница 193
- Конструирование модулей - Страница 194
- Совсем как классический? - Страница 196
- Расширение синтаксического анализатора - Страница 198
- Термы и выражения - Страница 200
- Присваивания - Страница 202
- Булева алгебра - Страница 203
- Булево «AND» - Страница 205
{–}
{ Parse and Translate a Boolean Term }
procedure BoolTerm;
begin
NotFactor;
while Look = '&' do begin
EmitLn('MOVE D0,-(SP)');
Match('&');
NotFactor;
EmitLn('AND (SP)+,D0');
end;
end;
{–}
Теперь мы почти дома. Мы транслируем сложные булевые выражения, хотя только и для постоянных значений. Следующий шаг – учесть NOT. Напишите следующую процедуру:
{–}
{ Parse and Translate a Boolean Factor with NOT }
procedure NotFactor;
begin
if Look = '!' then begin
Match('!');
BoolFactor;
EmitLn('EOR #-1,D0');
end
else
BoolFactor;
end;
{–}
И переименуйте предыдущую процедуру в BoolFactor. Теперь испытайте компилятор. К этому времени синтаксический анализатор должен обрабатывать любое булевое выражение, которое вы позаботитесь ему подкинуть. Работает? Отлавливает ли он неправильно сформированные выражения?
Если вы следили за тем, что мы делали в синтаксическом анализаторе для математических выражений вы знаете что далее мы расширили определение показателя для включения переменных и круглых скобок. Мы не должны делать это для булевого показателя, потому что об этих маленьких вещах позаботится наш следующий шаг. Необходима только одна дополнительная строка в BoolFactor, чтобы позаботиться об отношениях:
{–}
{ Parse and Translate a Boolean Factor }
procedure BoolFactor;
begin
if IsBoolean(Look) then
if GetBoolean then
EmitLn('MOVE #-1,D0')
else
EmitLn('CLR D0')
else Relation;
end;
{–}
Вы могли бы задаться вопросом, когда я собираюсь предоставить булевские переменные и булевские выражения в скобках. Отвечаю: никогда. Помните, ранее мы убрали их из грамматики. Прямо сейчас я собираюсь кодировать грамматику, которую мы уже согласовали. Сам компилятор не может видеть разницы между булевыми переменными или выражениями и арифметическими переменными или выражениями... все это будет обрабатываться в Relation в любом случае.
Конечно, понадобится некоторый код для Relation. Однако, я не чувствую себя комфортно, добавляя еще код, не проверив сперва тот, который мы уже имеем. Так что давайте сейчас просто напишем фиктивную версию Relation, которая ничего не делает за исключением того, что съедает текущий символ и выводит небольшое сообщение:
{–}
{ Parse and Translate a Relation }
procedure Relation;
begin
WriteLn('<Relation>');
GetChar;
end;
{–}
ОК, наберите этот код и испытайте его. Все старые дела все еще должны работать... у вас должна быть возможность генерировать код для AND, OR и NOT. Кроме того, если вы наберете любой алфавитный символ, вы должны получить небольшой заменитель <Relation>, где должен быть булев показатель. Вы получили это? Отлично, тогда давайте перейдем к полной версии Relation.
Чтобы получить ее, тем не менее, сначала мы должны положить небольшое основание. Вспомните, что отношение имеет форму:
<relation> ::= | <expression> [<relop> <expression]
Так как у нас появился новый вид операторов, нам также понадобится новая логическая функция для ее распознавания. Эта функция показана ниже. Из-за ограничения в один символ, я придерживаюсь четырех операторов, которые могут быть закодированы такими символами («не равно» закодировано как "#").
{–}
{ Recognize a Relop }
function IsRelop(c: char): Boolean;
begin
IsRelop := c in ['=', '#', '<', '>'];
end;
{–}
Теперь вспомните, что мы используем нуль или -1 в регистре D0 для представления логического значения и также то, что операторы цикла ожидают, что будет установлен соответствующий флаг. При реализации всего этого для 68000 все становится немного сложным.
Так как операторы цикла выполняются только по флажкам, было бы хорошо (а также довольно эффективно) просто установить эти флажки и совсем ничего не загружать в D0. Это было бы прекрасно для циклов и ветвлений, но запомните, что отношения могут быть использованы везде, где могут быть использованы булевы показатели. Мы можем сохранять его результат в булевой переменной. Так как мы не можем знаеть пока как будет использоваться результат, мы должны учесть оба случая.
Сравнение числовых данных достаточно просто... 68000 имеет команду для этого... но она устанавливает флажки а не значение. Более того, всегда будут устанавливаться те же самые флажки (ноль если равно, и т.д.), в то время, как нам необходим по-разному установленный флажок нуля для каждого различного оператора отношения.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206