简介

Spark SQL、Presto --> Antlr4 SQL 解析器

Flink SQL --> Apache Calcite(通过JavaCC 实现)

Spark SQL如何进行语法解析:

Spark SQL 最终是转换为RDD调用代码, 然后被Spark Core 执行

Antlr4起的作用就是将SQL语句解析为未解析的逻辑计划

具体流程如下:

对于语法分析树有两种遍历机制:

  1. Listener:

我们可以自行实现ParseTreeListener来填充自己的逻辑, 每条规则都对应接口enter () 和exit() 方法

不需要显示遍历访问子节点

  1. 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'
  1. 定义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)

  1. 执行 antlr4 ArrayInit.g4 生成下列文件:

  • ArrayInitLexer: 词法解析器类识别我们语法中的文法规则和词法规则
  • ArrayInitParser: 语法解析器类
  • ArrayInit.tokens: ANTLR会给每个我们定义的词法符号指定一个数字形式的类型
  • ArrayInitListener,ArrayInitBaseListener:监听器类
  1. 我们实现将{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()
}
}
  1. 执行结果:

总结

本篇主要讲解了Antlr4解析器以及Spark SQL 的解析流程, 介绍了Antlr4抽象树两种遍历机制:listener 和visitor, 同时实现了一个简单的语法通过 Antlr4 listener方式遍历解析的案例.

下篇会介绍visitor 模式的案例以及实现一些语法并且会转换为Spark RDD去执行.

Antlr4 语法解析生成器(上)的更多相关文章

  1. Generator函数语法解析

    转载请注明出处: Generator函数语法解析 Generator函数是ES6提供的一种异步编程解决方案,语法与传统函数完全不同.以下会介绍一下Generator函数. 写下这篇文章的目的其实很简单 ...

  2. LR(1)语法分析器生成器(生成Action表和Goto表)java实现(二)

    本来这次想好好写一下博客的...结果耐心有限,又想着烂尾总比断更好些.于是还是把后续代码贴上.不过后续代码是继续贴在BNF容器里面的...可能会显得有些臃肿.但目前管不了那么多了.先贴上来吧hhh.说 ...

  3. LR(1)语法分析器生成器(生成Action表和Goto表)java实现(一)

    序言 : 在看过<自己实现编译器链接器>源码之后,最近在看<编译器设计>,但感觉伪代码还是有点太浮空.没有掌握的感觉,也因为内网几乎没有LR(1)语法分析器生成器的内容,于是我 ...

  4. 微服务效率工具 goctl 深度解析(上)

    前言 本文根据 安前松 的视频分享整理而来,视频回放地址如下: https://www.bilibili.com/video/BV1Hr4y1x7Ne goctl 的由来 1. goctl 的诞生 g ...

  5. MySQL- -Join语法解析与性能分析

    Mysql Join语法解析与性能分析 一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ...

  6. 转换器4:手写PHP转Python编译器,语法解析部分

    写完词法部分,又有很多杂事,周末终于有空来实现伟大的语法解析部分了. 撸完代码之后发现,程序太短了,不算上状态机,才186行(含注释),关键代码不到100行.运行调试过后,发现还行.居然可以解析One ...

  7. 在.NET Core中使用Irony实现自己的查询语言语法解析器

    在之前<在ASP.NET Core中使用Apworks快速开发数据服务>一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语 ...

  8. Lua编写wireshark插件初探——解析Websocket上的MQTT协议

    一.背景 最近在做物联网流量分析时发现, App在使用MQTT协议时往往通过SSL+WebSocket+MQTT这种方式与服务器通信,在使用SSL中间人截获数据后,Wireshark不能自动解析出MQ ...

  9. 用java实现编译器-算术表达式及其语法解析器的实现

    大家在参考本节时,请先阅读以下博文,进行预热: http://blog.csdn.net/tyler_download/article/details/50708807 本节代码下载地址: http: ...

  10. 用java实现一个简易编译器-语法解析

    语法和解析树: 举个例子看看,语法解析的过程.句子:“我看到刘德华唱歌”.在计算机里,怎么用程序解析它呢.从语法上看,句子的组成是由主语,动词,和谓语从句组成,主语是“我”,动词是“看见”, 谓语从句 ...

随机推荐

  1. Win32封装对话框类

    [主程序入口.cpp] #include <windows.h> #include <tchar.h> #include "resource.h" #inc ...

  2. 【Mac + Python + Selenium】之获取验证码图片code并进行登录

    自己新总结了一篇文章,对代码进行了优化,另外附加了静态图片提取文字方法,两篇文章可以结合着看:<[Python]Selenium自动化测试之动态识别验证码图片方法(附静态图片文字获取)> ...

  3. 性能、成本与 POSIX 兼容性比较: JuiceFS vs EFS vs FSx for Lustre

    JuiceFS 是一款为云环境设计的分布式高性能文件系统.Amazon EFS 易于使用且可伸缩,适用于多种应用.Amazon FSx for Lustre 则是面向处理快速和大规模数据工作负载的高性 ...

  4. JWT单点登录

    单点登录 概念:登录某集团的某一产品之后,访问其他产品的网站时就会是登录状态,比如登录QQ之后,进入QQ游戏的时候就是登录过的状态,具体实现方法有以下: Redis+token实现单点登录: 生成一个 ...

  5. Asp.net core 学习笔记之 Microsoft Graph API

    早年如果我们要读写用户得 outlook 内容是比较麻烦的, 要用许多 smtp 之类的方式. 现在终于是有了 http 级的 API 可以 call 了. 不仅仅是 outlook, calenda ...

  6. Excel 国产化替换新方案

    前言 在当前数字化转型和信创(信息技术应用创新)战略背景下,企业对于安全性.自主可控性和高效办公工具的需求日益增加.作为一款国产自主研发的高性能表格控件,SpreadJS 正成为替换 Excel 的最 ...

  7. 微信js-sdk接入原理

    1.有一个微信公众号,并获取到该公众号的AppID和AppSecret. 其中AppID是可以对外公开的,AppSecret是该公众号的密钥,是需要绝对保密的 2.向微信服务器发送一个GET请求,获取 ...

  8. [Tkey] 与非

    解法原理1 首先我们需要明白 \(\operatorname{nand}\) 的运算: \[\operatorname{not}(a\operatorname{nand}b)=a\operatorna ...

  9. Windows远程设置''不可复制''的权限

    起因: 有一个技术部门的同事需要远程其他同学的电脑进行操作,但是不允许他复制目标电脑上的文件,避免造成资料外泄 解决办法: 组策略编辑器中,设置 计算机配置 -> 管理模板 -> wind ...

  10. TLB一致性维护

    TLB 是页表项的物理 cache,用于加速虚拟地址到物理地址的转换.CPU 在访问一个虚拟地址时,首先会在 TLB 中查找,如果找不到对应的表项,那么就称之为 TLB miss,此时就需要去内存里查 ...