我想部分解析C声明和/或函数定义列表。
也就是说,我想将其拆分为子串,每个子串包含一个声明或函数定义。
然后将每个声明(单独)传递给另一个模块( 包含完整的C解析器,但我无法直接调用。)
显然我可以通过在我的程序中包含另一个完整的C解析器来实现这一点,但我希望避免这种情况。
到目前为止,我遇到的棘手案件涉及'}'
是否终止声明/定义的问题。例如在
int main(int ac, char **av) {return 0;}
...... '}'
是终结者,而在
typedef struct foo {int bar;} *pfoo;
不是。可能还有像这样的病态代码片段:
struct {int bar;} *getFooPtr(...) { /* code... */ }
备注
答案 0 :(得分:1)
据我所知,以下解决方案仅适用于声明(即,必须将函数定义保留在本节之外,或者在它们之后添加分号可能是一种解决方法:)< / p>
;
,我们已经找到了声明的结尾。"
或'
,请跳转到匹配的引号,必要时跳过转义序列。(
,[
或{
,请跳转到匹配的)
,]
或}
(跳过嵌套的括号和必要时递归字符串)如果这被证明是不能令人满意的,我将切换到 clang 解析器。
答案 1 :(得分:1)
要在处理函数定义的答案中扩展状态机,请添加以下步骤:
;
,我们找到了声明的结尾,而不是函数定义(尽管可能是函数声明)。"
或'
,请跳转到匹配的引号,必要时跳过转义序列。(
,[
或{
,请跳转到匹配的)
,]
或}
(跳过嵌套的括号和必要时递归字符串){
.. }
,我们已经找到了声明的结尾,以及它的函数定义(
.. )
,请将fun / var状态设置为“function”。=
或,
,请将fun / var状态设置为'not-function`。当然,这只适用于预处理后的代码 - 如果你的宏有各种奇怪的东西尚未扩展,那么所有的赌注都会关闭。
答案 2 :(得分:0)
您最好的选择是提取与声明相关的C语法部分,并为该语法或缩写版本构建解析器。同样,你想要函数体的语法,以类似的方式缩写,所以你可以跳过它们。
这可能会为声明生成一个相对值得信赖的解析器。
不幸的是,你不太可能得到一个值得信赖的C语法; ANSI标准中的那个不是编译器实际使用的那个。每个供应商都为其编译器添加了好东西和复杂功能(例如,MS C的declspecs等)。
预处理器运行的假设很有意思。您将在哪里获得预处理器配置? (例如,编译器命令行定义,包括路径,编译指示设置等)?这比看起来更难,因为每个开发环境都定义了设置预处理器条件的不同方法。
如果您愿意接受偶然的错误,那么任何启发式算法都是有效的候选者, 以多少方式模拟重要客户端代码的错误。这也意味着您可以处理未经处理的代码,完全避免预处理器问题。