Сколько времени потребовалось бы для записи компилятора C++ с помощью flex/yacc?

Сколько времени потребовалось бы для записи компилятора C++ с помощью lex/yacc?

Где я могу начать с ним?

17
задан lesmana 6 May 2013 в 11:13
поделиться

13 ответов

Существует множество правил синтаксического анализа, которые не могут быть разобраны парсером bison/yacc (например, проведение различия между объявлением и вызовом функции при некоторых обстоятельствах). Кроме того, иногда для интерпретации лексем требуется ввод от синтаксического анализатора, особенно в C++0x. Например, работа с символьной последовательностью >> очень сильно зависит от контекста парсинга.

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

yacc и bison - это LALR(1) генераторы парсеров, которые недостаточно сложны для эффективной работы с Си++. Как отмечали другие люди, большинство C++ компиляторов сейчас используют рекурсивное снижение парсер, и несколько других ответов указали на хорошие решения для написания своих собственных.

C++ шаблонов не очень хороши для работы со строками, даже с константными (хотя это можно исправить в C++0x, я тщательно не исследовал), но если бы это было так, то можно было бы довольно легко написать рекурсивный парсер понижения на языке шаблонов C++. Я нахожу это довольно забавным.

21
ответ дан 30 November 2019 в 10:16
поделиться

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

Парсер Elsa (и мой компилятор ellcc) используют генератор компилятора Elkhound GLR.

В любом случае, написание компилятора C++ - большая работа.

.
0
ответ дан 30 November 2019 в 10:16
поделиться

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

Например, если вы используете LLVM, то можете работать быстрее. Она уже предоставляет множество инструментов, ассемблера, компоновщика, оптимизатора..... Можно получить препроцессор c из проекта boost... Нужно создать тестовый набор для автоматического тестирования компилятора.

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

.
2
ответ дан 30 November 2019 в 10:16
поделиться

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

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

Если вы делаете гугл для "грамматики C++", то для начала есть пара.

C++ LEX  Tokens:   http://www.computing.surrey.ac.uk/research/dsrg/fog/CxxLexer.l
C++ YACC Grammer:  http://www.computing.surrey.ac.uk/research/dsrg/fog/CxxGrammar.y
                   http://www.computing.surrey.ac.uk/research/dsrg/fog/CxxTester.y
2
ответ дан 30 November 2019 в 10:16
поделиться

Во-первых, тег "flex" на SO относится к продукту Adobe, а не к генератору лексеров. Во-вторых, Bjarne Stroustrup записывает, что он хотел бы реализовать Cfront (первый компилятор C++), используя рекурсивный спуск, а не табличный инструмент. И в-третьих, ответить на ваш вопрос напрямую - лот. Если вы считаете, что вам нужно написать один, посмотрите на ANTLR - не самый мой любимый инструмент, но для него уже есть парсеры C++.

.
3
ответ дан 30 November 2019 в 10:16
поделиться

Компилятор C++ очень сложен. Чтобы реализовать достаточно Си++ для совместимости с большинством Си++ кода, потребуется несколько разработчиков за пару лет. clang - это проект компилятора, финансируемый компанией Apple для разработки нового компилятора для C, C++ и Objective-C, в котором участвуют несколько штатных разработчиков, а поддержка C++ все еще очень далека от завершения после пары лет разработки.

1
ответ дан 30 November 2019 в 10:16
поделиться

Это нетривиальная проблема, и для ее правильного решения понадобилось бы немало времени. Во-первых, грамматика для С++ не полностью поддается разбору парсером LALR, таким как yacc. Можно делать подмножества языка, но исправить всю спецификацию языка сложно.

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

Вот важная цитата из статьи:

"После множества исследований, я решил, что написание парсер/инструмент анализа для C++ - это достаточно трудно, чтобы Проблема с этой статьей в том, что она немного старая, и некоторые из ссылок разбиты. Вот несколько ссылок на некоторые другие ресурсы по написанию парсеров на C++:

3
ответ дан 30 November 2019 в 10:16
поделиться

Долгое время, и lex и yacc не помогут

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

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

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

.
6
ответ дан 30 November 2019 в 10:16
поделиться

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

Парсинг C++, как известно, подвержен ошибкам. Грамматика не полностью LR-параметризирована, так как многие ее части чувствительны к контексту. Вы не сможете заставить его работать корректно в flex/yacc, или, по крайней мере, его будет очень неудобно реализовать. Есть только два фронт-конца, которые, как я знаю, позволяют сделать все правильно. Лучше всего использовать один из них и сконцентрироваться на написании бэк-энда. Вот где интересный материал :-).

Существующие C++ Front Ends:

  1. Фронтенд EDG используется большинством коммерческих вендоров (Intel, Portland Group, и т.д.) в их компиляторах. Это стоит денег, но очень тщательно. Люди платят за это большие деньги, потому что они не хотят иметь дело с болью от написания своего собственного парсера C++.

  2. GCC's C++ front-end достаточно тщателен для производственного кода, но вы должны понять, как интегрировать это в ваш проект. Я считаю, что отделить его от GCC достаточно сложно. Это тоже было бы GPL, но я не уверен, является ли это проблемой для вас. Вы можете применять внешний интерфейс GCC в своем проекте с помощью gcc_xml, но это даст вам XML только для классов, функций, пространств имен и набранных определений. Это не даст вам синтаксическое дерево для кода.

  3. Другая возможность - использовать clang, но их поддержка C++ в настоящее время неаккуратна. Будет приятно увидеть, как они вытаскивают все ошибки, но если вы посмотрите на их страницу статуса C++, вы заметите, что есть более чем несколько тестовых случаев, которые все еще ломаются. Примите во внимание - clang - это большой проект. Если у этих ребят уйдут годы на реализацию фронт-энда C++, то это займёт у вас больше времени.

  4. Другие упоминали ANTLR, и для этого есть грамматика C++, но я скептически отношусь к этому. Я не слышал о том, чтобы ANTLR использовался в основных компиляторах, хотя я считаю, что он используется в IDE NetBeans. Возможно, он подходит для IDE, но я скептически отношусь к тому, что вы сможете использовать его в производственном коде.

10
ответ дан 30 November 2019 в 10:16
поделиться

Похоже, вы новичок в создании парсинга/компилятора. Если это так, то я бы настоятельно рекомендовал , а не , начиная с C++. Это чудовище языка.

Или придумайте свой банальный игрушечный язык, или сделайте что-нибудь по образцу чего-нибудь гораздо меньшего и более простого. Я видел парсер lua, где грамматическое определение было около страницы длиной. Это было бы гораздо разумнее в качестве отправной точки.

10
ответ дан 30 November 2019 в 10:16
поделиться

Ну, что вы имеете в виду, написав компилятор?

Сомневаюсь, что хоть один парень создал настоящий компилятор Си++, который записал его на ассемблере, но я использовал lex и yacc, чтобы сделать компилятор Си, и без него.

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

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

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

.
0
ответ дан 30 November 2019 в 10:16
поделиться

Как уже говорили другие, YACC является плохим выбором для реализации анализатора C ++ . Можно сделать это; Оригинал GCC сделал это, до того, как команда GCC произошла отвратительна тем, насколько трудно поддерживать и простираться. (Flex может быть в порядке, как лексером).

Некоторые говорят, что рекурсивные анализаторы спуска лучше всего, потому что сказал Bjarne Strooustrop. Наш опыт - это анализ GLR - это правильный ответ для этого, и наш передний конец C ++ - это хорошее доказательство, как и передний конец ELSA. Наш передний конец использовался в гневе на миллионах строк C ++ (включая диалекты Microsoft и GCC) для проведения анализа программы и массового преобразования исходного кода.

Но то, что не подчеркивается достаточно, так это то, что разбор - это просто очень маленькая часть того, что требуется для создания компилятора, особенно для C ++. Вам необходимо также создавать таблицы символов («Что означает этот идентификатор в этом контексте?») И делать то, что вам необходимо в конечном итоге кодировать большую часть нескольких сотен страниц стандарта C ++. Мы считаем, что основа, на котором мы построим компиляторские инструменты, DMS , чрезвычайно хороша для этого, и потребовалось нас за человеком, чтобы получить только эту деталь.

Но тогда у вас есть остальная часть компилятора для рассмотрения:

  • Preprocessor
  • AST Construction
  • семантический анализ и проверка типа
  • Управление, поток данных и анализ указателя
  • Базовый генерация кода
  • Оптимизация
  • Распределение регистров
  • Окончательное поколение кода
  • Поддержка отладки

Я продолжаю говорить это: построение анализатора (часть BNF) для языка похоже на восхождение на предгорью Гималаи. Строительство полного компилятора - это как восхождение Everest. В значительной степени любой CLOD может сделать прежнее (хотя C ++ прямо на краю). Только действительно серьезные делают последнее, и только когда очень хорошо подготовлены.

Ожидайте, что создание компилятора C ++, чтобы взять вас годы.

(передний конец SD C ++ обрабатывает Lexing, Parsing, AST Generation, таблицы символов, проверка некоторых типов и регенерация коммуникационного исходного текста из AST, включая оригинальные комментарии, для основных диалектов C ++. срок около 6 лет).

Редактировать: май 2015 года. Оригинальный ответ был написан в 2010 году; У нас сейчас 11 лет инвестировано, забрав нас через C ++ 14. Дело в том, что это бесконечное, большие усилия для построения одного из них.

3
ответ дан 30 November 2019 в 10:16
поделиться

Несколько лет - если вы сможете получить исследовательский грант на написание нового lex/yacc :-)

Люди продолжают гоняться за своими хвостами в этом вопросе - начиная со Струструпа, который всегда считался "дизайнером" языка, а не автором компилятора (вспомните, что его C++ был просто codegen в течение многих лет и был бы им до сих пор, если бы не gcc и другие люди).

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

По сути, вам нужна разумная золотая середина - например, LALR(2) с фиксированной, ограниченной обратной трассировкой (плюс статическая проверка, которая будет кричать, если "desiogner" вклинится в недетерминированное дерево), а также ограниченная и разделенная обратная связь по таблице символов (современный парсер должен быть дружественным к параллелизму).

Звучит как предложение на исследовательский грант, не так ли :-) Теперь, если мы найдем кого-то, кто действительно его профинансирует, это будет нечто :-))

.
1
ответ дан 30 November 2019 в 10:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: