Учимся писать компилятор

Предпочтительные языки : C / C++, Java и Ruby.

Я ищу несколько полезных книг / руководств о том, как написать собственный компилятор просто для образовательных целей. Я больше всего знаком с C / C++, Java и Ruby, поэтому я предпочитаю ресурсы, которые включают один из этих трех, но любой хороший ресурс приемлем.

Ответов (25)

Решение

Большой список ресурсов:

Легенда:

  • ¶ Ссылка на файл PDF
  • $ Ссылка на печатную книгу

Книга «Дракон» определенно является книгой по «построению компиляторов», но если ваш язык не так сложен, как языки текущего поколения, вы можете взглянуть на паттерн Интерпретатор из Паттернов проектирования .

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

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

Как вы думаете, как был создан C++?

Взгляните на книгу ниже. Автор - создатель ANTLR .

Шаблоны языковой реализации: создавайте свои собственные предметно-ориентированные и общие языки программирования .

альтернативный текст

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

Я бы добавил книгу Oberon, которая содержит полный исходный код удивительно быстрого и простого компилятора Oberon Project Oberon .

Альтернативный текст

«... Давайте построим компилятор ...»

Я бы второй http://compilers.iecc.com/crenshaw/ по @sasb . Забудьте пока покупать больше книг.

Почему? Инструменты и язык.

Требуемый язык - Паскаль, и, если я правильно помню, основан на Турбо-Паскале. Так уж получится, если вы зайдете на http://www.freepascal.org/ и загрузите компилятор Pascal, все примеры будут работать прямо со страницы ~ http://www.freepascal.org/download.var . Паскаль - это то, что вы можете использовать его практически с любым процессором или ОС, о которых вы можете заботиться.

После того, как вы усвоите уроки, попробуйте более продвинутую « Книгу драконов ~ http://en.wikipedia.org/wiki/Dragon_book

Я согласен со ссылкой на Книгу Дракона; ИМО, это исчерпывающее руководство по созданию компилятора. Однако приготовьтесь к некоторой жесткой теории.

Если вам нужна книга, более легкая по теории, вам лучше подойдет Game Scripting Mastery . Если вы новичок в теории компиляторов, это более мягкое введение. В нем не рассматриваются более практические методы синтаксического анализа (выбор непрогнозирующего рекурсивного спуска без обсуждения анализа LL или LR), и, насколько я помню, в нем даже не обсуждается какая-либо теория оптимизации. Кроме того, вместо компиляции в машинный код он компилируется в байт-код, который должен выполняться на виртуальной машине, которую вы также пишете.

Это по-прежнему неплохое чтение, особенно если вы можете дешево купить его на Amazon. Если вам нужно только легкое знакомство с компиляторами, Game Scripting Mastery - неплохой вариант. Если вы хотите стать хардкорным, вам не стоит довольствоваться ни чем иным, как Dragon Book.

Если вы хотите использовать мощные инструменты более высокого уровня, а не строить все самостоятельно, просмотр проектов и чтение этого курса - довольно хороший вариант. Это языковой курс от автора механизма синтаксического анализа Java ANTLR. Вы можете получить книгу к курсу в формате PDF у прагматичных программистов .

В курсе рассматриваются стандартные компоненты компилятора компилятора, которые вы можете встретить в других местах: синтаксический анализ, типы и проверка типов, полиморфизм, таблицы символов и генерация кода. Практически единственное, что не рассматривается, - это оптимизация. Окончательный проект представляет собой программу , которая составляет подмножество C . Поскольку вы используете такие инструменты, как ANTLR и LLVM, можно написать весь компилятор за один день (у меня есть доказательства этого, хотя я имею в виду ~ 24 часа). Это тяжелый практический инжиниринг с использованием современных инструментов, немного легче теории.

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

«Давайте создадим компилятор» - это здорово, но немного устарело. (Я не говорю, что это делает его даже немного менее достоверным.)

Или посмотрите SLANG . Это похоже на «Давайте построим компилятор», но это гораздо лучший ресурс, особенно для начинающих. Он поставляется с учебным пособием в формате pdf, в котором используется 7-шаговый подход к обучению вас компилятору. Добавление ссылки quora, поскольку в ней есть ссылки на все различные порты SLANG на C++, Java и JS, а также на интерпретаторы на python и java, изначально написанные с использованием C# и платформы .NET.

Я думаю, что современная реализация компилятора в ML - лучший вводный текст для написания компилятора. Также есть версия для Java и версия для C , каждая из которых может быть более доступной с учетом вашего языкового фона. В книге собрано много полезного базового материала (сканирование и синтаксический анализ, семантический анализ, записи активации, выбор инструкций, генерация собственного кода RISC и x86) и различные «продвинутые» темы (компиляция объектно-ориентированных и функциональных языков, полиморфизм, сборка мусора, оптимизация и т. Д. одну статическую форму назначения) на относительно небольшое пространство (~ 500 страниц).

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

Должен признаться, у меня есть серьезная слабость к конструкции компилятора Никлауса Вирта . Он доступен в Интернете в формате PDF. Я считаю, что эстетика программирования Вирта просто прекрасна, однако некоторые люди находят его стиль слишком минималистичным (например, Вирт отдает предпочтение синтаксическим анализаторам с рекурсивным спуском, но большинство курсов CS сосредоточено на инструментах генератора синтаксического анализатора; языковые конструкции Вирта довольно консервативны). основных идей Вирта, поэтому, нравится вам его стиль или нет, я настоятельно рекомендую прочитать эту книгу.

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

Одна книга еще не предложена, но очень важна - это «Линкеры и загрузчики» Джона Левина. Если вы не используете внешний ассемблер, вам понадобится способ вывода объектного файла, который можно связать с вашей окончательной программой. Даже если вы используете внешний ассемблер, вам, вероятно, потребуется разбираться в перемещениях и том, как работает весь процесс загрузки программы, чтобы создать рабочий инструмент. В этой книге собрано много случайных сведений об этом процессе для различных систем, включая Win32 и Linux.

Самый простой способ создать компилятор - использовать bison и flex (или аналогичный), построить дерево (AST) и сгенерировать код на C. Генерация кода C является наиболее важным шагом. Создавая код C, ваш язык будет автоматически работать на всех платформах, где есть компилятор C.

Сгенерировать код C так же просто, как сгенерировать HTML (просто используйте print или эквивалент), что, в свою очередь, намного проще, чем написать синтаксический анализатор C или HTML-синтаксический анализатор.

Если вы хотите использовать LLVM, проверьте это: http://llvm.org/docs/tutorial/ . Он учит вас, как написать компилятор с нуля, используя структуру LLVM, и не предполагает, что у вас есть какие-либо знания по этому вопросу.

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

Компилятор LCC ( википедия ) ( домашняя страница проекта ) ( github.com/drh/lcc ) Фрейзера и Хансона описан в их книге «Перенастраиваемый компилятор C: дизайн и реализация». Он вполне читабелен и объясняет весь компилятор, вплоть до генерации кода.

Вам следует проверить " ichbins " Дариуса Бэкона , который представляет собой компилятор небольшого диалекта Лиспа, ориентированного на C, на чуть более 6 страницах кода. Преимущество, которое он имеет перед большинством игрушечных компиляторов, состоит в том, что язык достаточно полный, чтобы компилятор был написан на нем. (В архиве также есть интерпретатор для начальной загрузки.)

На моей веб-странице Ur-Scheme есть еще кое-что о том, что я нашел полезным в обучении написанию компилятора .

Я изучаю ту же концепцию и нашел эту многообещающую статью Джоэла Побара,

Создайте компилятор языка для .NET Framework - не знаю, куда это делось

Создание языкового компилятора для .NET Framework - pdf-копия исходного документа

он обсуждает высокоуровневую концепцию компилятора и переходит к созданию своего собственного языка для среды .Net. Хотя он нацелен на .Net Framework, многие концепции должны быть воспроизведены. Статья охватывает:

  1. Определение языка
  2. Сканер
  3. Парсер (бит, который меня в основном интересует)
  4. Ориентация на .Net Framework
  5. Генератор кода

есть и другие темы, но вы попадаете в справедливую.

Он предназначен для начинающих, написан на C# (не совсем Java)

HTH

кости

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

Обычно интерпретируются Python и Ruby. Возможно, вы тоже захотите начать с переводчика. Это вообще проще.

Первый шаг - написать формальное описание языка, грамматику вашего языка программирования. Затем вам нужно преобразовать исходный код, который вы хотите скомпилировать или интерпретировать в соответствии с грамматикой, в абстрактное синтаксическое дерево, внутреннюю форму исходного кода, которую компьютер понимает и с которой может работать. Этот шаг обычно называется синтаксическим анализом, а программное обеспечение, которое анализирует исходный код, называется синтаксическим анализатором. Часто синтаксический анализатор генерируется генератором синтаксического анализатора, который преобразует формальную грамматику в исходный машинный код. Для хорошего нематематического объяснения синтаксического анализа я рекомендую "Методы синтаксического анализа - практическое руководство". В Википедии есть сравнение генераторов парсеров, из которых вы можете выбрать тот, который вам подходит. В зависимости от выбранного вами генератора синтаксического анализатора,

Написать синтаксический анализатор для вашего языка может быть очень сложно, но это зависит от вашей грамматики. Поэтому я предлагаю сделать вашу грамматику простой (в отличие от C++); хороший пример - LISP.

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

Если вы создаете интерпретатор, вам просто нужно будет интерпретировать промежуточное представление. Вы также можете скомпилировать его вовремя. Я рекомендую LLVM и libjit для своевременной компиляции. Чтобы сделать язык пригодным для использования, вам также необходимо будет включить некоторые функции ввода и вывода и, возможно, небольшую стандартную библиотеку.

Если вы собираетесь компилировать язык, это будет сложнее. Вам нужно будет написать бэкенды для разных компьютерных архитектур и сгенерировать машинный код из промежуточного представления в этих бэкэндах. Я рекомендую LLVM для этой задачи.

На эту тему есть несколько книг, но я не могу порекомендовать ни одну из них для общего пользования. Большинство из них слишком академичны или слишком практичны. Не существует «Научитесь писать компилятор за 21 день», и поэтому вам придется купить несколько книг, чтобы хорошо разобраться в этой теме. Если вы поищете в Интернете, вы найдете несколько онлайн-книг и конспектов лекций. Может быть, поблизости есть университетская библиотека, где можно брать книги на компиляторах.

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

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

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

Простое выполнение верхней половины позволяет вам получить опыт написания лексического анализатора и парсера и перейти к генерации некоторого «кода» (это промежуточное представление, о котором я упоминал). Таким образом, он возьмет вашу исходную программу и преобразует ее в другое представление и произведет некоторую оптимизацию (если хотите), которая является сердцем компилятора. Затем нижняя половина примет это промежуточное представление и сгенерирует байты, необходимые для запуска программы в определенной архитектуре. Например, нижняя половина возьмет ваше промежуточное представление и сгенерирует исполняемый файл PE.

Некоторые книги по этой теме, которые мне показались особенно полезными, - это « Принципы и методы компиляторов» (или «Книга драконов» из-за милого дракона на обложке). В нем есть отличная теория, и он определенно охватывает контекстно-свободные грамматики в действительно доступной форме. Кроме того, для создания лексического анализатора и парсера вы, вероятно, будете использовать инструменты * nix lex и yacc. И, что довольно неинтересно, книга под названием « lex and yacc » продолжилась с того места, где остановилась «Книга драконов» в этой части.

  1. Это обширная тема. Не стоит недооценивать этот момент. И не недооценивайте мою точку зрения, чтобы не недооценивать ее.
  2. Я слышал, что Книга Дракона - это (?) Место для начала, наряду с поиском. :) Поправляйся в поисках, со временем это будет твоя жизнь.
  3. Создание собственного языка программирования - отличное упражнение! Но знайте, что в конечном итоге он никогда не будет использоваться для каких-либо практических целей. Исключений здесь немного, и они очень редки.

Возможно, вы захотите изучить Lex / Yacc (или Flex / Bison, как хотите их называть). Flex - это лексический анализатор, который анализирует и идентифицирует семантические компоненты («токены») вашего языка, а Bison будет использоваться для определения того, что происходит при анализе каждого токена. Это может быть, но определенно не ограничивается, распечаткой кода C для компилятора, который будет компилироваться в C, или динамическим выполнением инструкций.

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

Я помню, как задавал этот вопрос около семи лет назад, когда был новичком в программировании.

Я был очень осторожен, когда спрашивал, и, что удивительно, не получил такой критики, как вы. Однако они указали мне направление « Книги драконов », которая, на мой взгляд, действительно отличная книга, в которой объясняется все, что вам нужно знать, чтобы написать компилятор (вам, конечно, придется освоить один или два языка. Тем более языки вы знаете, тем веселее.).

И да, многие люди говорят, что читать эту книгу - это безумие, и вы ничего не узнаете из нее, но я полностью с этим не согласен.

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

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

Я не сразу написал свой собственный компилятор, но, спросив, я знал, с чего начать. А теперь, после изучения множества разных языков и чтения Книги Дракона, писать не составляет особой проблемы. (Я также изучаю компьютерную инженерию, но большую часть того, что я знаю о программировании, я получил самостоятельно.)

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

Книга также хороша, если вы хотите научиться писать парсеры / интерпретаторы.

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

Учебник: метакомпиляторы, часть 1

Все это основано на замечательном небольшом техническом документе на 10 страницах:

Val Schorre META II: синтаксически-ориентированный язык написания компиляторов

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

Я знаю автора веб-сайта еще со времен учебы в колледже, но я не имею к нему никакого отношения.

Из FAQ comp.compilers :

"Программирование персонального компьютера" Пер Бринч Хансен Прентис-Холл 1982 ISBN 0-13-730283-5

В этой книге с печальным названием объясняется разработка и создание однопользовательской среды программирования для микропрограмм с использованием языка, подобного Паскалю, под названием Edison. Автор представляет весь исходный код и объяснения пошаговой реализации компилятора Edison и простой поддерживающей операционной системы, все написано на самом Edison (за исключением небольшого поддерживающего ядра, написанного на символическом ассемблере для PDP 11/23; полный исходный код также можно заказать для IBM PC).

Самыми интересными в этой книге являются: 1) ее способность продемонстрировать, как создать законченный, автономный, самоподдерживающийся, полезный компилятор и операционную систему, и 2) интересное обсуждение языкового дизайна и проблем спецификации и торговли. офф в главе 2.

"Бринч Хансен на компиляторах Паскаля" Пер Бринч Хансен Прентис-Холл 1985 ISBN 0-13-083098-4

Еще одна легкая теория, полная прагматиков, вот книга о том, как это кодировать. Автор представляет дизайн, реализацию и полный исходный код для компилятора и интерпретатора p-кода для Pascal- (Pascal «минус»), подмножества Pascal с логическими и целочисленными типами (но без символов, вещественных, поддиапазонных или перечислимых типов) , определения констант и переменных, а также типы массивов и записей (но без упакованных, вариантов, набора, указателей, безымянных, переименованных или файловых типов), выражения, операторы присваивания, определения вложенных процедур со значениями и параметрами переменных, операторы if, операторы while, и блоки begin-end (но без определений функций, процедурных параметров, операторов goto и меток, операторов case, операторов повторения, операторов for и операторов with).

Компилятор и интерпретатор написаны на Паскале * («звезда» Паскаля), подмножестве Паскаля, расширенном некоторыми функциями в стиле Эдисона для создания систем разработки программного обеспечения. Компилятор Pascal * для IBM PC продается автором, но компилятор Pascal из книги легко перенести на любую удобную платформу Pascal.

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

Если у вас мало времени, я рекомендую "Compiler Construction" Никлауса Вирта (Addison-Wesley, 1996) , крошечный буклет, который вы можете прочитать за день, но он объясняет основы (в том числе, как реализовать лексеры, парсеры рекурсивного спуска, и ваши собственные виртуальные машины на основе стека). После этого, если вы хотите глубоко погрузиться в книгу, не обойтись без книги Дракона, как предлагают другие комментаторы.