C 预处理器的替代品

发布于 2024-07-10 03:21:29 字数 1560 浏览 8 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

笔落惊风雨 2024-07-17 03:21:29

您可以使用 PHP 作为 C 预处理器。 优点是:

  • 语法非常相似,因此语法突出显示有效。
  • ?> 在标准 C 中不使用(对于非标准 C,唯一被破坏的是返回 min/max 的旧 GCC 扩展运算符)
  • 它有丰富的图书馆。
  • 它是图灵完备的。
  • 宏的使用非常明确。 (与偷偷摸摸的 C 预处理器宏相比)

不过,为了认真使用,需要让 PHP 打印 #line 指令来调试预处理代码。

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

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

You can use PHP as a C preprocessor. The advantages are:

  • very similiar syntax, so syntax highlighting works.
  • <? and ?> are not used in standard C (with non-standard C, the only thing that gets broken is old GCC extension operator that returns min/max)
  • it's rich in libraries.
  • it's turing complete.
  • usage of macros is very explicit. (compared to sneaky C preprocessor macros)

For serious use though, making PHP print the #line directives is needed for debugging preprocessed code.

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

int main()
{
    <?php
        for($i = 0; $i < 20; $i++)
            echo 'printf("%d\n", '.$i.');';
    ?>
}
风吹过旳痕迹 2024-07-17 03:21:29

Cog 并不完全是一个预处理器,但它确实在代码中内联并生成即时的东西。

Cog isn't exactly a pre-processor, but it does go in-line in the code and generates stuff on the fly.

当爱已成负担 2024-07-17 03:21:29

您可能需要考虑 m4。
http://www.gnu.org/software/m4/

You might want to consider m4.
http://www.gnu.org/software/m4/

南风起 2024-07-17 03:21:29

运行代码,然后将其结果拼接的想法称为准引用。 您运行的代码是反引号的。

我知道如何使用Lua解决这个问题。 我将 string.gsub我自己编写的反引号函数结合使用。 我使用 shell 语法进行反引号。 与在 shell 中一样,反引号代码返回一个字符串,然后将其拼接到代码中。

下面的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 '^%$%((.*)%)

在使用中,程序如下所示:

: nr@curlycoat 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");
}
return assert(loadstring(body))() end prog = prog:gsub('%$%b()', antiquote) io.stdout:write(prog)

在使用中,程序如下所示:

The idea that you run code, the result of which is then spliced in is called quasiquotation. The code you run is antiquoted.

I know how to solve this problem using Lua. I've used string.gsub with an antiquotation function I wrote myself. I've used shell syntax for the antiquotation. As in the shell the antiquoted code returns a string which is then spliced into the code.

Below prog is the C code with antiquoted text, and antiquote is the antiquotation function. I've used Lua's special string quoting double square brackets to full advantage. In practice you wouldn't do this; you'd put prog in a separate file.

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 '^%$%((.*)%)

In use, the program looks like this:

: nr@curlycoat 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");
}
return assert(loadstring(body))() end prog = prog:gsub('%$%b()', antiquote) io.stdout:write(prog)

In use, the program looks like this:

泅渡 2024-07-17 03:21:29

当然,标准 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的维护者。 如果您有疑问,请随时给我留言!

Sure, the standard C preprocessor is very limited.
I've done such a tool recently: https://github.com/d-ash/perlpp

For example this

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

becomes this

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

Syntax is similar to PHP, but it uses Perl instead, and can capture texts into Perl stings.

Edit by cxw — With @d-ash's approval, I am also a maintainer of perlpp. If you have questions, feel free to drop me a line!

莫言歌 2024-07-17 03:21:29

如果您稍微抽象一下您的问题,那么您实际上正在为您的代码寻找模板引擎。 正如大多数网站在静态模板中插入动态生成的内容一样,您希望将动态生成的代码插入到您的程序中。

我目前使用Jinja2 (Python) 来完成大多数模板工作 - 我发现它在各个方面都非常可配置。

If you abstract your problem a bit, then you are in fact looking for a templating engine for your code. Just as most websites inserts dynamically generated content in static templates, you want to insert dynamically generated code into your program.

I currently use Jinja2 (Python) for most templating work - I've found it to be very configurable in every way.

绝不放开 2024-07-17 03:21:29

如果您准备好接触一些 C++,Boost 中有 Wave 解析器,它是使用 Spirit 递归下降解析器构建的。 它是一个完整的 C 预处理器,符合 C 和 C++(以及扩展的 Objective C、AFAICS)的所有最新规范。

它是高度模块化的,因此您可以切换自己的驱动程序,以完成您想要的额外操作。

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

If you're prepared to get your hands dirty with some C++, there's the Wave parser in Boost, which is built using the Spirit recursive descent parser. It's a complete C pre-processor that conforms to all the latest specs for C and C++ (and, by extension, Objective C, AFAICS).

It's highly modular so you can switch your own driver in that could do the extras you want.

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

飘落散花 2024-07-17 03:21:29

CPP 为 C 代码做了许多重要的事情,您可能不需要重新实现这些事情。 您似乎正在寻找的可能是发出 C 代码的模板化过程。

Cheetah 只是众多允许您使用 python 的工具之一。 还有其他语言使用 python,甚至更多使用其他语言,但 Cheetah 因与输出无关而闻名,其中一些模板引擎非常适合 HTML/XML。 做你的研究。

CPP does many important things for C code that you probably don't need re-implemented. What you seem to be looking for instead may be a templating process that emits C code.

Cheetah is just one of many that allows you to use python. There are others that use python and still more in other languages, but Cheetah is known for being output-agnostic where some templating engines are very heavily geared towards HTML/XML. Do your research.

酒儿 2024-07-17 03:21:29

我过去也考虑过同样的问题。 确保您同意这样一个事实:任何想要编译您的代码的人也都需要新的预处理工具。 如果您是唯一一个愿意从事该工作的人,没问题,但如果您想让代码可供其他人使用,那么您可能需要考虑添加工具要求是否是一个好主意。

I've thought about this same problem in the past. Make sure you are OK with the fact that anyone who wants to compile your code will need the new pre-processing tool as well. If you are the only one who will ever work on it, no problem, but if you want to make the code available to others, then you might want to consider whether or not adding a tool requirement is a good idea.

十秒萌定你 2024-07-17 03:21:29

最简洁的答案是不。” 预处理器与 C 的语义如此紧密地联系在一起,以至于你无法真正删除它,事实上,在某些编译器中,它甚至不是像过去那样的一个单独的阶段 --- 在 a 上编译 Objective C Mac 只是解析 Objective C 语法。 因此,虽然您当然可以使用另一个宏处理器(例如 m4)在将源文本传递给 C 之前对其进行处理,但您不会消除 C 预处理器,而是添加 预处理的另一个步骤。

但这里有一个更深层次的问题:通过消除 CPP 阶段您希望获得什么?

The short answer is "no." The preprocessor is so intimately tied to the semantics of C that you can't really remove it, and in fact in some compilers isn't even a separate phase like it used to be in the old days --- compiling Objective C on a Mac just parses the Objective C syntax. So while you could certainly use another macro-processor, like m4, to process your source text before passing it to C, you wouldn't be eliminating the C preprocessor, you'd be adding another step of preprocessing.

But there's a deeper question here: what do you want to gain by eliminating the CPP phase?

当爱已成负担 2024-07-17 03:21:29

您可以使用您最喜欢的编程语言构建脚本/工具来生成源文件(.c/.cpp 或 .h 或其他文件)。 只需 #include 它们或将它们编译到您的项目中。 在 #include 附近添加注释可能有助于识别该工具的位置/位置以及生成的内容。

这可能不像使用“真正的”预处理器那么方便(或干净),但它会起作用。 话又说回来,这真的取决于你的情况。

You can use your favourite programming language to build a script/tool to generate source files (.c/.cpp or .h, or whatever). Simply #include them or compile them into your project. It may help to have comments near the #include to identify what/where the tool is and what is generated.

This may not be as handy (or clean) as using a "real" preprocessor, but it would work. Then again, it really depends on your case.

烟酉 2024-07-17 03:21:29

我看到一篇 2001 年的论文介绍了一个类似 python 的预处理器 http ://ray.cg.tuwien.ac.at/rft/Papers/PYM/pym.html。 不清楚有没有人用过..

I see a 2001 paper introducing a python-like pre-processor http://ray.cg.tuwien.ac.at/rft/Papers/PYM/pym.html. It's not clear that anyone is using it..

清晰传感 2024-07-17 03:21:29

我很想看看人们会想出什么。 我倾向于使用用 Perl 编写的预处理器来做一些小的定制事情。 构建一个调用预处理器的 Makefile 很容易。 例如,以下规则调用名为“meta”的程序从“file.c.meta”生成“file.c”。

% :: %.meta
    meta 
lt; > $@

我正在用“元”做一些有趣的事情,比如生成定制的 C 数据结构。 这绝对是我建议探索的一个方向。 我的希望是最终能提出一个与 C++ 模板大致平行的元库。

I'd be interested to see what people come up with. I've tended to do small custom things with preprocessors written in Perl. It's easy to rig up a Makefile that calls the preprocessor. For example, here's a rule to call a program named 'meta' to generate 'file.c' from 'file.c.meta'.

% :: %.meta
    meta 
lt; > $@

I'm doing fun things with 'meta' like generating custom fit C data structures. It's definitely a direction I'd suggest exploring. My hope is to eventually come up with a meta library roughly parallel to C++ templates.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文