Начиная простой (возможно, самый простой) компилятор C? - PullRequest
40 голосов
/ 28 февраля 2010

Я сталкивался с этим: Написание компилятора с использованием Turbo Pascal

Мне любопытно, есть ли какие-нибудь учебники или ссылки, объясняющие, как создать простой компилятор Си. Я имею в виду, что достаточно, если он выведет меня на уровень понимания арифметических операций. Я стал действительно любопытным после прочтения этой статьи Кеном Томпсоном . Идея написать что-то, что понимает сама себя, кажется захватывающей.

Почему я поставил этот вопрос вместо того, чтобы задавать вопрос Google? Я попробовал Google, и Pascal был первой ссылкой. Остальное не показалось мне актуальным и добавило к этому ... Я не являюсь мажором CS (поэтому мне все еще нужно узнать, что делают все эти инструменты, такие как yacc), и я хочу изучить это, делая и надеюсь, что люди с большим опытом всегда лучше, чем Google. Я хочу прочитать статью, написанную в том же духе, что я перечислил выше, но ту, в которой освещаются как минимум начальные этапы построения простого компилятора Си.

Кроме того, я не знаю лучший способ учиться. Должен ли я начать с компилятора C на C или на другом языке? Я пишу компилятор C или другой язык? Я чувствую, что на такие вопросы лучше ответить, когда у меня есть какое-то направление для изучения. Есть предложения?

Есть предложения?

Ответы [ 12 ]

24 голосов
/ 28 февраля 2010

Я советую вам этот урок:

Это небольшой пример того, как реализовать «небольшой язык» компилятора. Исходный код очень маленький и объясняется шаг за шагом.

Для библиотеки LLVM (низкоуровневая виртуальная машина, представляющая внутреннюю структуру программы) существует также библиотека C:

24 голосов
/ 28 февраля 2010

Компилятор состоит из трех частей:

  1. Парсер
  2. Абстрактное синтаксическое дерево (AST)
  3. Генератор кода

Существует множество хороших генераторов синтаксических анализаторов, которые начинаются с грамматик языка. Может быть, ANTLR будет хорошим началом для вас. Если вы хотите придерживаться корней C, попробуйте lex / yacc или bison.

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

Получив AST, вы используете его для генерации машинного кода, который вы запустите.

Это выполнимо, но не тривиально.

Я бы также проверил Amazon на наличие книг о написании компиляторов. Книга Дракона - классика, но есть и более современные.

ОБНОВЛЕНИЕ: По переполнению стека возникали похожие вопросы, например этот . Проверьте также эти ресурсы.

15 голосов
/ 28 февраля 2010

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

12 голосов
/ 28 февраля 2010

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

Вместо того, чтобы писать полный или совместимый со стандартами компилятор языка C (по крайней мере, в начале), я бы предложил ограничиться базовым подмножеством языка, таким как общие операторы, поддержка только целых чисел, а также базовые функции и указатели. Одним из классических примеров этого была книга Рона Каина Small-C , ставшая популярной благодаря серии статей, написанных в Dr. Журнал Доббса в, я полагаю, 1980-х годов. Они публикуют CD с книгой Джеймса Хендрикса, вышедшей из печати, Компилятор Small-C .

Что я хотел бы предложить, так это следовать учебному пособию Crenshaw, но написать его для компилятора языка, подобного C, и для любого целевого процессора (Crenshaw предназначается для процессора Motorola 68000), на который вы хотите ориентироваться. Чтобы сделать это, вам нужно знать базовую сборку, для которой вы хотите запускать скомпилированные программы. Это может включать в себя эмулятор для 68000 или MIPS, которые, вероятно, являются более хорошими наборами инструкций по сборке, чем почтенный набор инструкций CISC Intel x86 (16/32-битный).

Существует множество потенциальных книг, которые можно использовать в качестве отправных точек для изучения теории компилятора / переводчика (и практики). Прочтите часто задаваемые вопросы comp.compilers и обзоры у различных онлайн-продавцов книг. Большинство вводных книг написаны как учебники для студентов старших курсов старших классов по информатике, поэтому они могут быть медленными при чтении без знания CS. Одна старая книга, которая может быть более вводной, но легче читаемой, чем " Книга Дракона " - Введение в конструкцию компилятора Томаса Парсонс. Он старше, поэтому вы сможете найти подержанную копию у выбранного вами интернет-продавца книг по разумной цене.

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

Добавлено:

В отношении процесса начальной загрузки. Поскольку существуют свободно доступные компиляторы C, вам не нужно беспокоиться о начальной загрузке. Напишите свой компилятор с отдельными существующими инструментами (GCC, Visual C ++ Express, Mingw / djgpp, tcc), и вы можете беспокоиться о самостоятельной компиляции вашего проекта на более поздней стадии. Я был удивлен этой частью вопроса, пока не понял, что вы пришли к идее написания своего собственного компилятора, прочитав награду Кена Томаса ACM Turing, Reflections on Trusting Trust , которая действительно входит в компилятор процесс начальной загрузки. Это модерируемая продвинутая тема, а также просто много хлопот. Я нахожу даже самозагрузку компилятора C GCC в старых системах Unix (Digital OSF / 1 на 64-битной Alpha), в которых компилятор C был медленным и трудоемким, подверженным ошибкам процессом.

Другой вопрос был о том, что на самом деле делает инструмент компилятора, такой как Yacc. Yacc (еще один компилятор компилятора или Bison от GNU) - это инструмент, предназначенный для облегчения написания парсера компилятора (или переводчика). Основываясь на формальной грамматике для целевого языка, который вы вводите в yacc, он генерирует синтаксический анализатор , который является одной из частей общего дизайна компилятора. Далее идет Lex (или flex из GNU), который используется для генерации лексического анализатора или сканера, который часто используется в сочетании с синтаксическим анализатором, сгенерированным yacc, для формирования каркаса внешнего интерфейса компилятора. Эти инструменты делают писателя фронтэндом, возможно, проще, чем написание лексического анализатора и анализатора самостоятельно. В учебнике Crenshaw эти инструменты не используются, и вам это не нужно, многие авторы компиляторов не всегда их используют. Конечно, Креншоу признает, что парсер учебника довольно прост.

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

6 голосов
/ 28 февраля 2010

Вас может заинтересовать книга / курс Элементы вычислительных систем: создание современного компьютера из первых принципов .

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

В дополнение к «сборке аппаратного обеспечения», вы также будете поэтапно реализовывать ассемблер, виртуальную машину, компилятор и элементарную ОС. Я думаю, что это даст вам достаточно фона, чтобы углубиться в предметную область с некоторыми из наиболее рекомендуемых ресурсов, перечисленных в других ответах.

5 голосов
/ 28 февраля 2010

Как мне [начать писать] простой компилятор C?

Нет ничего простого в компиляции C . Лучший простой компилятор C - lcc Крис Фрейзер и Дэвид Хэнсон. Они потратили 10 лет на разработку дизайна, чтобы сделать его настолько простым, насколько это возможно, и при этом генерировать достаточно хороший код. Если у вас есть доступ к университетской библиотеке, вы сможете получить их книгу.

Начну ли я с компиляции C на C или на другом языке?

Какой-то другой язык. Однажды я спросил Хансона, какие уроки он и Фрейзер получили, потратив 10 лет на проект lcc. Главное, что сказал Хансон, было

C - паршивый язык для написания компилятора.

Вам лучше использовать Haskell или какой-нибудь диалект ML. Оба языка предлагают функции над алгебраическими типами данных, что идеально соответствует задачам, с которыми сталкивается разработчик компилятора. Если вы все еще хотите заниматься C, вы можете начать с CIL Джорджа Некулы, который представляет собой большой кусок компилятора C, написанного на ML.

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

Вы не найдете другой статьи, подобной Кену. Но Эндрю Аппель написал замечательную статью под названием Axiomatic Bootstrapping: руководство для хакеров-компиляторов Я не смог найти бесплатную версию, но многие люди имеют доступ к цифровой библиотеке ACM.

Есть предложения?

Если вы хотите написать компилятор,

  • Используйте Haskell или ML в качестве языка реализации.

  • В качестве первого компилятора выберите очень простой язык, например Оберон или P0 из книги Никлауса Вирта Алгоритмы + структуры данных = Программы . Вирт известен тем, что разрабатывает языки, которые легко компилировать.

Вы можете написать компилятор C для вашего второго компилятора.

5 голосов
/ 28 февраля 2010

In Среда программирования Unix , Керниган и Пайк проходят 5 итераций, делая калькулятор, работающий от простого лексического анализа на основе C и немедленного выполнения, до синтаксического анализа yacc / lex и генерации кода для абстрактной машины.Потому что они пишут так чудесно, что я не могу предложить более плавное введение.Это, конечно, меньше, чем C, но это, вероятно, в ваших интересах.

5 голосов
/ 28 февраля 2010

Компилятор - сложный предмет, охватывающий аспекты

  • Обработка ввода с использованием Lexing, Parsing
  • Создание хранилища символов для каждой используемой переменной, такой как абстрактное синтаксическое дерево (AST)
  • Из дерева AST транспонировать и построить двоичный файл машинного кода на основе синтаксиса

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

Вот несколько ссылок для начала:

3 голосов
/ 28 февраля 2010

Если вам нужен умопомрачительный опыт, который научит вас писать компиляторы, которые сами компилируются, вам нужно прочитать эту статью из 1964 .

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

На 10 страницах рассказывается, как писать компиляторы, как писать мета-компиляторы, предоставляется набор команд виртуального метакомпилятора и пример компилятора, созданного с помощью метакомпилятора.

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

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

И если получить документ по исходной ссылке неудобно, поскольку вы не являетесь участником ACM, вы обнаружите, что в любом случае учебник содержит все детали. (ИМХО, по цене, сама бумага стоит того-то).

10 страниц!

3 голосов
/ 28 февраля 2010

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

Забавно, что вы должны спросить об этом сегодня, поскольку всего пару дней назад я написал интерпретатор лямбда-исчисления. Лямбда-исчисление является дедушкой всех функциональных языков. Он длиной всего 200 строк (на языке C ++, включая отчеты об ошибках, немного красивой печати, немного юникода) и имеет двухфазную структуру с промежуточным форматом, который можно использовать для создания кода.

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

...