我正在尝试 AST 操作。目前我正在尝试从输入 AST 中删除某些节点。我认为 NodeTransformer 类是实现此目的的合适工具。遗憾的是,它的表现并不如预期。
文档说:
“NodeTransformer 将遍历 AST,并使用访问者方法的返回值来替换或删除旧节点。如果访问者方法的返回值为 None,则该节点将从其位置中删除,否则将替换为返回值。”
现在看看我的程序:
import _ast
import ast
import sys
#ast transformer
class MyTransformer(ast.NodeTransformer):
def iterate_children(self, node):
"""
helper
"""
children = ast.iter_child_nodes(node)
for c in children:
self.visit(c)
def generic_visit(self, node):
"""
default behaviour
"""
print("visiting: "+node.__class__.__name__)
self.iterate_children(node)
return node
def visit_For(self, node):
"""
For nodes: replace with nothing
"""
print("removing a For node")
return None
#read source program
filename = sys.argv[1]
with open (filename, "r") as myfile:
source = …Run Code Online (Sandbox Code Playgroud) tokenize在Python中,如何将模块与模块结合使用ast?两者都使用不同的节点类型,您如何将两者关联在一起?有办法吗?可能是parser模块?
我正在构建一个小型 Java 代码分析工具,想知道是否可以使用令人惊叹的 IntelliJ 编译器来获取 Java 项目的 AST?
IntelliJ几年前在 Apache 2 许可证下开源了社区版本。该项目还可以用作 Java 独立项目中的库(而不是完整 IDE 的插件)来分析 Java 项目吗?Git 存储库相当大,我很感激任何从哪里开始的提示或链接。
(我已经阅读过有关Eclipse JDT 的内容,但创建自己的 Mini-ANTLR-Java 解析器比让 Eclipse JDT 为我工作要容易得多。但如果我可以使用更复杂、始终最新的,那就太棒了-我的项目的 Java AST 的最新版本。所以我的希望寄托在 IntelliJ 编译器上。)
java parsing code-analysis intellij-idea abstract-syntax-tree
给定以下 C++ 文件:
class Foo
{
public:
Foo();
void bar(int input);
void another(int input, double & output);
};
void
Foo::bar(int input)
{
input += 1;
}
void
Foo::another(int input, double & output)
{
input += 1;
output = input * 1.2345;
}
Run Code Online (Sandbox Code Playgroud)
如何利用 clang python 绑定来提取这两个方法的定义。我可以使用下面的 python 脚本获取类声明,但我似乎不知道如何提取完整的方法。例如,我想要以下信息:
void
Foo::another(int input, double & output)
{
input += 1;
output = input * 1.2345;
}
Run Code Online (Sandbox Code Playgroud)
Python脚本:
#!/usr/bin/env python
import clang.cindex
clang.cindex.Config.set_library_path('/opt/moose/llvm-3.7.0/lib')
def getCursors(cursor, output, kind):
"""
Recursively extract all the cursors …Run Code Online (Sandbox Code Playgroud) 我有风格
.a{width: 10px;}
...
.a{width: 20px;}
Run Code Online (Sandbox Code Playgroud)
很明显,第一个选择器未使用。我正在寻找一个工具,可以为我提供有关 css 中此类位置的信息。例如getUnusedRule(styles)-> style.css、规则、选择器等处的行号。别的。
第二种情况是通知过于嵌套的选择器
.a .b .c .d{...}
Run Code Online (Sandbox Code Playgroud)
getTooLongSelectors(styles, maxNestingNum)-> 在源代码中查找位置的信息
我不想缩小输出CSS,但需要在代码中找到这些地方并手动修复它。重点不是缩小代码,而是使源代码更准确,以便更好地维护并防止堆积不必要的东西。
我认为它可能是 css AST 分析器,它输出用于手动源代码改进的信息。
我更喜欢基于javascript的工具,我们团队中有一些 js 程序。
有任何想法吗?不仅欢迎现成的工具,而且欢迎思维方式。
是否可以使用标准 C 语法(如官方 ANTLR4 GitHub 存储库中找到的语法)来实现经典的Yacc 词法分析器 hack,以区分 ANTLR4 生成的 C 解析器中的标识符名称和类型名称?
看来可以插入 ANTLR4 词法分析器的临时代码非常有限。在《The Definitive ANTLR4 Reference》一书中,Terrence Parr 说道:
“一种长期存在的常见做法涉及从解析器向词法分析器发送反馈,以便词法分析器可以向解析器发送精确的标记。[...]不幸的是,这对于 ANTLR 语法来说是不可能的,因为 ANTLR 生成的解析器通常在令牌流中向前看以做出解析决策。[...]”
有什么方法可以规避上述问题并实现反馈循环吗?或者在访问解析树时如果不采取疯狂的黑客手段,在 ANTLR4 中实现 C 解析器是不可能的吗?
我目前正在使用 ast 和 astor 模块来研究抽象语法树。该文档教我如何检索和漂亮打印各种函数的源代码,网络上的各种示例展示了如何通过将一行内容替换为另一行内容或将所有出现的 + 更改为 * 来修改部分代码。
但是,我想在不同的地方插入额外的代码,特别是当一个函数调用另一个函数时。例如,以下假设函数:
def some_function(param):
if param == 0:
return case_0(param)
elif param < 0:
return negative_case(param)
return all_other_cases(param)
Run Code Online (Sandbox Code Playgroud)
会产生(一旦我们使用过astor.to_source(modified_ast)):
def some_function(param):
if param == 0:
print ("Hey, we're calling case_0")
return case_0(param)
elif param < 0:
print ("Hey, we're calling negative_case")
return negative_case(param)
print ("Seems we're in the general case, calling all_other_cases")
return all_other_cases(param)
Run Code Online (Sandbox Code Playgroud)
这对于抽象语法树来说可能吗?(注意:我知道运行代码时调用的装饰函数会产生相同的结果,但这不是我想要的;我需要实际输出修改后的代码,并插入比 print 语句更复杂的东西)。
假设我有一个像这样的变量声明:
std::vector<MyType> myVector(1);
Run Code Online (Sandbox Code Playgroud)
CXXConstructExpr这在 Clang AST 中表示为 a 。我有一个匹配器可以找到 this CXXConstructExpr,但我想MyType从中提取 decl for 。
我尝试了各种各样的方法,但似乎没有任何效果:
const CXXConstructExpr* construct = Result.Nodes.getNodeAs<CXXConstructExpr>("expr");
construct->getConstructor()->getTemplateSpecializationArgs() // Always nullptr
construct->getConstructor()->getParent() // Seems to lose the template parameters
construct->getConstructor()->getDescribedTemplate() // Always nullptr
Run Code Online (Sandbox Code Playgroud) python 依赖于__class__a 中的变量进行cell调用super()。free它从第一个堆栈帧中的变量获取此单元格。
奇怪的是,这个变量并不在 中locals(),而是当您从方法中引用它时__init__。
以这段代码为例:
class LogicGate:
def __init__(self,n):
print(locals())
a = __class__
print(locals())
Run Code Online (Sandbox Code Playgroud)
当您反汇编它时,您可以看到它以某种方式知道print和locals是全局变量并且__class__是LOAD_DEREF. 在运行代码之前,编译器如何知道这一点。据我所知,locals,print和只是编译器的变量名称。__class__而且这种方式是在它被复制到之前__class__突然出现的。locals()a
4 10 LOAD_DEREF 0 (__class__)
Run Code Online (Sandbox Code Playgroud)
尽管locals:
2 LOAD_GLOBAL 1 (locals)
Run Code Online (Sandbox Code Playgroud)
我这么问是因为我正在研究一个 python 到 javascript 编译器。目前,该编译器不区分printor__class__并尝试从全局范围中获取它们。
正如您从上面代码的 ast 的打印输出中看到的,解析器不区分localsor __class__:
Module(body=[ClassDef(name='LogicGate',
bases=[],
keywords=[],
body=[FunctionDef(name='__init__',
args=arguments(args=[arg(arg='self', …Run Code Online (Sandbox Code Playgroud) python ×5
parsing ×4
clang ×3
c ×2
c++ ×2
antlr ×1
antlr4 ×1
cell ×1
css ×1
free ×1
java ×1
javascript ×1
llvm ×1
optimization ×1
python-3.2 ×1
python-3.x ×1
tokenize ×1