安装ANTLR

作者的电脑是MAC的操作系统macOS Catalina 10.15.2。

安装步骤后linux操作的系统的一样, Windows系统大致步骤一样,但是环境变量等配置有差别,作者很久没使用过win系统,只能基于MAC的系统介绍了。

环境准备

ANLTR是用JAVA编写的,需要先安装好JAVA,需要的JAVA版本是1.6以上。相信看这篇文章的各位同学电脑上应该都有安装JAVA。

下载ANTLR

使用ANTLR的功能其实很简单, 下载一个ANTLR的jar包即可。
官方下载地址

配置

最后一步配置环境变量,方便后面在命令行操作ANTLR
打开环境变量文件,作者安装的是zsh,所以编辑~/.zshrc文件,各位同学应该也清楚环境变量的配置,在文件加入几行:

export CLASSPATH=".:/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH"  #设置antlr的jar包到环境变量
alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.Tool' #快速运行ANTLR的解释器
alias grun='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.gui.TestRig' #快速运行ANTLR测试工具

完成上面的准备工作就可以开始体验ANTLR的强大功能了

第一个语法解释器

下面用一个简单的例子展示ANTLR的使用,编译一个最简单的赋值语句的语法。

编写g4文件

新建一个Hello.g4的文件,这个文件是针对语法的描述,相当于告诉ANTLR我的语法规范

Hello.g4内容如下:

 grammar Hello;  //定义一个名为 Hello 的语法
statement: ID '=' NUM; //匹配类似 a=1 age=100 这样的语句
ID: [a-z]+; // 定义了一个词法 ID,由小写字母组成
NUM:[0-9]+; // 定义了一个词法 NUM,由数字组成
WS: [ \t\r\n]+ -> skip; //在进行解析的过程中,忽略掉空格,换行

这样其实就定义好了一个简单语法。
对于不同的程序语言来说,语法结构越是复杂,想对应的g4文件也会越复杂
这个项目里面有针对目前流行的语言的ANTLR语法定义文件
各位同学可以找找接触过哪些,看看你用的语言复杂不复杂。反正JAVA文件是很复杂

生成解释器

生成ANTLR的解释器很简单,一条命令搞定。

antlr4 Hello.g4

运行完这条命令会生成如下几个文件:

Hello.interp
Hello.tokens
HelloBaseListener.java
HelloLexer.interp
HelloLexer.java
HelloLexer.tokens
HelloListener.java
HelloParser.java
  • HelloParser.java

    该文件包含一个语法解释器类的定义,负责识别我们定义的语法

public class HelloParser extends Parser { ... }
  • HelloLexer.java

    该文件包含一个词法解释器类的定义,负责自动识别我们定义的语法中的文法规则和词法规则。

public class HelloLexer extends Lexer { ... }
  • HelloListener.java和HelloBaseListener.java

    这两个类都是事件监听类,是留给开发者自己来定义相应的事件。因为ANTLR在进行遍历解析时,遍历器会触发一系列的事件。 比如进入某某标签,读到一个数字等。ANTLR开放了这些接口,开发者通过实现这些事件可以做到除了解释语法以外更复杂的功能。这里就不详细解释,后面会再介绍。先挖个坑

public interface HelloListener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link HelloParser#statement}.
* @param ctx the parse tree
*/
void enterStatement(HelloParser.StatementContext ctx);
/**
* Exit a parse tree produced by {@link HelloParser#statement}.
* @param ctx the parse tree
*/
void exitStatement(HelloParser.StatementContext ctx);
}
  • 其他非java文件

    ANTLR会给每个定义的词法符号指定一个数字形式的类型,然后将对应关系存储在这些文件中。当不同的语法有相同的词时这个文件就有大作用了。

测试解释器

最后到了验收结果的时候,测试一下ANTLR的语法解释器做了什么。下面会展示两种测试方式。

JAVA代码
  1. 将前面生成的4个JAVA文件添加到一个测试工程内,该工程需要引入ANTLR依赖。
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.7.1</version>
</dependency>
  1. 编写相关测试代码
public static void main(String[] args) {
HelloLexer lexer = new HelloLexer(CharStreams.fromString("a = 1"));
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
HelloParser parser = new HelloParser(tokenStream);
System.out.println(parser.statement().toStringTree(parser));
}
  1. 运行后会有如下输入:
    (statement a = 1)
    这个代码ANTLR成功识别到了我们的赋值语句。
命令行

ANTLR也提供了自动的测试工具,可以直接在命令行测试。详细用法如下

  1. 编译java代码,就跟一般的java代码一样我们需要同javac把java文件编译成class文件。
javac *.java
  1. 使用ANTLR测试工具,输入如下命令
grun Hello statement -gui

Hello 对应我们定义的语法 grammar Hello
statement 对应我们定义的词法 statement: ID '=' NUM;
-gui 表示输出图形界面

  1. 进入测试工具后,输入a = 1。 MAC电脑结束输入符号 control+D。
$ grun Hello statement -gui
a = 1
^D

ANTLR会输出图形界面

可以看到ANTLR最终解释出来的语法树。

总结

这篇文章带大家完成了第一个ANTLR的语法文件,并展示了测试过程。中间有一些细节没有在这里仔细讲解,在后面的笔记会陆续更新。最后附上一个稍微复杂一点的语法树的图。

ANTLR随笔(二)的更多相关文章

  1. Alpha冲刺随笔二:第二天

    课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(十天冲刺) 团队名称:葫芦娃队 作业目标:在十天冲刺里对每天的任务进行总结. 随笔汇总:https://www.cnblogs ...

  2. android 项目学习随笔二十一(IM、语音识别、机器人、统计、扫描二维码、条形码)

    语音识别:科大讯飞语音云 http://www.xfyun.cn/ 语音机器人模拟 public class TalkBean { public String text; public boolean ...

  3. android 学习随笔二十一(内容提供者 )

    一.内容提供者* 应用的数据库是不允许其他应用访问的* 内容提供者的作用就是让别的应用访问到你的私有数据* 自定义内容提供者,继承ContentProvider类,重写增删改查方法,在方法中写增删改查 ...

  4. oc随笔二:组合、继承

    在oc中如果没有使用ARC的话,手动管理内存一定要注意处理好“野指针”,通常我们在释放指针的指向的地址时,都要将指针赋值为nil,这样能有效的防止野指针.常用的关键字:retain.assign .s ...

  5. 多线程随笔二(Task)

    Task类是.net 4.0新加进来的特性,对原有的Thread,ThreadPool做了进一步的封装,使得.net平台上的多线程编程变得更加方便.废话不多说,进入正题. 一. Task启动 Task ...

  6. JavaSE 第二次学习随笔(二)

    循环结构中的多层嵌套跳出 targeta: for(int i = 0; i < 100; i++){ for (int j = 0; j < 100; j++) { if(i + j = ...

  7. 如何提高码农产量,基于ASP.NET MVC的敏捷开发框架之移动端开发随笔二

    前言 在前一篇文章中我已经做过开篇,接下来的随笔会详细讲一下我们的开发框架是如何实现的,专业的事由专业的人来讲,以后就由我们的高级码农小李英文名查尔斯和他的师父厂长(因为姓陈,酷爱摄影,我们的文艺片都 ...

  8. ANTLR随笔(三)

    ANTLR基本语法 前面已经简单介绍了ANTLR以及怎么安装和测试. 同学们应该大概清楚ANTLR的使用场景,但是对于关键步骤,怎么编写一个语法文件并没有详细介绍,这篇笔记主要详细讲解一下ANTLR的 ...

  9. ANTLR随笔(一)

    学习背景 最近做项目需要开发一个类似Graphql的简单版的自定义查询功能. 功能主要是通过前端自定义的复查询条件来控制后端的查询字段以及最终返回的JSON格式. 最初准备直接使用Graphql实现但 ...

随机推荐

  1. git涨姿势(一)

    今天遇到了一个git冲突问题,解决冲突方案我是当然知道的,就是本地不知道何时自己傻不拉几的新建了一个relese分支,而remote是没有release分支的,需要拉取的是release/V1.4.2 ...

  2. JavaScript的函数(一)

    ,1,在javascript中,函数即对象.函数里面的参数可以是个函数,例如: data.sort(function(a,b){return a-b;}) 函数的返回值,return语句导致函数停止执 ...

  3. 检测js对象是不是数组类型?

    面试时候被人问如何检测一个未知变量是不是数组类型,丢脸啊,老祖宗的脸都丢没了,这都不会,回家啃书本去吧!!! var a = [];方法一:Array.isArray([])  //true type ...

  4. golang的sync.WaitGroup使用示例

    下面一段代码 len(m) 不一定会打印为 10,为什么?.如果想要 len(m) 打印为 10,应该怎么修改代码? func main() { const N = 10 m := make(map[ ...

  5. 基于 HTML + WebGL 结合 23D 的疫情地图实时大屏 PC 版

    前言 2019年12月以来,湖北省武汉市陆续发现了多例肺炎病例,现已证实为一种新型冠状病毒感染引起的急性呼吸道传染病并蔓延全国,肺炎疫情牵动人心,人们每天起来第一件事变成了关注疫情进展,期望这场天灾早 ...

  6. 结题报告--洛谷P3915

    题目:点此. 我处理这种多组数据的方法被我叫做“mains法”,就是先假设只有一组数据,写一个代码,然后把那个main函数改成mains,最后写一个真正的main函数. 这个“真正的”main函数一般 ...

  7. 【python】定时锁屏,保护身体

    前言 最近越来越懒,一上班坐到电脑前就不愿意动,不喝水也不起来走动,一下班离开电脑就头晕眼花.想起前两年被肾结石支配的恐惧o(╥﹏╥)o,,,还是写个小工具强制自己喝水防止复发吧.VS Code启动 ...

  8. Java基础(五):数组

    数组,一种应用非常广泛的数据结构,简单地来说就是一组类型相同且无序的元素的存储在固定长度且有序的内存空间. 创建一个数组 在Java中,我们可以通过[]去声明一个指定类型的数组 int[] a; // ...

  9. 常用的 Git 命令与场景

    Git 分布式版本控制系统 它拥有完整的版本控制功能,能够解决多人协作的问题 将自己的代码同步到 Github 上能够提升开发效率 git 会记录你每一次的版本修改操作 常用的 Git 操作 # 指定 ...

  10. 视觉目标跟踪算法——SRDCF算法解读

    首先看下MD大神2015年ICCV论文:Martin Danelljan, Gustav Häger, Fahad Khan, Michael Felsberg. "Learning Spa ...