1 回答

TA贡献1784条经验 获得超8个赞
它看起来像是对类似作用域的结构的c_generator.CGenerator调用_generate_stmt方法,即使它是一个空字符串,它也会(带有缩进)附加到 for 语句的结果。';\n'visit
要删除函数调用,我们可以像这样重载它
class RemoveFuncCalls(c_generator.CGenerator):
def _generate_stmt(self, n, add_indent=False):
if isinstance(n, c_ast.FuncCall):
return ''
else:
return super()._generate_stmt(n, add_indent)
接着就,随即
void main()
{
x = 1;
}
这看起来像你想要的。
让我们考虑一个案例
if (bar(42, "something"))
return;
如果我们需要它成为
if ()
return;
然后我们需要添加
def visit_FuncCall(self, n):
return ''
就像在 OP 中一样,因为_generate_stmt不被字段序列化的RemoveFuncCalls.visit_If方法调用。cond
走得更远
我不知道“使用 pycparser 从 AST 中删除节点/子树的规范/惯用方法”,但我确实知道aststdlib 中的模块——ast.NodeTransformer类pycparser(由于某种原因不存在)。
它将允许我们str通过重写私有方法和修改 AST 本身来避免弄乱 AST 的序列化方式
from pycparser import c_ast
class NodeTransformer(c_ast.NodeVisitor):
def generic_visit(self, node):
for field, old_value in iter_fields(node):
if isinstance(old_value, list):
new_values = []
for value in old_value:
if isinstance(value, c_ast.Node):
value = self.visit(value)
if value is None:
continue
elif not isinstance(value, c_ast.Node):
new_values.extend(value)
continue
new_values.append(value)
old_value[:] = new_values
elif isinstance(old_value, c_ast.Node):
new_node = self.visit(old_value)
setattr(node, field, new_node)
return node
def iter_fields(node):
# this doesn't look pretty because `pycparser` decided to have structure
# for AST node classes different from stdlib ones
index = 0
children = node.children()
while index < len(children):
name, child = children[index]
try:
bracket_index = name.index('[')
except ValueError:
yield name, child
index += 1
else:
name = name[:bracket_index]
child = getattr(node, name)
index += len(child)
yield name, child
对于我们的例子,它可以简单地被子类化
class FuncCallsRemover(NodeTransformer):
def visit_FuncCall(self, node):
return None
并像使用
...
ast = parser.parse(text)
v = FuncCallsRemover()
ast = v.visit(ast) # note that `NodeTransformer` returns modified AST instead of `None`
之后我们可以使用未修改c_generator.CGenerator的实例并获得相同的结果。
添加回答
举报