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

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

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

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

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

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

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

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

Интервал:

Закладка:

Сделать

procedure DoRepeat;

var L: string;

begin

Match('r');

L := NewLabel;

PostLabel(L);

Block;

Match('u');

Condition;

EmitLn('BEQ ' + L);

end;

{–}

Как и прежде, мы должны добавить вызов DoRepeat в Block. Хотя на этот раз есть различия. Я решил использовать "r" вместо REPEAT (естественно), но я также решил использовать "u" вместо UNTIL. Это означает, что "u" должен быть добавлен к множеству символов в условии while. Это символы, которые сигнализируют о выходе из текущего блока... символы «follow», на жаргоне разработчиков компиляторов.

{–}

{ Recognize and Translate a Statement Block }

procedure Block;

begin

while not(Look in ['e', 'l', 'u']) do begin

case Look of

'i': DoIf;

'w': DoWhile;

'p': DoLoop;

'r': DoRepeat;

else Other;

end;

end;

end;

{–}

ЦИКЛ FOR

Цикл FOR очень удобен, но он тяжел для трансляции. Не столько потому, что сама конструкция трудна... в конце концов это всего лишь цикл... но просто потому, что она трудна для реализации на ассемблере. Как только код придуман, трансляция достаточно проста.

Фаны Си любят цикл FOR этого языка (фактически он проще для кодирования), но вместо него я выбрал синтаксис очень похожий на синтаксис из старого доброго Бейсика:

FOR = TO ENDFOR

Сложность трансляции цикла «FOR» зависит от выбранного вами способа его реализации, от пути, которым вы решили определять правила обработки ограничений. Рассчитывается ли expr2 каждый раз при прохождении цикла, например, или оно обрабатывается как постоянное ограничение? Всегда ли вы проходите цикл хотя бы раз, как в Fortran, или нет. Все становится проще, если вы приверженец точки зрения что эта конструкция эквивалентна:

=

TEMP =

WHILE <= TEMP

ENDWHILE

Заметьте, что с этим определением цикла не будет выполнен вообще если изначально больше чем .

Код 68000, необходимый для этого, сложней чем все что мы делали до сих пор. Я сделал несколько попыток, помещая и счетчик и верхний предел в стек, в регистры и т.д. В конечном итоге я остановился на гибридном варианте размещения, при котором счетчик помещается в памяти (поэтому он может быть доступен внутри цикла) а верхний предел – в стеке. Оттранслированный код получился следующий:

; получить имя счетчика цикла

; получить начальное значение

LEA (PC),A0 ; обратиться к счетчику цикла

SUBQ #1,D0 ; предварительно уменьшить его

MOVE D0,(A0) ; сохранить его

; получить верхний предел

MOVE D0,-(SP) ; сохранить его в стеке

L1: LEA (PC),A0 ; обратиться к счетчику цикла

MOVE (A0),D0 ; извлечь его в D0

ADDQ #1,D0 ; увеличить счетчик

MOVE D0,(A0) ; сохранить новое значение

CMP (SP),D0 ; проверить диапазон

BLE L2 ; пропустить если D0 > (SP)

BRA L1 ; цикл для следующего прохода

L2: ADDQ #2,SP ; очистить стек

Ничего себе! Это же куча кода... строка, содержащая кажется совсем потерявшейся. Но это лучшее из того, что я смог придумать. Я полагаю, чтобы вам помочь, вы должны иметь в виду что в действительности это всего лишь шестнадцать слов, в конце концов. Если кто-нибудь сможет оптимизировать это лучше, пожалуйста дайте мне знать.

Однако, подпрограмма анализа довольно проста теперь, когда у нас есть код:

{–}

{ Parse and Translate a FOR Statement }

procedure DoFor;

var L1, L2: string;

Name: char;

begin

Match('f');

L1 := NewLabel;

L2 := NewLabel;

Name := GetName;

Match('=');

Expression;

EmitLn('SUBQ #1,D0');

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

EmitLn('MOVE D0,(A0)');

Expression;

EmitLn('MOVE D0,-(SP)');

PostLabel(L1);

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

EmitLn('MOVE (A0),D0');

EmitLn('ADDQ #1,D0');

EmitLn('MOVE D0,(A0)');

EmitLn('CMP (SP),D0');

EmitLn('BGT ' + L2);

Block;

Match('e');

EmitLn('BRA ' + L1);

PostLabel(L2);

EmitLn('ADDQ #2,SP');

end;

{–}

Так как в этой версии синтаксического анализатора у нас нет выражений, я использовал тот же самый прием что и для Condition и написал подпрограмму:

{–}

{ Parse and Translate an Expression }

{ This version is a dummy }

Procedure Expression;

begin

EmitLn('');

end;

{–}

Испытайте его. Снова, не забудьте добавить вызов в Block. Так как у нас нет возможности ввода для фиктивной версии Expression, типичная входная строка будет выглядеть так:

afi=bece

Хорошо, генерируется много кода, не так ли? Но, по крайней мере, это правильный код.

ОПЕРАТОР DO

Из-за всего этого мне захотелось иметь более простую версию цикла FOR. Причина появления всего этого кода выше состоит в необходимости иметь счетчик цикла, доступный как переменная внутри цикла. Если все, что нам нужно это считающий цикл, позволяющий нам выполнить что-то определенное число раз, но не нужен непосредственный доступ к счетчику, имеется более простое решение. Процессор 68000 имеет встроенную команду «уменьшить и переход если не ноль», которая является идеальной для подсчета. Для полноты давайте добавим и эту конструкцию. Это будет наш последний цикл.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x