python antlr_使用ANTLR在5分钟内用Java解析任何语言:例如Python
python antlr
我喜歡出于多種目的處理代碼,例如靜態分析或自動重構。 對我來說,有趣的部分是推理從抽象語法樹(AST)構建的模型。 為此,您需要一種從源文件中獲取AST的方法。 可以使用ANTLR輕松完成此操作,并在此處提供完整語法的集合: https : //github.com/antlr/grammars-v4
謝謝大家的語法!
我們將只為Python 3編寫一個腳本,對于Python 2來說也應該可以正常工作。如果我們需要做一些小的調整,我們可以從這個基礎上輕松地做到這一點。
獲得語法
首先,我們要學習語法。
只需訪問https://github.com/antlr/grammars-v4并獲取所需的語法即可。 大多數語法都有非常寬松的許可。
R,Scala,Python,Swift,PHP等許多語言都有數十種語法。 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 repo'url '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.antlr4'antlr4 {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 + '-all'from { 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 i=0;i<indentation;i++) {System.out.print(" ");}System.out.println(ruleName);for (int i=0;i<ctx.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.html
python antlr
總結
以上是生活随笔為你收集整理的python antlr_使用ANTLR在5分钟内用Java解析任何语言:例如Python的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 备案说要扣车什么意思(备案说要扣车)
- 下一篇: linux配置php环境(linux p