Ответ @Lothars может быть «циничным», но, к сожалению, он довольно близок к истине. Чтобы реализовать что-то вроде @encode()
, вам нужен полноценный синтаксический анализатор для извлечения информации о типе. Ну, по крайней мере, для всего, кроме «тривиальных» операторов @encode()
(т. е. @encode(char *)
). Современные компиляторы обычно имеют два или три основных компонента:
- Передняя часть.
- Промежуточный конец (для некоторых компиляторов).
- Задний конец.
Внешний интерфейс должен анализировать весь исходный код и в основном преобразовывать текст исходного кода во внутреннюю, «пригодную для использования машиной» форму.
Серверная часть переводит внутреннюю, «пригодную для использования машиной» форму в исполняемый код.
Компиляторы, у которых есть «промежуточный конец», обычно делают это из-за какой-то необходимости: они поддерживают несколько «внешних интерфейсов», возможно, состоящих из совершенно разных языков. Другая причина заключается в упрощении оптимизации: все этапы оптимизации работают с одним и тем же промежуточным представлением. Набор компиляторов gcc
является примером "трехступенчатого" компилятора. llvm
можно считать компилятором «промежуточного и внутреннего уровня»: «виртуальная машина низкого уровня» является промежуточным представлением, и вся оптимизация происходит в этой форме. llvm
также может удерживать его в этом промежуточном представлении вплоть до последней секунды — это позволяет «оптимизировать время соединения». Компилятор clang
на самом деле представляет собой «передний конец», который (эффективно) выводит llvm
промежуточное представление.
Итак, если вы хотите добавить функциональность @encode()
к «существующему» компилятору, вам, вероятно, придется сделать это как «компилятор/препроцессор» «от источника к источнику». Именно так были написаны исходные компиляторы Objective-C и C++ — они анализировали входной исходный текст и преобразовывали его в «обычный C», который затем передавался стандартному компилятору C. Есть несколько способов сделать это:
Сверните свой собственный
- Используйте
yacc
и lex
, чтобы собрать парсер ANSI-C. Вам понадобится грамматика — грамматика ANSI C (Yacc) а> это хорошее начало. На самом деле, чтобы внести ясность, когда я говорю yacc
, я на самом деле имею в виду bison и flex
. А также другие различные yacc
и lex
подобные инструменты на основе C: lemon, dparser и т. д....
- Используйте
perl
с Yapp или EYapp, которые являются псевдо-yacc
клонами в perl
. Вероятно, лучше подходит для быстрого прототипирования идеи по сравнению с yacc
и lex
на основе C - в конце концов, это perl
: регулярные выражения, ассоциативные массивы, отсутствие управления памятью и т. д.
- Создайте свой парсер с помощью Antlr. У меня нет опыта работы с этой цепочкой инструментов, но это еще один инструмент «компилятор компилятора», который (кажется) больше ориентирован на разработчиков Java. По-видимому, существуют свободно доступные грамматики C и Objective-C.
Взломать другой инструмент
Примечание. У меня нет личного опыта использования какого-либо из этих инструментов для добавления @encode()
, но я подозреваю, что они очень помогут.
- CIL. Личного опыта работы с этим инструментом нет, но он предназначен для разбора исходного кода C, а затем "выполнения вещи" с ним. Из того, что я могу почерпнуть из документации, этот инструмент должен позволить вам извлечь необходимую информацию о типе.
- Sparse — стоит посмотреть, но не уверен.
- clang — не использовал его для этой цели, но якобы одной из целей было сделать его «легко взломанным». "только для таких вещей. В частности (и опять же, без личного опыта) при выполнении «тяжелой работы» всего синтаксического анализа, что позволяет вам сосредоточиться на «интересной» части, которая в данном случае будет извлекать контекстно-зависимую информацию о типе синтаксиса, а затем преобразовать ее в на простую строку C.
- плагины gcc — плагины представляют собой gcc 4.5 (текущая альфа-версия/ бета-версия компилятора) и «могут» позволить вам легко подключиться к компилятору для извлечения необходимой информации о типе. Понятия не имею, допускает ли архитектура плагина такие вещи.
Другие
- Coccinelle – недавно добавил это в закладки, чтобы "посмотреть позже". Это «может» сделать то, что вы хотите, и «может» сделать это без особых усилий.
- MetaC — недавно тоже добавил это в закладки. Не представляю, насколько это будет полезно.
- mygcc — «Может» делать то, что вы хотите. Это интересная идея, но она не применима напрямую к тому, что вы хотите. С веб-страницы: «Mygcc позволяет программистам добавлять свои собственные проверки, которые учитывают синтаксис, поток управления и информацию о потоке данных».
Ссылки.
Правка №1, бонусные ссылки.
@Lothar делает хороший вывод в своем комментарии. На самом деле я собирался включить lcc
, но, похоже, он потерялся по пути.
- lcc — компилятор
lcc
C. Это компилятор C, который особенно мал, по крайней мере, с точки зрения размера исходного кода. У него также есть книга, которую я очень рекомендую.
- tcc — компилятор
tcc
C. Не так поучительно, как lcc
, но определенно стоит посмотреть.
- poc — компилятор
poc
Objective-C. Это компилятор Objective-C "от источника к источнику". Он анализирует исходный код Objective-C и генерирует исходный код C, который затем передает gcc
(ну, обычно gcc
). Имеет ряд расширений/функций Objective-C, недоступных в gcc
. Определенно стоит посмотреть.
person
johne
schedule
14.02.2010