Antlr4 语法解析生成器(上)
简介
Spark SQL、Presto --> Antlr4 SQL 解析器
Flink SQL --> Apache Calcite(通过JavaCC 实现)
Spark SQL如何进行语法解析:
Spark SQL 最终是转换为RDD调用代码, 然后被Spark Core 执行
Antlr4起的作用就是将SQL语句解析为未解析的逻辑计划
具体流程如下:

对于语法分析树有两种遍历机制:
- Listener:
我们可以自行实现ParseTreeListener来填充自己的逻辑, 每条规则都对应接口enter () 和exit() 方法
不需要显示遍历访问子节点

- vistors:
显示访问每个子节点, 每条规则对应接口中visit () 方法

Antlr4应用案例
问题: 实现识别包裹在花括号或者嵌套的花括号中的整数 {1,2,3} 和 {1,{2,3}}
实现:
1. 配置Antlr 运行环境
OS X
$ cd /usr/local/lib
$ sudo curl -O https://www.antlr.org/download/antlr-4.7.2-complete.jar
$ export CLASSPATH=".:/usr/local/lib/antlr-4.7.2-complete.jar:$CLASSPATH"
$ alias antlr4='java -jar /usr/local/lib/antlr-4.7.2-complete.jar'
$ alias grun='java org.antlr.v4.gui.TestRig'
- 定义g4 语法文件
/** Grammars always start with a grammar header. This grammar is called
* ArrayInit and must match the filename: ArrayInit.g4
*/
grammar ArrayInit;
/** A rule called init that matches comma-separated values between {...}. */
init : '{' value (',' value)* '}' ; // must match at least one value
/** A value can be either a nested array/struct or a simple integer (INT) */
value : init
| INT
;
// parser rules start with lowercase letters, lexer rules with uppercase
INT : [0-9]+ ; // Define token INT as one or more digits
WS : [ \t\r\n]+ -> skip ; // Define whitespace rule, toss it out
grammars 关键字必须与 .g4 文件同名, 如果一个语法文件太大可以拆分成多个文件,相互依赖就是依赖 import + 关键字 文件名 语句
语法分析器的规则以小写字母开头( init和value)
词法分析器的规则以大小字母开头(INT和WS)
- 执行
antlr4 ArrayInit.g4生成下列文件:

- ArrayInitLexer: 词法解析器类识别我们语法中的文法规则和词法规则
- ArrayInitParser: 语法解析器类
- ArrayInit.tokens: ANTLR会给每个我们定义的词法符号指定一个数字形式的类型
- ArrayInitListener,ArrayInitBaseListener:监听器类
- 我们实现将{1,2,3 } 识别解析成字符串 “123”, 自定义监听器:
class ShortToUnicodeString extends ArrayInitBaseListener{
/**
* {@inheritDoc }
*
* <p>The default implementation does nothing.</p>
*/
override def enterInit(ctx: ArrayInitParser.InitContext): Unit = {
print('"')
}
/**
* {@inheritDoc }
*
* <p>The default implementation does nothing.</p>
*/
override def exitInit(ctx: ArrayInitParser.InitContext): Unit = {
print('"')
}
/**
* {@inheritDoc }
*
* <p>The default implementation does nothing.</p>
*/
override def enterValue(ctx: ArrayInitParser.ValueContext): Unit = {
val value = Integer.valueOf(ctx.INT().getText)
print(value)
}
}
将监听器配置到分析树上面:
object Translate {
def main(args: Array[String]): Unit = {
val input = new ANTLRInputStream("{1,2,3}")
//新建词法分析器
val lexer = new ArrayInitLexer(input)
//新建词法缓冲区,用于存储分析器生成的词法符号
val token = new CommonTokenStream(lexer)
//新建语法分析器用于处理词法缓冲区中的内容
val parser = new ArrayInitParser(token)
//针对规则开始语法分析
val tree = parser.init(); // begin parsing at init rule
val walker = new ParseTreeWalker()
//遍历解析期间创建的树,触发回调
walker.walk(new ShortToUnicodeString, tree)
println()
}
}
- 执行结果:

总结
本篇主要讲解了Antlr4解析器以及Spark SQL 的解析流程, 介绍了Antlr4抽象树两种遍历机制:listener 和visitor, 同时实现了一个简单的语法通过 Antlr4 listener方式遍历解析的案例.
下篇会介绍visitor 模式的案例以及实现一些语法并且会转换为Spark RDD去执行.
Antlr4 语法解析生成器(上)的更多相关文章
- Generator函数语法解析
转载请注明出处: Generator函数语法解析 Generator函数是ES6提供的一种异步编程解决方案,语法与传统函数完全不同.以下会介绍一下Generator函数. 写下这篇文章的目的其实很简单 ...
- LR(1)语法分析器生成器(生成Action表和Goto表)java实现(二)
本来这次想好好写一下博客的...结果耐心有限,又想着烂尾总比断更好些.于是还是把后续代码贴上.不过后续代码是继续贴在BNF容器里面的...可能会显得有些臃肿.但目前管不了那么多了.先贴上来吧hhh.说 ...
- LR(1)语法分析器生成器(生成Action表和Goto表)java实现(一)
序言 : 在看过<自己实现编译器链接器>源码之后,最近在看<编译器设计>,但感觉伪代码还是有点太浮空.没有掌握的感觉,也因为内网几乎没有LR(1)语法分析器生成器的内容,于是我 ...
- 微服务效率工具 goctl 深度解析(上)
前言 本文根据 安前松 的视频分享整理而来,视频回放地址如下: https://www.bilibili.com/video/BV1Hr4y1x7Ne goctl 的由来 1. goctl 的诞生 g ...
- MySQL- -Join语法解析与性能分析
Mysql Join语法解析与性能分析 一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ...
- 转换器4:手写PHP转Python编译器,语法解析部分
写完词法部分,又有很多杂事,周末终于有空来实现伟大的语法解析部分了. 撸完代码之后发现,程序太短了,不算上状态机,才186行(含注释),关键代码不到100行.运行调试过后,发现还行.居然可以解析One ...
- 在.NET Core中使用Irony实现自己的查询语言语法解析器
在之前<在ASP.NET Core中使用Apworks快速开发数据服务>一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语 ...
- Lua编写wireshark插件初探——解析Websocket上的MQTT协议
一.背景 最近在做物联网流量分析时发现, App在使用MQTT协议时往往通过SSL+WebSocket+MQTT这种方式与服务器通信,在使用SSL中间人截获数据后,Wireshark不能自动解析出MQ ...
- 用java实现编译器-算术表达式及其语法解析器的实现
大家在参考本节时,请先阅读以下博文,进行预热: http://blog.csdn.net/tyler_download/article/details/50708807 本节代码下载地址: http: ...
- 用java实现一个简易编译器-语法解析
语法和解析树: 举个例子看看,语法解析的过程.句子:“我看到刘德华唱歌”.在计算机里,怎么用程序解析它呢.从语法上看,句子的组成是由主语,动词,和谓语从句组成,主语是“我”,动词是“看见”, 谓语从句 ...
随机推荐
- 【团队建设】如何做好团队开发中的 CodeReview(代码评审)?
目录 前言 一.为什么要做 二.有哪些好处 三.具体怎么做 3.1评审条件 3.2评审重点 3.3评审形式 四.还可以怎么做 4.1提出亮点 4.2轮流评审 4.2文档沉淀 五.文章小结 前言 你是否 ...
- stm32学习之调试篇踩坑记录
如何下载fml文件 找不到64k的fml文件 could not stop cortex-m device:无法连接,我当时是在程序中的一些初始化函数中,有几条语句禁用了(JTAG+SW) 接线顺序, ...
- AI驱动的PlantUML:快速生成专业级UML图表
**对于程序员来说,编写验收文档中的各种UML图是最让人头疼的事情之一,相信各位读者对此深有体会.** 本文将探讨如何利用AI驱动的PlantUML来快速生成专业级别的UML图表,从而减轻这一负担. ...
- QT6窗口系统之QT底层窗口QWindow:QT框架中哪些常见窗口是基于QWindow的? 如何实现QT框架栅格窗口?如何实现QT框架OpenGL窗口?
QT6窗口系统之QT底层窗口QWindow:QT框架中哪些常见窗口是基于QWindow的? 如何实现QT框架栅格窗口?如何实现QT框架OpenGL窗口? 简介 本文介绍了QT6窗口系统中的QT底层窗口 ...
- [OI] Kruskal 重构树
算法介绍 Kruskal 重构树用于快速判断节点的连通性. 考虑到,假如两个节点是联通的,则他们之间总会有一条边被选入最小生成树内,因此他们在最小生成树内也是联通的. 也就是说,我们可以通过求最小生成 ...
- [使用目前最新版]HybridCLR6.9.0+YooAsset2.2.4实现纯C# Unity热更新方案 (一)
1.前言 什么是热更新 游戏或者软件更新时,无需重新下载客户端进行安装,而是在应用程序启动的情况下,在内部进行资源或者代码更新 Unity目前常用热更新解决方案 HybridCLR,Xlua,ILRu ...
- IP地址集中管控:从分配规划、现网管理到合规性监测、准入控制全周期监管
当前,网络已成为企业必不可少的资源,企业网络系统也在不断扩展,IP地址数量不断增长,随之而来的是IP地址管理问题凸显.如何高效集中地管理网络中的IP地址,IP如何有效划分,成为影响企业网络可用性和质量 ...
- 八字五行强弱喜用神测算api免费接口_json数据格式_可计算五行打分强弱
八字以木.火.土.金.水去分析其旺弱,而分析之法以月令地支最为有力,其次为时支,再次为日支,最弱为年支,而天干必须见地支有同类或有生自己的五行才有用,因为只有天干一个单独的五行,其力会弱至无用.这个接 ...
- Android Systrace 基础知识 -- Systrace 简介
1. 正文 Systrace 是 Android4.1 中新增的性能数据采样和分析工具.它可帮助开发者收集 Android 关键子系统(如 SurfaceFlinger/SystemServer/Ke ...
- 6款支持C#语言的AI辅助编程工具,开发效率提升利器!
前言 在这个AI迅速发展的阶段,涌现出了一大批好用的AI辅助编程工具.AI辅助编程工具能够提高开发效率.改善代码质量.降低bug率,是现代软件开发过程中的重要助手.今天大姚给大家分享6款AI辅助编程工 ...