- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
让我们首先考虑这个片段:
import sys
from pycparser import c_parser, c_ast, c_generator
text = r"""
void main() {
foo(1,3);
foo1(4);
x = 1;
foo2(4,
10,
3);
foo3(
"xxx"
);
}
"""
class FuncCallVisitor(c_ast.NodeVisitor):
def visit_FuncCall(self, node):
print('%s called at %s' % (node.name.name, node.name.coord))
if node.args:
self.visit(node.args)
class RemoveFuncCalls(c_generator.CGenerator):
def visit_FuncCall(self, n):
# fref = self._parenthesize_unless_simple(n.name)
# return fref + '(' + self.visit(n.args) + ')'
return ""
if __name__ == '__main__':
parser = c_parser.CParser()
ast = parser.parse(text)
v = FuncCallVisitor()
v.visit(ast)
print('-' * 80)
ast.show(showcoord=True)
generator = RemoveFuncCalls()
print('-' * 80)
print(generator.visit(ast))
上面的输出将是:
void main()
{
;
;
x = 1;
;
;
}
但我希望它变成这样:
void main()
{
x = 1;
}
所以我的问题是,使用 pycparser 从 AST 中删除节点/子树的规范/惯用方法是什么?
最佳答案
看起来像c_generator.CGenerator
调用_generate_stmt
method对于类似范围的结构which appends ';\n'
(带缩进)到 visit
for 语句的结果,即使它是空字符串。
要删除函数调用,我们可以重载它,例如
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 中删除节点/子树的规范/惯用方法”,但我确实知道 stdlib 中的 ast
模块 - ast.NodeTransformer
class (由于某种原因,pycparser
中不存在)。
它将使我们能够通过覆盖私有(private)方法并修改 AST 本身来避免混淆 AST 序列化为 str
的方式
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
实例并获得相同的结果。
关于python - 如何使用 pycparser 删除 AST 节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60195762/
我正在尝试检查 Go 源代码以制作一个工具。为此,我使用 ast.Inspect 函数。 我需要知道函数/方法内部如何使用 channel 。 我将此作为要检查的示例代码: package main
我正在为我自己的语言制作一个解释器作为一个业余爱好项目。目前我的解释器只是执行它看到的代码。我听说你应该让解析器从源代码生成 AST。所以我想知道,正如解析器所见,AST 实际上如何使事情比仅仅线性执
我正在为 JavaScript 实现一个突变测试工具。修改 AST 并针对修改后的代码执行测试用例。运行测试用例后,我想将修改后的 AST 恢复为原始 AST,以便我可以重复变异过程。但是,我不知道如
AST 文档:https://www.dartdocs.org/documentation/analyzer_experimental/0.8.0/analyzer/parseCompilationU
更新2:再次感谢@deepak-azad,我设法解决了我的问题:这里是主代码的链接:https://gist.github.com/1714641 更新:感谢@deepak-azad,我补充了代码,但
我正在编写一些 Go AST 代码,而编译器在这一行上令人窒息: var call ast.Expr = ast.CallExpr{Fun: ast.NewIdent("foo"), Args: []
我正在对 c 程序进行静态分析。我搜索了 antlr 网站,似乎没有合适的语法文件为 c 程序生成 ast。这是否意味着我必须从一开始就自己做。或者是有一个更快的方法。我还需要一个可以遍历解析器创建的
是否可以像这样采用带引号的 Elixir 表达式(AST 树): quote do: 1 + 1 => {:+, [context: Elixir, import: Kernel], [1, 1]}
我遇到了这个异常: unexpected AST node: query 我的查询是: SELECT u.user_id, u.username,u.email,u.phone,u.status,r
我是 Java 编程语言的初学者。我想从 java 源代码中提取 AST 并将 AST 打印到文件或标准输出。 我按照本教程学习了如何使用 AST。 http://www.programcreek.c
NodeVisitor 以深度优先的方式遍历 AST,并且在进入时仅访问每个节点一次。因此,用它做一些严肃的事情是有问题的。是否可以更改其默认行为? 最佳答案 也许有人会对一些草拟的例子感兴趣,如何做
目前,我正在努力用 Java 表示我用 SML 编写的 AST 树,这样我就可以随时用 Java 遍历它。 我想知道是否应该在 Java 中创建一个 Node 类,其中包含我想要表示的数据,以及一个数
我正在尝试修改/重构输入的 C 源代码。我试图在输入代码的每一行之后添加一个 printf 语句。 例如如果我的输入是 - void foo(){ // Sample input code
我目前正在使用 eclipse AST 来生成源代码。除了在大多数示例中,我是在独立应用程序中从头开始生成源代码,而不是在 eclipse 插件中。 当从 ASTParser 读取时,您可以通过调用
我有一个 HQL 查询: query = select item.itemNumber from items item where item.stock>0 and item.price it = q
根据 Om Next's documentation : query->ast (om.next/query->ast '[(:foo {:bar 1})]) Given a query expres
如果能学到一些有用的东西,我会非常感激,至于现在,我一直在盲目地行动。所以问题出在python的ast.NodeTransformer上。我想知道是否可以使用这种方式向现有类添加一个函数,而不是生气。
我们希望为 Elixir 开发一个静态代码分析器,以检测并发问题(主要是死锁和竞争条件)。我们对分析器的结构有了一些基本的了解,但我们的问题是哪种 AST 更适合这项任务。正如我们所了解的,Elixi
我在以下代码段中遇到错误 using (var session = Database.OpenSession()) { var q = from x in session.Query()
我正在使用以下 C# 代码: public IList GetAllByExpression(Expression> expression, int startIndex, int count, Fu
我是一名优秀的程序员,十分优秀!