在Python或JavaScript中实现C预处理器?

13

是否有Python或JavaScript实现的C预处理器工具?我正在寻找一种稳健的方法来预处理C(和类似C的)源代码,并希望能够处理条件编译和宏,而无需调用外部CPP工具或本地代码库。另一个潜在的用例是在Web应用程序中进行预处理,在Web浏览器中进行。

到目前为止,我已经找到了用JavaPerl,以及当然是CC的实现。现在可以使用其中一个C到JavaScript编译器。

PLY(Python Lex和Yacc)工具包包括一个用Python实现的cpp。


7
@billy:预处理器并不简单,一旦考虑到宏,就需要支持行拼接、注释去除、编译指示、符号连接和算术运算。@ira:在无法调用外部工具的情况下(例如在浏览器中或在纯Python环境中),需要执行源代码分析/操作。@karl:我需要一个与特定编译器无关的预处理器,因为实际上我不是在寻求编译,而是在处理代码,当编译器不可用时。 - grrussel
你需要使用Python或JavaScript有什么特别的原因吗?如果你决定自己实现,我建议你使用像Ruby中的treetop这样的解析表达式语法库。 - david4dev
我目前正在使用Python解析器工具(PLY),并希望集成预处理。在Web前端浏览器中,JS可以发挥作用。 - grrussel
7
@Billy: 我花了一个多月的时间,在C++中实现了大部分预处理器(我省略了一些东西,比如多字符字面量和UCN)。总共有超过4,000行非常简明的C++代码,不包括测试套件。宏替换非常复杂。至少,你需要一个词法分析器、条件堆栈、宏替换器、文件管理器、表达式解析器、表达式求值器以及一些较小的组件。你还需要考虑C90、C99、C++03和C++0x。 - James McNellis
如果您正在使用Python,那么调用预处理器不应该是一个问题;我认为它可以外壳。有没有这样的世界?我认为在Javascript中构建静态分析工具不是一个好主意;当您处理它们引用的包含文件时,C/C++程序会变得非常大,并且您需要良好的性能来进行预处理/解析部分以及分析部分。 - Ira Baxter
显示剩余9条评论
5个回答

7

请查看pypreprocessor

它也可以在PYPI(Python软件包索引)上找到,因此可以直接使用pip进行下载。

如果您想要使用#define和#ifdef语句来进行简单的条件编译,那么它应该能够满足您的需求。您可以将其作为独立脚本运行并指定要处理的输入文件(可以是任何语言),或者您可以将其导入为Python模块并用它来自我消耗Python源代码。

pypreprocessor不支持

  • 宏替换
  • 逻辑操作(例如|| &&)
  • 数学操作(例如+ - * /)
  • 多行预处理指令

它是一个专门设计用于条件编译而不是元编程的工具。

以下是使用pypreprocessor作为独立脚本处理C文件的示例:

from pypreprocessor import pypreprocessor

pypreprocessor.defines.append('debug')
pypreprocessor.input = 'input_file.c'
pypreprocessor.output = 'output_file.c'
pypreprocessor.removeMeta = True

pypreprocessor.parse()

这个实现非常简单。

defines.append('debug'):

与在文件中添加“#define debug”指令具有相同的效果。这只是一种方便设置宏定义的方式。

pypreprocessor.input = 'input_file.c':

设置要处理的文件。

pypreprocessor.output = 'output_file.c':

设置输出文件的位置。

pypreprocessor.removeMeta = True:

删除文件中找到的所有预处理器指令。这包括源文件中的所有 #define、#ifdef、#undefine、#else 等等。这对于创建一个“干净”的生产版本的源代码非常有用,该版本减去了所有未使用的条件代码和指令。此步骤完全是可选的。如果您不添加此选项,则任何不符合定义条件的代码都将自动被注释掉。

例如:

#define debug

#ifdef debug
print('this will appear in the postprocessed code')
#else
#print('this will be commented out in the postprocessed code')
#endif

如果您需要宏替换,例如将源语言更改为另一种语言,pyprocessor目前还不支持此功能。理论上,增加此功能不需要太多的工作,但是在跳过出现在文本字符串中的关键字之前,需要先扩展词法分析器。
附注:它也与python2x和python3k兼容。
声明:我是pypreprocessor的作者。

6
请查看PLY,这是一个在Python上实现的Lex和Yacc工具,其中包含一个使用PLY词法分析器实现的Python cpp工具。此外还有pycparser,它是基于PLY构建的C语言解析器。

2
遗憾的是,pycparser不支持C代码,除非在其上调用了预处理器。 - grrussel
pycparser可以为您调用预处理器 - kynan

2
Firefox的构建系统对其chrome做了类似的处理。名为jar.mn的源文件列出了所有所需的XUL/JS文件,这些文件在发货前可选择进行预处理。因此,将文件发送的脚本也会调用一个迷你预处理器。具体请参见JarMaker.pyPreprocessor.py

1

你可以尝试在clang c预处理器周围创建一个Python绑定。


现在libclang已经带有Python绑定。请参见使用Clang在Python中解析C++ - prideout

0
如果ANTLR可以与Python/Javascript一起使用(我非常怀疑后者),您可以从ANTLR网站获取语法:http://www.antlr.org/grammar/1166665121622/Cpp.tar 如果不行,这仍然可能是一个好的开始 - 只需将其转换为您喜欢的解析器生成器所理解的语法即可。

2
很不幸,实现预处理器的难点在于必须编写用于宏替换和受限范围表达式求值的自定义逻辑。 - James McNellis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接