如何把antlr4融合到编译器项目中使用
antlr4是什么?
antlr4是一个开源的词法、语法分析程序生成器,仅需要配置词法和语法规则,即可自动生成语言编译器所需的词法、语法分析程序。
问题:antlr4官方给出了jar包,可以命令行运行使用,但是要是想把源码直接融合到自己的编译器项目中去,如何做呢?
1 下载源码
git clone https://github.com/antlr/antlr4.git
2 寻找程序主入口
官方给出的jar包运行方式是:
java -jar antlr-xxx.jar Hello.g4
或
java org.antlr.v4.Tool Hello.g4
可以看到antlr4的程序主入口是 org.antlr.v4.Tool
。除此之外,还有一种找程序入口的方法,可以打开项目pom.xml
,<CTRL+F>查找一下mainClass
3 打开Tool.java
可以看到main
函数中,使用了args
参数,也就是传递 g4 文件地址。按道理说,只要我们引入源码,然后带参数运行此main
函数就可以像命令行那样使用了,但是事实上,编译都没通过。
4 解决编译报错
源码的编译报错,一般不太可能是代码语法问题,基本上都是类找不到,依赖的包没有,antlr4也是如此。
解决依赖包的问题
antlr4依赖项可以从pom.xml
的 <dependencies>
标签中找到,如下:
<dependencies><dependency><groupId>org.antlr</groupId><artifactId>antlr4-runtime</artifactId><version>${project.version}</version></dependency><dependency><groupId>org.antlr</groupId><artifactId>antlr-runtime</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.antlr</groupId><artifactId>ST4</artifactId><version>4.3</version></dependency><dependency><groupId>org.abego.treelayout</groupId><artifactId>org.abego.treelayout.core</artifactId><version>1.0.3</version></dependency><dependency><groupId>org.glassfish</groupId><artifactId>javax.json</artifactId><version>1.0.4</version></dependency><dependency><groupId>com.ibm.icu</groupId><artifactId>icu4j</artifactId><version>61.1</version></dependency></dependencies>
把这段配置加入到自己项目的pom.xml
中去,Maven重新构建一下项目,把包装上即可。
解决源码中g文件的编译问题
这个问题相当有趣。在antlr4中有部分源码是用 antlr3 编译 g 文件自动生成的,但是源码中并没有给出这些生成的源码,所以需要自己手动生成。从ANTLR官方下载网址可以看到这样一句话:
ANTLR v4 is written in ANTLR v3.5.2 and StringTemplate 4.3. In antlr-4.9.1-complete.jar, you’ll find everything you need to run the ANTLR tool and make its generated parsers work.
摘自 https://www.antlr.org/download.html
所以,我们需要去下载 antlr3 来对 antlr4 源码中的 g 文件进行编译生成依赖的类文件。点击打开antlr3的官网下载渠道
编译的命令和antlr4是一样的。大部分的 g 文件在 org.antlr.v4.parse
包内,生成前的包内是这样的:
生成后的包内是这样的:
解决找不到UnicodeData.java类
这个问题很棘手,在org.antlr.v4.unicode.UnicodeDataTemplateController
类中,可以看到这样一段注释:
/**
* StringTemplate controller used to generate parameters to feed
* to {@code unicodedata.st} to code-generate {@code UnicodeData.java},
* used by the tool for Unicode property escapes like {@code \p{Lu}}.
*
* Uses ICU to iterate over Unicode character categories, properties,
* and script codes, as well as aliases for those codes.
*
* This class exists in its own Maven module to avoid adding a
* dependency from the tool onto the (large) ICU runtime.
*/
透过这段话,可以知道,UnicodeData.java
是由unicodedata.st
模板生成的,这应该是要调用源码中某个类的方法来生成。遗憾的是,我找了很久依然不知道如何生成这个类。好在我发现了,其实源码中已经给出了这些需要自动生成的类,只是没有放在正确的位置罢了。
target/generated-sources/tool/src/org/antlr/v4/unicode/UnicodeData.java target/generated-sources/antlr3/org/antlr/v4/parse/... —— 这是parse包内编译 g 文件 自动生成的代码集合target/generated-sources/antlr3/org/antlr/v4/codegen/... —— 这是codegen包内编译 g 文件 自动生成的代码集合
Antlr的作者还是很良心的,其实已经把需要的类,帮我们生成了,放在 generated-sources
文件夹下了。
解决找不到 org.antlr.v4.runtime包的问题
runtimeruntimeruntime包是antlr4生成的词法和语法文件运行时所需的包,但是不知道为啥编译时竟然也需要这个包。不管他,还是在下载的源码包里去找,根目录有一个runtime
文件夹,下面给出了各个目标语言所需的运行时包:
我这里把Java里面的runtime包,拷贝到 org.antlr.v4.runtime
即可
基本上到这里,所有需要的依赖包或者类都已经加入或生成,源码中编译问题是没有了。
5 解决运行时报错问题
解决了编译问题后,给 Tool.java 一个参数,运行了一下,发现报这个错误:
找不到 org/antlr/v4/tool/templates/messages/formats/antlr.stg 这个模板文件,去源码中看,tool包下确实没有 templates 这个文件夹。经过查找,在 target/classes/org/antlr/v4/tool 里发现了这个 templates 文件夹。于是将其放至源码 src 下的tool包里,发现依然是这个错误,但是路径应该是没有问题的。
打开 ErrorManager.java
对应错误的位置读一下源码:
错误位置为 231 行 ,因为url
为null
,往上看,有两行关键代码:
ClassLoader cl = Thread.currentThread().getContextClassLoader();URL url = cl.getResource(fileName);
fileName就是上一个图中打印出来的 org/antlr/v4/tool/templates/messages/formats/antlr.stg
。这样搞清楚这两行是什么意思,就知道程序为什么会报错。所幸,在这片博文https://www.cnblogs.com/lingxi2b2/p/12063623.html中找到了答案。这里cl.getResource(fileName)
相对的是ClassPath
的目录,所以这个templates
文件夹应该放到classes
里面,而不是src
下面。
6 成功run起来了
更新 1
忘记可以直接访问jar包里的资源了,直接Maven导入依赖包,然后import
即可使用,瞎搞了一圈。如果想把jar包中的资源也打包进自己的项目,可以先将jar包下载,并放至lib下,然后配置pom.xml,进行打包。
更新 2
没有白费功夫!在源码入口文件Tool.java
中,main函数执行结束,强制进行了程序退出,也就是说如果仅是引入依赖包使用,那么调用Tool.main函数后,程序就自动退出了,还是没有起到融合的效果。所以还是得引入源码,然后修改源码来解决这个问题。
解决程序强制退出问题
这是由于源码中的System.exit(0)
引起的,只需要把调用exit
函数的地方全部注释掉即可。
如何把antlr4融合到编译器项目中使用相关推荐
- 怎样在普通java项目中使用aspectj
背景 自从学习spring起,AOP这个词几乎是天天挂在嘴边,好像一切都是天经地义的. 尤其在springboot里面,经常见到的@Before @After等之类的内容,一般更是没有多少解释,通常被 ...
- EasyCVR在校园视频融合及明厨亮灶项目中的应用方案设计
随着校园智能化需求的不断增长,越来越多的校园逐渐开始升级校园监控视频平台,将原先传统的视频监控系统,逐渐升级转变为灵活性强.视频能力丰富.具备AI检测能力.并能支持视频汇聚与统一管理的智能化校园综合管 ...
- java对office、pdf文档在线预览解析(融合进项目中)
最近在项目中要做一个文档的预览,在网上搜了好多demo,都可以实现其功能,但是放在自己的项目中有点复杂. 先说明本人的开发环境(win7+tomcat7+maven+svn+myeclipse),接下 ...
- Java 并发在项目中的使用场景
1.并发编程的三个核心问题: (1)分工:所谓分工指的是如何高效地拆解任务并分配给线程 (2)同步:而同步指的是线程之间如何协作 (3)互斥:互斥则是保证同一时刻只允许一个线程访问共享资源 (4)应用 ...
- 在vue项目中使用prismjs(网页代码高亮插件)
在vue项目中使用prismjs 什么是prismjs prismjs是一款代码高亮美化插件,在一些技术博客类的网站中需要展示代码时,可以使用它类似与markdown的代码块, 官网链接:https: ...
- C++项目中的extern C {}
2010-07-10 19:45 by 吴秦, 92864 阅读, 22 评论, 收藏, 编辑 引言 在用C++的项目源码中,经常会不可避免的会看到下面的代码: ? 1 2 3 4 5 6 7 8 9 ...
- 在项目中使用Google Closure Compiler
现在的Web项目总是离不开大量JavaScript,而JS文件的体积也越来越大,也越来越影响页面的感知性能(Perceived Performance).因此,我们会对JS文件进行压缩,一方面是使用G ...
- 从15000个Python开源项目中精选的Top30,Github平均star为3707,赶紧收藏!
翻译 | AI科技大本营(ID:rgznai100) 参与 | SuiSui 继推出2017年机器学习开源项目Top 30榜单后,Mybridge AI又推出了一个Python开源项目Top 30榜单 ...
- 华北计算机研究无人机,飞马D200无人机在华北某环境地调项目中的应用案例
一.环境地质调查简介 环境地质调查是通过对区域地质环境条件和由自然地质作用及人类活动引起的环境地质问题的调查研究,评价预测资源开发与国土整治的环境地质条件,论证重大区域性环境地质问题和有关地质灾害的地 ...
最新文章
- C#对Microsoft.VisualBasic My对象兰台妙选【月儿原创】
- 单片机教学视频讲得好
- 【渝粤教育】电大中专电商运营实操作业 题库
- spring事物管理--声明式(AspectJ)注解实现 (推荐使用)
- lighttpd,nginx,apache的性能负载比较
- echarts在(React,Vue)中的使用总结
- 06.SpringBoot的webjars和静态资源映射
- 查询mysql数据库的端口号_查询数据库端口号的命令
- 1.1.1.1校园网_突破校园网限制,开启寝室Wifi
- Linux命令之dhclient,dhclient命令 – 动态获取或释放IP地址
- IOS APP 公司主体变更的转让流程
- NVIDIA CUDA初级教程(P2-P3)CPU体系架构概述、并行程序设计概述
- web前端学习(一):国内最常用,又优秀的web框架,Vue渐近式框架
- 括弧匹配检验:比较基础的栈
- 行业云服务——乐视云点播服务试用体验
- linux中的wget命令
- 通过2-3-4树理解红黑树
- Idea相关操作以及相关问题
- 再创佳绩|Google Play 2020 年度中国开发者最佳榜单!
- oracle undoautotune,Oracle 暗藏参数:undo_autotune、一个吃力不讨好的活
热门文章
- JavaScript export和import学习笔记
- windows操作系统实验之粘滞键漏洞
- 定时发邮件 linux,linux 定时巡检系统时间并且发邮件
- PermissionError: [Errno 13] Permission denied 解决方法
- Docker 修改MySQL表大小写敏感
- SysTick_系统定时器实现流水灯
- git报错:git did not exit cleanly (exit code 1)
- Vue.js教程(一)
- ## ARM基础编程实验
- mysql中将列动态转换为行,mysql 行转列 MySQL数据库动态行转列