济南网站开发公司排名,个人手机网站大全,网站seo在线诊断分析,重庆建设造价信息网站python antlr我喜欢出于多种目的处理代码#xff0c;例如静态分析或自动重构。 对我来说#xff0c;有趣的部分是推理从抽象语法树#xff08;AST#xff09;构建的模型。 为此#xff0c;您需要一种从源文件中获取AST的方法。 可以使用ANTLR轻松完成此操作#xff0c;并… python antlr 我喜欢出于多种目的处理代码例如静态分析或自动重构。 对我来说有趣的部分是推理从抽象语法树AST构建的模型。 为此您需要一种从源文件中获取AST的方法。 可以使用ANTLR轻松完成此操作并在此处提供完整语法的集合 https : //github.com/antlr/grammars-v4 谢谢大家的语法 我们将只为Python 3编写一个脚本对于Python 2来说也应该可以正常工作。如果我们需要做一些小的调整我们可以从这个基础上轻松地做到这一点。 获得语法 首先我们要学习语法。 只需访问https://github.com/antlr/grammars-v4并获取所需的语法即可。 大多数语法都有非常宽松的许可。 RScalaPythonSwiftPHP等许多语言都有数十种语法。 Java也有一个但是对于Java您更喜欢使用JavaParser对吗 只需将语法复制到src / main / antlr下的新项目中 使用Gradle设置项目 现在我们将使用Gradle设置构建脚本。 我们将使用ANTLR4插件从melix 因为我觉得它更灵活的中描述的的官方文件 。 我们将在特定的程序包 me.tomassetti.pythonast.parser 中生成代码因此将在从该程序包派生的目录build / generate-src / me / tomassetti / pythonast / parser中生成代码。 buildscript {repositories {maven {name JFrog OSS snapshot repourl https://oss.jfrog.org/oss-snapshot-local/}jcenter()}dependencies {classpath me.champeau.gradle:antlr4-gradle-plugin:0.1.1-SNAPSHOT}
}repositories {mavenCentral()jcenter()
}apply plugin: java
apply plugin: me.champeau.gradle.antlr4antlr4 {source file(src/main/antlr)output file(build/generated-src/me/tomassetti/pythonast/parser)extraArgs [-package, me.tomassetti.pythonast.parser]
}compileJava.dependsOn antlr4sourceSets.main.java.srcDirs antlr4.outputconfigurations {compile.extendsFrom antlr4
}task fatJar(type: Jar) {manifest {attributes Implementation-Title: Python-Parser,Implementation-Version: 0.0.1}baseName project.name -allfrom { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }with jar
} 我还添加了fatJar任务。 该任务将产生一个包含所有依赖项的JAR。 我使用它可以更轻松地将解析器导入Jetbrains MPS。 要从语法生成解析器您只需运行gradle antlr4。 然后您必须向您的IDE解释它应该考虑build / Generated-src下的代码。 如何调用解析器 现在让我们看看如何调用解析器。 public class ParserFacade {private static String readFile(File file, Charset encoding) throws IOException {byte[] encoded Files.readAllBytes(file.toPath());return new String(encoded, encoding);}public Python3Parser.File_inputContext parse(File file) throws IOException {String code readFile(file, Charset.forName(UTF-8));Python3Lexer lexer new Python3Lexer(new ANTLRInputStream(code));CommonTokenStream tokens new CommonTokenStream(lexer);Python3Parser parser new Python3Parser(tokens);return parser.file_input();}
} 我们的ParserFacade只有一个名为parse的公共方法。 它获取一个文件并返回AST。 没有比这更简单的了。 让我们看一些AST 让我们看一个简单的文件 def sum(a, b):return a bprint(The sum of %i and %i is %i % (5, 3, sum(5, 3))) 现在获取AST。 我们可以使用以下代码进行打印 public class AstPrinter {public void print(RuleContext ctx) {explore(ctx, 0);}private void explore(RuleContext ctx, int indentation) {String ruleName Python3Parser.ruleNames[ctx.getRuleIndex()];for (int i0;iindentation;i) {System.out.print( );}System.out.println(ruleName);for (int i0;ictx.getChildCount();i) {ParseTree element ctx.getChild(i);if (element instanceof RuleContext) {explore((RuleContext)element, indentation 1);}}}} 如果我们解析简单的示例并使用AstPrinter进行打印我们将获得一个超级复杂的AST。 第一行看起来像 file_inputstmtcompound_stmtfuncdefparameterstypedargslisttfpdeftfpdefsuitestmtsimple_stmtsmall_stmtflow_stmtreturn_stmttestlist... 对于解析器的构建方式有很多无效的规则。 在解析时这很有意义但是会产生非常污染的AST。 我认为有两种不同的ASTS一种易于生成的解析AST 另一种易于推理的逻辑AST 。 幸运的是我们可以毫不费力地将第一个转换为后者。 一种简单的方法是列出仅包装程序的所有规则然后跳过它们取而代之的是唯一的子规则。 我们可能必须对此进行优化但是作为第一步的近似我们只是跳过只有一个子节点的节点这是另一个解析器规则无终端。 这样我们从164个节点增加到28个节点。结果逻辑AST为 file_inputfuncdefparameterstypedargslisttfpdeftfpdefsuitesimple_stmtreturn_stmtarith_expratomatomsimple_stmtpoweratomtrailertermstringatomtestlist_compintegerintegerpoweratomtrailerarglistintegerinteger 在这棵树中我们应该将所有内容映射到我们理解的概念而无需人工节点只是出于解析原因而创建的节点。 结论 编写解析器并不是我们可以产生最大价值的地方。 我们可以轻松地重用现有语法生成解析器并使用这些解析器构建我们的智能应用程序。 那里有几个解析器生成器其中大多数足以满足您可以实现的大多数目标。 在它们当中我倾向于比其他人更多地使用ANTLR它很成熟得到支持速度很快。 它产生的AST可以使用异构API我们为每种类型的节点生成单个类和同类API我们可以询问每个节点代表哪个规则及其子列表进行导航。 ANTLR的另一个巨大好处是存在随时可以使用的语法。 构建语法需要经验和一些工作。 特别是对于Java或Python这样的复杂GPL。 它还需要非常广泛的测试。 即使我们已经使用JavaParser解析了成千上万个文件我们仍然发现JavaParser背后的Java 8语法存在一些小问题。 如果可以避免的话这是现在编写自己的语法的一个很好的理由。 顺便说一下所有代码都可以在github上找到 python-ast 翻译自: https://www.javacodegeeks.com/2016/02/parsing-language-java-5-minutes-using-antlr-example-python.htmlpython antlr