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

Тут можно читать онлайн Джек Креншоу - Давайте создадим компилятор! - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Давайте создадим компилятор!
  • Автор:
  • Жанр:
  • Издательство:
    неизвестно
  • Год:
    неизвестен
  • ISBN:
    нет данных
  • Рейтинг:
    3.89/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

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

Давайте создадим компилятор! - описание и краткое содержание, автор Джек Креншоу, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

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

Давайте создадим компилятор! - читать книгу онлайн бесплатно, автор Джек Креншоу
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

{–}

{ Parse and Translate a Block of Statements }

procedure Block;

begin

Scan;

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

case Token of

'i': DoIf;

'w': DoWhile;

'R': DoRead;

'W': DoWrite;

'x': Assignment;

end;

Semi;

Scan;

end;

end;

{–}

Внимательно взгляните на тонкие изменения в операторе case. Вызов Assigment теперь ограничивается проверкой Token. Это позволит избежать вызова Assigment когда токен является точкой с запятой (что случается когда утверждение пустое).

Так как объявления – тоже утверждения, мы также должны добавить вызов Semi в процедуру TopDecl:

{–}

{ Parse and Translate Global Declarations }

procedure TopDecls;

begin

Scan;

while Token = 'v' do begin

Alloc;

while Token = ',' do

Alloc;

Semi;

end;

end;

{–}

Наконец нам нужен вызов для утверждения PROGRAM:

{–}

{ Main Program }

begin

Init;

MatchString('PROGRAM');

Semi;

Header;

TopDecls;

MatchString('BEGIN');

Prolog;

Block;

MatchString('END');

Epilog;

end.

{–}

Проще некуда. Испробуйте это с копией TINY и скажите как вам это нравится.

Версия Паскаля немного сложнее, но она все равно требует только небольших изменений и то только в процедуре Block. Для максимальной простоты давайте разобьем процедуру на две части. Следующая процедура обрабатывает только одно утверждение:

{–}

{ Parse and Translate a Single Statement }

procedure Statement;

begin

Scan;

case Token of

'i': DoIf;

'w': DoWhile;

'R': DoRead;

'W': DoWrite;

'x': Assignment;

end;

end;

{–}

Используя эту процедуру мы можем переписать Block так:

{–}

{ Parse and Translate a Block of Statements }

procedure Block;

begin

Statement;

while Token = ';' do begin

Next;

Statement;

end;

end;

{–}

Это, уверен, не повредило, не так ли? Теперь мы можем анализировать точки с запятой в Паскаль-подобном стиле.

Компромисс

Теперь, когда мы знаем как работать с точками с запятой, означает ли это, что я собираюсь поместить их в KISS/TINY? И да и нет. Мне нравится дополнительный сахар и защита, которые приходят с уверенным знанием, где заканчиваются утверждения. Но я не изменил своей антипатии к ошибкам компиляции, связанным с точками с запятой.

Так что я придумал хороший компромис: сделаем их необязательными!

Рассмотрите следующую версию Semi:

{–}

{ Match a Semicolon }

procedure Semi;

begin

if Token = ';' then Next;

end;

{–}

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

Поместите эту процедуру на место в первую версию вашей программы (с синтаксисом для C/Ada) и вы получите TINY Version 1.2.

Комментарии

Вплоть до этого времени я тщательно избегал темы комментариев. Вы могли бы подумать, что это будет простая тема... в конце концов компилятор совсем не должен иметь дела с комментариями; он просто должен игнорировать их. Чтож, иногда это так.

Насколько простыми или насколько трудными могут быть комментарии, зависит от выбранного вами способа их реализации. В одном случае, мы можем сделать так, чтобы эти комментарии перехватывались как только они поступят в компилятор. В другом, мы можем обрабатывать их как лексические элементы. Станет интереснее когда вы рассмотрите вещи, типа разделителей комментариев, содержащихся в строках в кавычках.

Односимвольные разделители

Вот пример. Предположим, мы принимаем стандарт Turbo Pascal и используем для комментариев фигурные скобки. В этом случае мы используем односимвольные разделители, так что наш анализ немного проще.

Один подход состоит в том, чтобы удалять комментарии как только мы встретим их во входном потоке, т.е. прямо в процедуре GetChar. Чтобы сделать это сначала измените имя GetChar на какое-нибудь другое, скажем GetCharX. (На всякий случай запомните, это будет временное изменение, так что лучше не делать этого с вашей единственной копией TINY. Я полагаю вы понимаете, что вы всегда должны делать эти эксперименты с рабочей копией).

Теперь нам нужна процедура для пропуска комментариев. Так что наберите следующее:

{–}

{ Skip A Comment Field }

procedure SkipComment;

begin

while Look <> '}' do

GetCharX;

GetCharX;

end;

{–}

Ясно, что эта процедура будет просто считывать и отбрасывать символы из входного потока, пока не найдет правую фигурную скобку. Затем она считывает еще один символ и возвращает его в Look.

Теперь мы можем написать новую версию GetChar, которая вызывает SkipComment для удаления комментариев:

{–}

{ Get Character from Input Stream }

{ Skip Any Comments }

procedure GetChar;

begin

GetCharX;

if Look = '{' then SkipComment;

end;

{–}

Наберите этот код и испытайте его. Вы обнаружите, что вы действительно можете вставлять комментарии везде, где захотите. Комментарии никогда даже не попадут в синтаксический анализатор... каждый вызов GetChar просто возвращает любой символ, не являющийся частью комментария.

Фактически, хотя этот метод делает свое дело и может даже совершенно удовлетворять вас, он делает свою работу немного слишком хорошо. Прежде всего, большинство языков программирования определяет, что комментарии должны быть обработаны как пробелы, так как комментарии не могут быть вложены, скажем, в имя переменной. Эта текущая версия не заботится о том, где вы помещаете комментарии.

Во-вторых, так как остальная часть синтаксического анализатора не может даже получить символ '{', вам не будет позволено поместить его в строку в кавычках.

Однако, прежде чем вы отвернете свой нос от такого упрощенного решения, я должен подчеркнуть, что столь уважаемый компилятор, как Turbo Pascal, также не позволит использовать '{' в строке в кавычках. Попробуйте. Относительно комментариев, вложенных в идентификатор, я не могу представить чтобы кто-то захотел сделать подобные вещи, так что вопрос спорен. Для 99% всех приложений то что я показал, будет работать просто отлично.

Но, если вы хотите быть щепетильным в этом вопросе и придерживаться стандартного обращения, тогда нам нужно переместить место перехвата немного ниже.

Чтобы сделать это сперва верните GetChar на старое место и измените имя, вызываемое в SkipComment Затем, давайте добавим левую фигурную скобку как возможный символ незаполненного пространства:

{–}

{ Recognize White Space }

function IsWhite(c: char): boolean;

begin

IsWhite := c in [' ', TAB, CR, LF, '{'];

end;

{–}

Теперь мы можем работать с комментариями в процедуре SkipWhite:

{–}

{ Skip Over Leading White Space }

procedure SkipWhite;

begin

while IsWhite(Look) do begin

if Look = '{' then

SkipComment

else

GetChar;

end;

end;

{–}

Обратите внимание, что SkipWhite написан так, что мы пропустим любую комбинацию незаполненного пространства и комментариев в одном вызове.

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

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

Интервал:

Закладка:

Сделать


Джек Креншоу читать все книги автора по порядку

Джек Креншоу - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Давайте создадим компилятор! отзывы


Отзывы читателей о книге Давайте создадим компилятор!, автор: Джек Креншоу. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x