Antlr4介绍和Helloworld
摘要:本文将首先介绍Antlr4,以及如何通过Antlr4 grammer生成对应的hello的AST
1. Antlr4简单介绍
Antlr4(Another Tool for Language Recognition)是一款基于Java开发的开源的语法分析器生成工具,能够根据语法规则文件生成对应的语法分析器,广泛应用于DSL构建,语言词法语法解析等领域。现在在非常多的流行的框架中都用使用,例如,在构建特定语言的AST方面,CheckStyle工具,就是基于Antlr来解析Java的语法结构的(当前Java Parser是基于JavaCC来解析Java文件的,据说有规划在下个版本改用Antlr来解析),还有就是广泛应用在DSL构建上,著名的Eclipse Xtext就有使用Antlr。
Antlr可以生成不同target的AST(https://www.antlr.org/download.html),包括Java、C++、JS、Python、C#等,可以满足不同语言的开发需求。当前Antlr最新稳定版本为4.9,Antlr4官方github仓库中,已经有数十种语言的grammer(https://github.com/antlr/grammars-v4,不过虽然这么多语言的规则文法定义都在一个仓库中,但是每种语言的grammer的license是不一样的,如果要使用,需要参考每种语言自己的语法结构的license)。
2,ANTLR v4 安装和hello world运行环境避坑
在ANTLR上有个downloads界面,但是点击老是报错,
实际上,downloads的界面不再此处,
antlr资源下载
点击下载 antlr-4.9.3-complete.jar
现在来测试下ANTLR工具是否工作正常:
java -jar antlr-4.5.1-complete.jar # 启动org.antlr.v4.Tool
如果正常的话会看到以下帮助信息:
ANTLR Parser Generator Version 4.5.1-o ___ specify output directory where all output is generated-lib ___ specify location of grammars, tokens files...
每次运行ANTLR工具都要输入这么长的命令是否有些痛苦?写个脚本来解放我们的手指吧!
#!/bin/sh
java -cp .:./antlr-4.5.1-complete.jar:$CLASSPATH org.antlr.v4.Tool $*
把它保存为antlr.sh,以后就可以使用下列命令来运行ANTLR工具了:
antlr
3,idea插件安装
file -> settings -> plugins 搜索 ANTLR 点击安装即可
修改下文件生成路径
创建springboot或者maven项目添加jar
<dependency><groupId>org.antlr</groupId><artifactId>antlr4</artifactId><version>4.9.3</version></dependency>
创建Hello.g4
grammar 的名字要和文件名保持一致
grammar Hello;compilation_unit:prog+ EOF //EOF结束符号匹配;prog:level_num '9' HELLO ID '!';level_num:NUM | '9';// '9' 是隐式词法,一般情况下,在词法解析树后,第一个排列(也就是当前位置) 匹配时首个匹配
// '9' 直接做本字符匹配//词法解析 由这些组成
HELLO : H E L L O;// 表示 由纯数字组成 最少有1个,可以有多个 至少出现一次
NUM : [0-9]+ ;//表示 由数字和字母组成 最少有1个,可以有多个 至少出现一次
ID : [a-zA-Z0-9]+ ;//如果是以这些符号开头的,这一行不匹配 放入 HIDDEN 隐藏通道
// 匹配双斜线后的任意字符,可以有可以没有
// .*? 非判断模式 可有可无
// '\r'? 可有可无 (适配linux)(liunx下的换行符为\n,win是\r\n)
LINE_COMMIT : '//' .*? '\r'? '\n' -> channel(HIDDEN);//无效字符 跳过不匹配 放入隐藏通道
WS : [ \t\r\n]+ -> skip;fragment H : [Hh];
fragment E : [Ee];
fragment L : [Ll];
fragment O : [Oo];
点击生成
最终项目结构
继承监听器,并实现替换输出
package com.yz.antlr.hello.impstand;import com.yz.antlr.hello.g4.HelloBaseListener;
import com.yz.antlr.hello.g4.HelloParser;
import org.antlr.v4.runtime.TokenStreamRewriter;
import org.antlr.v4.runtime.tree.TerminalNode;public class JCLAna extends HelloBaseListener {private TokenStreamRewriter tokenStreamRewriter;public JCLAna(TokenStreamRewriter tokenStreamRewriter) {super();this.tokenStreamRewriter = tokenStreamRewriter;}@Overridepublic void enterProg(HelloParser.ProgContext ctx) {// super.enterProg(ctx);System.out.println(">>>" + ctx.getText());HelloParser.Level_numContext level_numContext = ctx.level_num();TerminalNode num = level_numContext.NUM();}@Overridepublic void exitLevel_num(HelloParser.Level_numContext ctx) {// super.exitLevel_num(ctx);String text = ctx.getText();Integer level_num = Integer.valueOf(text);level_num += 1;// 修改替换 level_num,tokenStreamRewriter.replace(ctx.getStart(), ctx.getStop(), String.valueOf(level_num));}
}
`
获取树结构并替换值
package com.yz.antlr.hello.main;import com.yz.antlr.hello.g4.HelloLexer;
import com.yz.antlr.hello.g4.HelloParser;
import com.yz.antlr.hello.impstand.JCLAna;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.TokenStreamRewriter;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.IOException;/*** @author yz* @version 1.0* TODO* @date 2022/3/24 19:18*/
public class HelloAntlrMain {private static final Logger log = LoggerFactory.getLogger(HelloAntlrMain.class);public void execMath(String str) {CharStream input = CharStreams.fromString(str);// 将内容传递到词法解析器HelloLexer lexer = new HelloLexer(input);//getAllTokens() 行为会取出字符,导致后续无法解析
// lexer.getAllTokens().forEach(token -> System.out.println(token.toString()));// 传递到流CommonTokenStream tokenStream = new CommonTokenStream(lexer);//获取到g4捕获到所有内容TokenStreamRewriter tokenStreamRewriter = new TokenStreamRewriter(tokenStream);//将流传递到语法解析器HelloParser parser = new HelloParser(tokenStream);//两个方法都能生成树,但是prog会报结尾错误,具体原因不详
// ParseTree tree = parser.prog();ParseTree tree = parser.compilation_unit();System.out.println(tree.toStringTree());//创建树遍历器ParseTreeWalker parseTreeWalker = new ParseTreeWalker();//添加自定义解析器JCLAna jclAna = new JCLAna(tokenStreamRewriter);// 添加树和自定义解析器到parseTreeWalker.walk(jclAna, tree);// 输出打印最终的内容System.out.println(tokenStreamRewriter.getText());}public static void main(String[] args) throws IOException {HelloAntlrMain antlrMain = new HelloAntlrMain();String str = "01 9 Hello world!";antlrMain.execMath(str);}
}
最终实现数据读取和替换输出
([] ([6] ([13 6] 01) 9 Hello world !) <EOF>)
>>>019Helloworld!
29Helloworld!
·
·
·
参考资料
Antlr4 —入门介绍
Antlr4 入门
从定义到AST及其遍历方式
·
·
我是离离原上草,要是有用就请一键三连吧。
Antlr4介绍和Helloworld相关推荐
- play(一) play介绍,helloworld项目
1.下载安装包并安装: (1)登录http://www.playframework.org/ 直接点击Download链接,下载.zip文件.选择版本play-1.4.2.zip (2) 直接解压该文 ...
- libgdx游戏引擎开发笔记(一)引擎介绍和Helloworld
做Android快一年了,项目也做了四五个,感觉没什么动力向前,思绪整理了一段时间,决定转入Android游戏开发,同时发现了一款强大的游戏引擎libgdx,在此边学边整理,好记性不如烂笔头嘛! ...
- CORBA的简单介绍及HelloWorld
CORBA概述 CORBA(Common Object Request Broker Architecture,公共对象请求代理体系结构)是由OMG组织制订的一种标准的面向对象应用程 序体系规范.或者 ...
- Springboot简单介绍
Springboot入门介绍 一.Spring框架概述 1.1 什么是Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnso ...
- Java编程一个简单运算程序+MyEclipse使用方法+HelloWorld,你get了吗?
相信每一位编程者第一段代码都是HelloWorld,由于太简单,所以会一笔带过,下面重点讲的是对于萌新们的第二个代码.(打过HelloWorld的萌新们可以跳过这第一段,直接看第二段) 第一段:首先介 ...
- Visual Studio 2008 可扩展性开发(九):总结篇
可以说木匠让小时的我第一次感受到了专业,虽然那时还不知道专业这个词,尤其是那些有年纪的老木匠,专注地在那锯木头.钉钉子.刨出带着香味的木花.他们有其他人所没有的工具,更重要的是他们掌握了那些工具.VS ...
- prism项目搭建 wpf_WPF Step By Step 系列-Prism框架在项目中使用
Prism是一个强大的Mvvm框架,下面我们将重点讲解如何在项目使用Prism提供的基础功能,完成基于MVVM的WPF项目的框架设计和开发,包括应用程序的架构. 项目的解决方案结构,项目采用Prism ...
- Spring松耦合的实现
HelloShiyanlou 与松耦合的实现 一.实验介绍 1.1 实验内容 本节实验将带你入门简单的 Maven 项目创建和如何实现松耦合. 1.2 实验知识点 Maven 介绍 Spring 松耦 ...
- 在Angular专家Dan Wahlin的免费33部分课程中学习Angular
According to the Stack Overflow developer survey 2018, Angular is one of the most popular frameworks ...
最新文章
- openssl 加密解密 指令_OpenSSL未来架构设计,3.0初步实现
- 人脸情绪识别系统第一次迭代总结
- Android网络开发之Volley--Volley自定义Request
- 通过sql-labs进行sql注入学习(11-22)
- 微计算机和微处理器的区别,CPU和微处理器的区别
- Linux学习笔记-Makefile优化之头文件依赖
- 大型互联网分布式企业微服务云架构
- 权威解读 GitHub、Apache 疑云:主流开源软件究竟是否会被闭源?| CSDN 独家
- IE9下透明度设置无效
- win11快捷键怎么使用 Windows11快捷键的使用方法
- bdm导入mysql_MySQL数据库导入教程
- 【图像提取】基于matlab PCA-CSIFT feature图像特征提取【含Matlab源码 1174期】
- 创新金融科技:从零到一构建新房交易供应链金融服务 PPT分享
- 12.接口测试报告包含哪些内容
- 夜深人静了,我们来学学分布式锁
- 关于MySQL中出现相对应引用词报错“ambiguous”的问题
- 目前几种实时视频流协议对比
- 国内android第三方rom,安卓手机第三方rom大盘点,曾经火到不行,如今几乎全军覆没...
- 狄利克雷分布公式_关于狄利克雷分布的理解
- 局域网和广域网的传输流程