Подтвердить что ты не робот

Написание собственного С++-компилятора

Я хочу написать свой собственный компилятор С++ в С++. Скажем, я собираюсь построить его в VS. Основная идея заключается в том, что он, должно быть, смог скомпилировать себя, а это значит, что я не могу использовать библиотеки STL, boost и т.д., Не так ли? Значит ли это, что я должен делать все с нуля - от лексического анализатора до генерации двоичного кода?

4b9b3361

Ответ 1

что означает, что я не могу использовать библиотеки STL, boost и т.д., могу ли я?

Почему бы и нет? Они не используют никакой магии (как бы), только простой С++. Поэтому, если ваш компилятор знает все С++, это не должно быть проблемой. Это, конечно, совершенно смехотворно, учитывая, что С++, вероятно, самый трудный для анализа языка программирования, существующего сегодня, и что создание компилятора с нуля, вероятно, займет сотни (!) Человеко-лет. (Я на самом деле не изобретал это число - я его где-то читал. К сожалению, я не могу найти источник сейчас.)

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

Итак, почему С++ так сложно компилировать?

Во-первых, С++ - это контекстно-зависимый язык. Создание парсера для такой грамматики намного сложнее. Однако это все еще один из самых простых аспектов. То, что делает С++ действительно трудным, - это определенные правила, относящиеся к объявлениям/определениям, поискам имен (рассматривают зависящие от аргументов имена) неявные правила преобразования и, конечно, разрешение шаблонов. Я думаю, что никакой существующий компилятор не получает шаблоны при любых обстоятельствах.

Рассмотрим Andrej Alexandrescu efford, чтобы написать версии шаблонов min и max, которые ведут себя так же корректно, как версия макроса. Он утверждает, что компилятору не удалось составить свой (теоретически правильный) код:

Все будет так хорошо, но там стоит немного подробностей. К сожалению, Min не работает с каким-либо компилятором, к которому я имею доступ. Справедливости ради, каждый компилятор задыхается на другом фрагменте кода.

Ответ 2

Это чрезвычайно сложная задача. Он включает в себя:

  • Выбор того, какой С++ вы хотите поддерживать. Stroustrup ARM? ISO/IEC 14882: 2003?
  • Поиск правильной грамматики для выбранной вами версии С++.
  • Написание лексера/парсера, который может обрабатывать контекстные тонкости.
  • Выбор аппаратной платформы для генератора кода.
  • Возможно, написана совместимый со стандартами компоновщик, поэтому вы можете использовать сторонние библиотеки.

Было принято gcc 22 года, чтобы добраться туда, где он есть. Visual С++ занял 17 лет (и был компилятор MS С++ за несколько лет до VС++). Эти продукты являются массивными.

chester89, я не хочу подразумевать, что вы этого не делаете, но для этого нужен профессионал и гений, как Уолтер Брайт, чтобы просто уйти и написать свой собственный компилятор С++ (а затем компилятор D).

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

Вам понадобится много кофе.

Ответ 3

Написание собственного С++-компилятора сложно. Lexing С++ достаточно плох, так как лексер должен знать, в каком состоянии находится парсер (вложенные определения шаблонов). Еще нет проверенной грамматики YACCable для С++, даже если задана правильная лексер, поэтому у вас могут быть еще худшие проблемы.

Тем не менее, я дам вам несколько указателей.

  • Сначала напишите препроцессор С++.
  • Пишите анализатор/лексер с помощью основной программы, которая красиво печатает дерево разбора.
  • Расширьте эту программу для создания таблиц пространства имен и уловите символы undefined.
  • Измените эту программу, чтобы вывести все выражения в постфиксной нотации.
  • Напишите базовый компилятор от этого парня, выводя некоторую промежуточную сборку для этого парня. Игнорировать inline/volatile/const/register на данный момент. Вам понадобится "вызов внешнего" в вашей сборке.
  • Напишите интерпретатор промежуточной сборки. Посмотрите, работает ли компилятор.
  • Внесите #file и #line в компилятор (тогда и препроцессор будет изрыгать). Это сэкономит вам боль на следующем шаге.
  • Добавьте в компилятор достаточное количество возможностей для компиляции. Поскольку у вас еще нет модулей, используйте препроцессор (один файл # включает все остальные)
  • Архивируйте все это.
  • Начните использовать свой компилятор в качестве своего собственного компилятора bootstrap (это очень быстро курит ошибки).
  • Напишите основную сборку сборки сборки → . Передайте это через ассемблер, чтобы получить объектные файлы, которые вы можете связать с исполняемыми файлами.
  • Архив всех этих
  • Начните использовать ваш компилятор с помощью сборщика ассемблера для компиляции. Это высветит еще больше ошибок.
  • Напишите главный двоичный код, который может вызывать все этапы.
  • Продолжайте добавлять функции до тех пор, пока не получите все необходимые функции.

Или отказаться от этого проекта и рассмотреть g++. Даже если у вас новая комбинация архитектуры процессора и ОС, вам будет легче переносить g++ на нее, чем писать свои собственные.

Ответ 4

Как многие говорили, очень сомнительно, что любая команда одного человека получит какую-либо значимость с помощью компилятора С++.

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

  • Сосредоточьтесь на самокомпилируемом аспекте. Начните с очень крошечного языкового ядра, что даже меньше обычного c (сначала забудьте С++). Как только он сможет скомпилировать себя, добавьте функции по одному, пока не получите С++ (или, скорее, отказаться от возможной жары-смерти Вселенной).
  • Разделите каждую часть системы на маленькие биты. Например, лексер может быть легким, если вы используете стандартную библиотеку регулярных выражений для большей части работы. Это будет медленным, но вы можете получить это довольно твердо в течение нескольких дней.
  • Многие говорили, что начинаются с С++ to C переводчика, похожего на Cfront. Это слишком много ускользает. начните с Verifier. Это только проверяет, что программа хорошо сформирована и будет компилироваться. Добавление анализатора, которое переводится в промежуточное абстрактное синтаксическое дерево, может быть добавлено в верификатор с относительной легкостью, а использование AST для выдачи машинного кода (на языке C или ассемблере или машинного кода) также является небольшим шагом.
  • Хотя я вижу прелесть в том, что вы не используете библиотеки, потому что тогда вам нужно слишком много компилировать, я не уверен, что сделаю то же самое. Во-первых, BOOST увеличит вашу производительность. У Boost есть всевозможные полезные инструменты для создания и обработки структур данных, необходимых для создания компилятора.
  • Одна из самых сложных частей получения компилятора С++ - правильная обработка шаблонов. Предполагается, что компоновщик удаляет повторяющиеся экземпляры шаблонов из разных единиц компиляции, так что присутствует только один из каждого экземпляра. Дубликаты другого кода являются ошибкой. Я бы просто удалил все дубликаты, даже если это ошибки. Или что-то вроде этого. Из стандартного варианта можно отказаться, не нарушая при этом действительного кода в любом месте, где он может помочь.

Ответ 5

Вам нужно bootstrap ваш компилятор. Также прочитайте Книга Дракона (обязательная ссылка).

Ответ 6

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

Требуется ли вашему компилятору поддерживать все возможности С++?

  • Если ему нужен, чтобы поддерживать/компилировать каждую функцию С++, тогда это большой проект! Он слишком велик, чтобы быть домашним заданием, ИМО, поэтому должен быть какой-то важный факт об этом задании, о котором вы не упомянули.

  • Если ему не требуется, чтобы поддерживать/компилировать каждую функцию С++ (если вместо этого она должна поддерживать только подмножество С++ и, в частности, подмножество, которое оно использует в своей собственной реализации, чтобы оно могло скомпилировать себя), тогда вам следует избегать использования STL и Boost в вашей реализации: поскольку STL и Boost реализованы с использованием шаблонов, поэтому, если ( и только если) вы их используете, вам придется включить/реализовать поддержку для компиляции шаблонов.

Ответ 7

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

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

Ответ 8

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

Однако, если вы хотите создать компилятор С++ в С++, я бы подумал, что создание его с использованием библиотек, таких как Boost или Standard С++, было бы неплохо, потому что вам все равно придется создавать код с использованием этих библиотек, Я бы счел это бонусом, если ваш компилятор будет использовать эти библиотеки и будет самостоятельным хостингом, так как у вас там довольно массивный тестовый пример.

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

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

Ответ 9

Я впечатлен вашим энтузиазмом.

Задумывались ли вы о том, какой формат файла вы хотите создать? объектные файлы? библиотечные файлы? исполняемые файлы? COFF/ELF/etc

Вы можете посмотреть на создание более простого компилятора, который генерирует C-код, т.е. как был создан для С++ в начале. См. CFront. Это может быть способом изначально сосредоточиться на синтаксическом анализе С++.

Добавлен

Уверен, что ваш лектор имел в виду С++? Возможно, задача заключалась в том, чтобы изобрести простой язык, на котором вы могли бы написать компилятор. Я думаю, что Lisp обычно используется в академических целях для такой задачи.

Ответ 10

Это высококачественные ответы.

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

Если он только должен скомпилировать себя, есть множество функций, которые вы можете оставить, например, шаблоны.

Можно ли использовать готовый препроцессор?

Нужно ли генерировать код сборки или просто C? C намного проще, очевидно.

Для разбора вам понадобится LR1 (yacc или эквивалент).

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