Джек Креншоу - Давайте создадим компилятор!

Здесь есть возможность читать онлайн «Джек Креншоу - Давайте создадим компилятор!» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Жанр: Программирование, на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Давайте создадим компилятор!: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Давайте создадим компилятор!»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Эта серия, написанная в период с 1988 по 1995 года и состоящая из шестнадцати частей, является нетехническим введением в конструирование компиляторов. Серия является руководством по теории и практике разработки синтаксических анализаторов и компиляторов языков программирования. До того как вы закончите чтение этой книги, вы раскроете каждый аспект конструирования компиляторов, разработаете новый язык программирования и создадите работающий компилятор.

Давайте создадим компилятор! — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Давайте создадим компилятор!», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

{–}

{ Load a Variable to Primary Register }

procedure LoadVar(Name, Typ: char);

begin

Move(Typ, Name + '(PC)', 'D0');

end;

{–}

По крайней мере для 68000, многие команды оказываются командами MOVE. Было бы полезно создать отдельный генератор кода только для этих инструкций и затем вызывать его когда необходимо:

{–}

{ Generate a Move Instruction }

procedure Move(Size: char; Source, Dest: String);

begin

EmitLn('MOVE.' + Size + ' ' + Source + ',' + Dest);

end;

{–}

Обратите внимание, что эти две подпрограммы – строго генераторы кода; они не имеют проверки ошибок и другой логики. Чтобы завершить картинку, нам необходим еще один программный уровень, который предоставляет эти функции.

Прежде всего, мы должны удостовериться, что типы, с которыми мы работаем – загружаемого типа. Это звучит как работа для другого распознавателя:

{–}

{ Recognize a Legal Variable Type }

function IsVarType(c: char): boolean;

begin

IsVarType := c in ['B', 'W', 'L'];

end;

{–}

Затем, было бы хорошо иметь подпрограмму, которая извлечет тип переменной из таблицы идентификаторов в то же время проверяя его на допустимость:

{–}

{ Get a Variable Type from the Symbol Table }

function VarType(Name: char): char;

var Typ: char;

begin

Typ := TypeOf(Name);

if not IsVarType(Typ) then Abort('Identifier ' + Name +

' is not a variable');

VarType := Typ;

end;

{–}

Вооруженная этими инструментами, процедура, выполняющая загрузку переменной, становится тривиальной:

{–}

{ Load a Variable to the Primary Register }

procedure Load(Name: char);

begin

LoadVar(Name, VarType(Name));

end;

{–}

(Примечание для обеспокоившихся: я знаю, знаю, все это очень неэффективно. В промышленной программы мы, возможно, предприняли бы шаги чтобы избежать такого глубокого вложения вызовов процедур. Не волнуйтесь об этом. Это упражнение, помните? Более важно сделать его правильно и понять его, чем получить неправильный ответ но быстро. Если вы закончите свой компилятор и обнаружите, что вы несчастны от его быстродействия, вы вольны вернуться и доработать код для более быстрой работы).

Было бы хорошей идеей протестировать программу сейчас. Так как мы пока не имеем процедуры для работы с операциями присваивания, я просто добавил строки:

Load('A');

Load('B');

Load('C');

Load('X');

в основную программу. Таким образом, после того, как раздел объявления завершен, они будут выполнены чтобы генерировать код для загрузки. Вы можете поиграть с различными комбинациями объявлений чтобы посмотреть как обрабатываются ошибки.

Я уверен, что вы не будете удивлены, узнав, что сохранение переменных во многом подобно их загрузке. Необходимые процедуры показаны дальше:

{–}

{ Store Primary to Variable }

procedure StoreVar(Name, Typ: char);

begin

EmitLn('LEA ' + Name + '(PC),A0');

Move(Typ, 'D0', '(A0)');

end;

{–}

{ Store a Variable from the Primary Register }

procedure Store(Name: char);

begin

StoreVar(Name, VarType(Name));

end;

{–}

Вы можете проверить их таким же образом, что и загрузку.

Теперь, конечно, достаточно легко использовать их для обработки операций присваивания. Что мы сделаем – создадим специальную версию процедуры Block, которая поддерживает только операции приваивания, а также специальную версию Expression, которая поддерживает в качестве допустимых выражений только одиночные переменные. Вот они:

{–}

{ Parse and Translate an Expression }

procedure Expression;

var Name: char;

begin

Load(GetName);

end;

{–}

{ Parse and Translate an Assignment Statement }

procedure Assignment;

var Name: char;

begin

Name := GetName;

Match('=');

Expression;

Store(Name);

end;

{–}

{ Parse and Translate a Block of Statements }

procedure Block;

begin

while Look <> '.' do begin

Assignment;

Fin;

end;

end;

{–}

(Стоит заметить, что новые процедуры, которые позволяют нам манипулировать типами, даже проще и яснее чем те, что мы видели ранее. Это в основном блягодаря нашим усилиям по изоляции подпрограмм генерации кода.)

Есть одна небольшая назойливая проблема. Прежде мы использовали завершающую точку Паскаля чтобы выбраться из процедуры TopDecl. Теперь это неправильный символ... он использован для завершения Block. В предудущих программах мы использовали для выхода символ BEGIN (сокращенно "b"). Но он теперь используется как символ типа.

Решение, хотя и является отчасти клуджем, достаточно простое. Для обозначения BEGIN мы будем использовать 'B' в верхнем регистре. Так что измените символ в цикле WHILE внутри TopDecl с "." на "B" и все будет прекрасно.

Теперь мы можем завершить задачу, изменив основную программу следующим образом:

{–}

{ Main Program }

begin

Init;

TopDecls;

Match('B');

Fin;

Block;

DumpTable;

end.

{–}

(Обратите внимание, что я должен был расставить несколько обращений к Fin чтобы избежать проблем переносов строк.)

ОК, запустите эту программу. Попробуйте ввести:

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Давайте создадим компилятор!»

Представляем Вашему вниманию похожие книги на «Давайте создадим компилятор!» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Давайте создадим компилятор!»

Обсуждение, отзывы о книге «Давайте создадим компилятор!» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x