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

Замены для препроцессора C

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

Примером может быть то, что позволило выйти из фрагмента python или perl в середине кода C, а фрагмент фрагмента C затем компилируется как обычно.

4b9b3361

Ответ 1

Вы можете использовать PHP как препроцессор C. Преимущества:

  • очень похожий синтаксис, поэтому подсветка синтаксиса работает.
  • <? и ?> не используются в стандартном C (с нестандартным C, единственное, что сломается - это старый оператор расширения GCC, который возвращает min/max)
  • он богат библиотеками.
  • завершение завершено.
  • Использование макросов очень явное. (по сравнению с скрытыми макросами препроцессора C)

Для серьезного использования, делая PHP-печать, директивы #line необходимы для отладки предварительно обработанного кода.

<?php include_once "stdio.h"; ?>

int main()
{
    <?php
        for($i = 0; $i < 20; $i++)
            echo 'printf("%d\n", '.$i.');';
    ?>
}

Ответ 2

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

Я знаю, как решить эту проблему с помощью Lua. Я использовал string.gsub с функцией антикотажа, которую я написал сам. Я использовал синтаксис оболочки для антикотации. Как и в оболочке, антикобайтный код возвращает строку, которая затем сращается в коде.

Ниже prog - это код C с текстом с анимированным текстом, а antiquote - функция антиобщения. Я использовал специальную строку Lua с двойными квадратными скобками в полной мере. На практике вы бы этого не сделали; вы поместите prog в отдельный файл.

names = { 'John', 'Paul', 'George', 'Ringo' }

local prog = [===[
#include <stdio.h>

main() {
  $(local out = { }
    for _, n in ipairs(names) do
      table.insert(out, string.format([[  printf("The name is %%s\n", %q);]], n))
    end
    return table.concat(out, '\n  ')
   )
}
]===]


local function antiquote(s)
  local body = s:match '^%$%((.*)%)$'
  return assert(loadstring(body))()
end

prog = prog:gsub('%$%b()', antiquote)
io.stdout:write(prog)

При использовании программа выглядит следующим образом:

: [email protected] 1181 ; lua /home/nr/tmp/emit-c.lua
#include <stdio.h>

main() {
    printf("The name is %s\n", "John");
    printf("The name is %s\n", "Paul");
    printf("The name is %s\n", "George");
    printf("The name is %s\n", "Ringo");
}

Ответ 3

Cog - не совсем препроцессор, но он вписывается в код и генерирует все на ходу.

Ответ 5

Если вы готовы заполучить свои руки на каком-то С++, там будет синтаксический анализатор Wave в Boost, который создается с использованием парсера рекурсивного спуска Spirit. Это полный предварительный процессор C, который соответствует всем последним спецификациям для C и С++ (и, соответственно, Objective C, AFAICS).

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

http://www.boost.org/libs/wave/doc/introduction.html

Ответ 6

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

В настоящее время я использую Jinja2 (Python) для большинства шаблонов работы - я нашел, что он очень настраивается во всех отношениях.

Ответ 7

Конечно, стандартный препроцессор C очень ограничен.
Недавно я сделал такой инструмент: https://github.com/d-ash/perlpp

Например, это

<?
    my @types = ('char', 'int', 'long'); 
    foreach (@types) {
?>
        <?= $_ ?> read_<?= uc($_) ?>(<?= $_ ?>* v);
<?  } ?>

становится этим

char read_CHAR(char* v);
int read_INT(int* v);
long read_LONG(long* v);

Синтаксис похож на PHP, но вместо этого он использует Perl и может захватывать тексты в укусах Perl.

Изменить cxw — При утверждении @d-ash, я также поддерживаю perlpp. Если у вас есть вопросы, не стесняйтесь бросать мне строку!

Ответ 8

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

Ответ 9

Короткий ответ - "нет". Препроцессор настолько тесно связан с семантикой C, что вы действительно не можете удалить ее, а на самом деле в некоторых компиляторах нет даже отдельной фазы, как это было в старые времена - компиляция Objective C на Mac просто анализирует синтаксис Objective C. Поэтому, хотя вы, конечно же, можете использовать другой макропроцессор, например m4, для обработки исходного текста перед его передачей на C, вы не исключили бы препроцессор C, вы бы добавили еще один шаг предварительной обработки.

Но здесь есть более глубокий вопрос: чего вы хотите добиться, устраняя этап CPP?

Ответ 10

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

Cheetah является лишь одним из многих, что позволяет использовать python. Есть и другие, которые используют python и еще больше на других языках, но Cheetah известен как выход-агностик, где некоторые шаблонные модули очень сильно ориентированы на HTML/XML. Сделайте свое исследование.

Ответ 11

Я вижу статью 2001 года, в которой представлен предварительный процессор типа python http://ray.cg.tuwien.ac.at/rft/Papers/PYM/pym.html. Не понятно, что кто-то его использует.

Ответ 12

Вы можете использовать свой любимый язык программирования для создания script/инструмента для генерации исходных файлов (.c/.cpp или .h или что-то еще). Просто #include их или скомпилируйте в свой проект. Это может помочь получить комментарии рядом с #include, чтобы определить, что/где инструмент и что генерируется.

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

Ответ 13

Мне было бы интересно узнать, что люди придумали. Я обычно делал небольшие пользовательские вещи с препроцессорами, написанными на Perl. Легко подстроить Makefile, который вызывает препроцессор. Например, здесь правило для вызова программы с именем "meta" для генерации "file.c" из "file.c.meta".

% :: %.meta
    meta $< > [email protected]

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