我有兴趣使用C预处理器以外的东西来预处理我的C和Objective-C源代码.有好的选择吗?
一个例子是允许一个人逃脱到C代码中间的python或perl片段,并且片段吐出C然后编译为正常.
您可以使用PHP作为C预处理器.优点是:
非常类似的语法,因此语法突出显示起作用.
并且
?>
不用于标准C(使用非标准C,唯一被破坏的是旧的GCC扩展运算符,它返回最小值/最大值)
它的图书馆很丰富.
这是完整的.
宏的用法非常明确.(与偷偷摸摸的C预处理器宏相比)
但是为了认真使用,调试预处理代码需要PHP打印#line指令.
int main() { }
Cog并不完全是一个预处理器,但它确实在代码中内嵌并在运行中生成内容.
你运行代码的想法,然后拼接其结果称为quasiquotation.您运行的代码是反引号.
我知道如何使用Lua解决这个问题.我已经使用string.gsub
了我自己编写的反引号函数.我已经使用shell语法进行反引号.与在shell中一样,反引号代码返回一个字符串,然后将其拼接到代码中.
下面prog
是带反引号文本的C代码,antiquote
是反引号函数.我已经使用Lua的特殊字符串引用双方括号来充分利用它. 在实践中你不会这样做 ; 你要放prog
一个单独的文件.
names = { 'John', 'Paul', 'George', 'Ringo' } local prog = [===[ #includemain() { $(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)
在使用中,程序看起来像这样:
: nr@curlycoat 1181 ; lua /home/nr/tmp/emit-c.lua #includemain() { 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"); }
你可能想要考虑m4.
http://www.gnu.org/software/m4/
如果你已准备好接受一些C++,那么Boost中的Wave解析器就是使用Spirit递归下降解析器构建的.它是一个完整的C预处理器,符合C和C++的所有最新规范(以及扩展,Objective C,AFAICS).
它是高度模块化的,因此您可以切换自己的驱动程序,这可以做您想要的额外功能.
http://www.boost.org/libs/wave/doc/introduction.html
如果您稍微抽象出问题,那么您实际上正在为您的代码寻找模板引擎.正如大多数网站在静态模板中插入动态生成的内容一样,您希望将动态生成的代码插入到程序中.
我目前使用Jinja2(Python)进行大多数模板工作 - 我发现它在各方面都是非常可配置的.
当然,标准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 stings中.
由cxw 编辑 - 在@ d-ash的批准下,我也是perlpp的维护者.如果您有任何疑问,请随时给我留言!