镇江网站关键词,WordPress 延时加载,wordpress中文广告,软件技术和计算机应用技术哪个好文章目录 1 什么是ANTLR42 为什么需要ANTLR43 环境搭建4 官方示例4.1 编写语法规则文件4.2 生成语法解析器4.3 基于SDK实现逻辑 5 总结 1 什么是ANTLR4
ANTLR是ANother Tool for Language Recognition的缩写#xff0c;它是一个强大的用于读取、处理、执行和翻译结构化文本或… 文章目录 1 什么是ANTLR42 为什么需要ANTLR43 环境搭建4 官方示例4.1 编写语法规则文件4.2 生成语法解析器4.3 基于SDK实现逻辑 5 总结 1 什么是ANTLR4
ANTLR是ANother Tool for Language Recognition的缩写它是一个强大的用于读取、处理、执行和翻译结构化文本或二进制文件的语法分析器生成器广泛用于构建语言、工具和框架通过语法描述规则它能够生成一个可以遍历解析树的解析器。ANTLR4是ANTLR的第4个版本。
2 为什么需要ANTLR4
以一个计算器的例子来说明当我们需要开发一个计算器程序时第一步就是要确认支持的边界也就是要确认支持哪些运算例如假设只需要支持整数的四则运算且不支持括号也就是只支持12*3等简单的计算。然后就可以开始开发开发的重点就变成对算式的解析还需要处理运算符的优先级。在通常的书籍中会基于栈和队列实现并且需要自行处理运算符的优先级复杂计算器——四则运算表达式求值中缀转后缀表达式。而使用ANTLR4就可以将算式的解析和实现分离ANTLR4会将算式解析为语法树然后提供遍历的机制去实现运算因此我们的代码就只需要实现运算即可。
简单来说ANTLR4就是一个生成词法分析器和语法分析器的生成器能够解析文本和二进制解析后生成语法树然后基于不同语言的SDK遍历该语法树实现对应的逻辑。
使用ANTLR4通常分成三步
编写语法规则文件规则文件以g4为后缀在规则文件中使用自顶向下的形式描述要解析的语法的格式使用antlr4将规则文件转换成对应语言的语法解析代码使用对应语言的SDK提供的函数遍历语法树
3 环境搭建
安装java建议安装比较高的版本这里安装的是jdk17安装虚拟环境pip3 install virtualenv创建虚拟环境并进入virtualenv myenv . myenv/bin/activate安装antlr4pip install antlr4-tools安装对应语言的运行时库对于python而言只支持python3安装antlr4-python3-runtime
这里面主要要注意的就是java的版本不能用1.6或者1.8等比较低的版本。
如果使用vscode进行开发可以安装ANTLR4 grammar syntax support插件如果使用pycharm开发可以安装ANTLR v4插件。
4 官方示例
4.1 编写语法规则文件
grammar expr;
prog: (expr NEWLINE)* ;
expr: expr (*|/) expr| expr (|-) expr| INT| ( expr );
NEWLINE : [\r\n] ;
INT : [0-9] ;语法规则文件是基于正则表达式并且从上到下的语法描述文件很类似于编译原理里面的词法分析和语法分析。
除了grammer所在的行每个分号结尾的部分都是描述一个规则grammer声明一个语法的名称名称为expr该名称与文件名一致prog整个规则的总体的描述prog在这里也只是个名字没有什么特殊含义该规则的含义是若干个(expr NEWLINE)expr描述prog中的expr表达式它是一种递归的形式表达式有4种情况表达式之间的乘除、表达式之间的加减、INT、表达式可以使用括号NEWLINE若干换行符INT若干数字组成
因此上面就是一个计算器的语法描述文件该计算器只支持整数的四则运算并且可以通过括号调整优先级。
4.2 生成语法解析器
将上述语法文件保存为expr.g4然后使用antlr4工具生成语法解析器
antlr4 -DlanguagePython3 expr.g4就会在当前目录下生成一些python程序和文件
exprLexer.py词法分析exprListener.py继承自ParseTreeListener的空类exprListenerexprParser.py语法分析
4.3 基于SDK实现逻辑
基于上面生成的类然后结合antlr4提供的api就可以得到antlr4为我们生成的AST(抽象语法树)相当于我们只使用antlr4为我们解析表达式但是具体的计算逻辑是需要编写代码去遍历AST。antlr4提供了两种方式遍历AST一种是listener另一种是visitor默认是listener。
例如当给定表达式为12*3时会生成如下的一棵AST树 # Listener.py
from grammer.exprListener import exprListener
from grammer.exprParser import exprParserclass Listener(exprListener):def __init__(self):self.result {}# Enter a parse tree produced by exprParser#prog.def enterProg(self, ctx:exprParser.ProgContext):pass# Exit a parse tree produced by exprParser#prog.def exitProg(self, ctx:exprParser.ProgContext):pass# Enter a parse tree produced by exprParser#expr.def enterExpr(self, ctx:exprParser.ExprContext):pass# Exit a parse tree produced by exprParser#expr.def exitExpr(self, ctx:exprParser.ExprContext):if ctx.getChildCount() 3:if ctx.getChild(0).getText() (:self.result[ctx.getText()] self.result[ctx.getChild(1).getText()]else:opc ctx.getChild(1).getText()v1 self.result[ctx.getChild(0).getText()]v2 self.result[ctx.getChild(2).getText()]if opc :self.result[ctx.getText()] v1 v2elif opc -:self.result[ctx.getText()] v1 - v2elif opc *:self.result[ctx.getText()] v1 * v2elif opc /:self.result[ctx.getText()] v1 / v2else:ctx.result[ctx.getText()] 0elif ctx.getChildCount() 2:opc ctx.getChild(0).getText()if opc :v self.result[ctx.getChild(1).getText()]self.result[ctx.getText()] velif opc -:v self.result[ctx.getChild(1).getText()]self.result[ctx.getText()] - velif ctx.getChildCount() 1:self.result[ctx.getText()] int(ctx.getChild(0).getText())继承exprListener创建我们自己的Listener需要基于该Listener类遍历生成的AST在这里只修改了exitExpr函数从字面意思理解该函数就是在遍历AST时离开某个节点时执行的函数此时可以根据当前节点的孩子的个数执行不同的计算逻辑。
from antlr4 import CommonTokenStream
from antlr4 import ParseTreeWalker
from antlr4.InputStream import InputStream
from antlr4.Token import CommonTokenfrom grammer.exprParser import exprParser
from grammer.exprLexer import exprLexer
from Listener import Listenerif __name__ __main__:input_stream InputStream(12*3\n)lexer exprLexer(input_stream)token_stream CommonTokenStream(lexer)parser exprParser(token_stream)tree parser.prog()listener Listener()walker ParseTreeWalker()walker.walk(listener, tree)print(listener.result)5 总结
在实现一种语言或者规则时首先需要解析语言或者规则然后再对其中的单词或者语句进行处理因此在实际开发过程中需要对输入进行分割然后再分析语义而通过antlr4可以自定义语言或者规则的构成然后就可以通过antlr4的库得到一个AST的树再利用antlr4的api遍历该树实现其他的业务逻辑因此基于antlr4可以简化我们的程序帮助实现词法和语法的分析。