SparkSQL源码分析系列03-Antlr4分析测试

SparkSQL主要通过Antlr4定义SQL的语法规则,完成SQL词法,语法解析,最后将SQL转化为抽象语法树。所以有必要先了解下Antlr4的工作流程。

ANTLR4是什么?

ANTLR 是 ANother Tool for Language Recognition 的缩写,官网:https://www.antlr.org/
它是一款强大的语法分析器生成工具,可用于读取、处理、执行和翻译结构化的文本或二进制文件。
包括:自动生成词法分析器 (Lexer)、语法分析器 (Parser) 和树分析器 (Tree Parser)。

词法分析器(Lexer):词法分析器的工作是分析量化那些本来毫无意义的字符流,将他们翻译成离散的字符组(也就是一个一个的Token),供语法分析器使用。
语法分析器(Parser):语法分析器将把收到的Tokens组织起来,并转换成语法规则定义的所允许的结构。
树分析器 (tree parser):树分析器可以用于对语法分析生成的抽象语法树进行遍历,并能执行一些相关的操作。

解析流程图:
在这里插入图片描述

  1. IDEA新建maven工程,导入如下依赖,注意antlr版本和安装的antlr插件版本保持一致。
    在这里插入图片描述

  2. 使用 ANTLR 的专门语法写一个简单的词法语法解析文件,并根据此文件自动生成相关词法语法解析的java文件。
    将编写的文件放到resources文件夹下,实现一个简答的数字加法功能:AddExpr.g4

    grammar AddExpr;
    
    // parser
    stat : expr;
    
    //定义表达式 :expr 表达式可以是数字(INT),也可以是加法运算表达式
    expr : expr op='+' expr   # AddSub
        | INT                 # int
        ;
    
    //lexer
    INT : [0-9]+ ;  // 运算数为整数的任意组合
    ADD : '+' ;  //加法
    

    在编写的AddExpr.g4文件上右键,选择 Configure ANTLR
    在这里插入图片描述
    填写代码生成的位置和包名
    在这里插入图片描述
    在编写的AddExpr.g4文件上右键,选择 Configure ANTLR Recognizer,就会在配置好的目录下生成代码了。
    在这里插入图片描述
    在这里插入图片描述

  3. 在test文件夹下建一个测试文件,以测试刚才生成的java代码
    在这里插入图片描述
    AddExprTest

    import com.addexpr.AddExprBaseVisitor;
    import com.addexpr.AddExprLexer;
    import com.addexpr.AddExprParser;
    import org.antlr.v4.runtime.ANTLRInputStream;
    import org.antlr.v4.runtime.CommonTokenStream;
    import org.antlr.v4.runtime.tree.ParseTree;
    
    public class AddExprTest {
        public static void run(String expr) {
    
            //对每一个输入的字符串,构造一个 ANTLRStringStream 流 in
            ANTLRInputStream in = new ANTLRInputStream(expr);
    
            //用 in 构造词法分析器 lexer,词法分析的作用是产生记号
            AddExprLexer lexer = new AddExprLexer(in);
    
            //用词法分析器 lexer 构造一个记号流 tokens
            CommonTokenStream tokens = new CommonTokenStream(lexer);
    
            //再使用 tokens 构造语法分析器 parser,至此已经完成词法分析和语法分析的准备工作
            AddExprParser parser = new AddExprParser(tokens);
    
            //最终调用语法分析器的规则 stat,完成对表达式的验证
            ParseTree tree = parser.stat();
            System.out.println("------------------AstTree-------------------");
            System.out.println(tree.toStringTree(parser));
    
            //遍历语法树--返回null
            AddExprBaseVisitor<Integer> visitor = new AddExprBaseVisitor<>();
            visitor.visit(tree);
            System.out.println(visitor.visit(tree));
    
            //原生的visitor遍历树结果返回null,并不是想要的结果,需要自定义重新实现
            //MyAddVisitor类就对应SparkSQL中的ASTBuild类
            MyAddVisitor myAddVsitor = new MyAddVisitor();
            System.out.println(myAddVsitor.visit(tree));
        }
    
        public static void main(String[] args) {
            String s = "1+2";
            run(s);
        }
    }
    
  4. 从代码运行结果中可以看出,原生的visitor遍历树结果返回null,并不是想要的结果,实际使用过程中,需要自定义重新实现visitor遍历方法,实际上,Spark源码中也是做的重新实现。代码中的 MyAddVisitor 类就对应SparkSQL中的 ASTBuild 类,就是自定义的实现类。代码如下:

    MyAddVisitor

    import com.addexpr.AddExprBaseVisitor;
    import com.addexpr.AddExprParser;
    
    /**
     * 自定义的Visitor实现类
     */
    public class MyAddVisitor extends AddExprBaseVisitor<Integer> {
    
        @Override
        public Integer visitStat(AddExprParser.StatContext ctx) {
            return visitChildren(ctx);
        }
    
        @Override
        public Integer visitAddSub(AddExprParser.AddSubContext ctx) {
    
            Integer left = visit(ctx.expr(0));        //获取左边表达式最终值
            Integer right = visit(ctx.expr(1));       //获取右边表达式最终值
    
            return left + right;
        }
    
        @Override
        public Integer visitInt(AddExprParser.IntContext ctx) {
            return Integer.parseInt(ctx.INT().getText());
        }
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/80940.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3D沉浸式旅游网站开发案例复盘【Three.js】

Plongez dans Lyon网站终于上线了。 我们与 Danka 团队和 Nico Icecream 共同努力&#xff0c;打造了一个令我们特别自豪的流畅的沉浸式网站。 这个网站是专为 ONLYON Tourism 和会议而建&#xff0c;旨在展示里昂最具标志性的活动场所。观看简短的介绍视频后&#xff0c;用户…

数据结构基础

将节点构建成树 数据的结构逻辑结构集合线性结构树形结构图状结构 存储结构合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如…

vue2.0/vue3.0学习笔记——2022.08.16

vue2&#xff08;查漏补缺&#xff09; 一、vue基础 内置指令&#xff08;查漏补缺&#xff09; 1、v-text 更新元素的textContent 2、v-html 更新元素的innerHtml 3、v-cloak 防止闪现&#xff0c;与css配合: [v-cloak] {dispaly: none} 4、v-once 在初次动态渲染厚&#x…

wxPython使用matplotlib绘制动态曲线

1.思路 我们创建了一个继承自wx.Frame的自定义窗口类MyFrame。在MyFrame的构造函数中&#xff0c;我们创建了一个matplotlib的Figure对象和一个FigureCanvas对象&#xff0c;用于在窗口中显示绘图结果。然后&#xff0c;我们使用numpy生成了一个包含100个点的x轴坐标数组self.…

Java IO流(二)IO模型(BIO|NIO|AIO)

概述 Java IO模型同步阻塞IO&#xff08;BIO&#xff09;、同步非阻塞IO&#xff08;NIO&#xff09;、异步非阻塞IO&#xff08;AIO/NIO2&#xff09;,Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种IO模型的封装 IO模型 BIO(Blocking I/O) 概述 BIO是一种同步并阻…

Linux实用运维脚本分享

Linux实用运维脚本分享&#x1f343; MySQL备份 目录备份 PING查询 磁盘IO检查 性能相关 进程相关 javadump.sh 常用工具安装 常用lib库安装 系统检查脚本 sed进阶 MySQL备份 #!/bin/bashset -eUSER"backup" PASSWORD"backup" # 数据库数据目录…

C++ Builder 关于TRichEdit的字符颜色标记处理

//积累经验每一天&#xff0c;以后忘记好搜索 void __fastcall TForm2::btn3Click(TObject *Sender) { //初始化验证 mmo->SelStart0; mmo->SelLengthmmo->Text.Length(); mmo->SelAttributes->ColorclBlack; String CGhEd…

如何使用Kali Linux进行渗透测试?

1. 渗透测试简介 渗透测试是通过模拟恶意攻击&#xff0c;评估系统、应用或网络的安全性的过程。Kali Linux为渗透测试人员提供了丰富的工具和资源&#xff0c;用于发现漏洞、弱点和安全风险。 2. 使用Kali Linux进行渗透测试的步骤 以下是使用Kali Linux进行渗透测试的基本…

visual studio 2017 运行的程序关闭后不能再运行?(visual studio建立项目之后退出,如何再次完整打开项目?)

在你储存项目的文件夹里面应该是这样的 里面.vcxproj后缀名的就是原来创建的项目&#xff0c;直接打开这个头文件源文件就会一起出来了&#xff01; 真的管用&#xff0c;亲测有效。

干翻Dubbo系列第十二篇:Dubbo协议介绍

文章目录 文章说明 一&#xff1a;Dubbo协议 1&#xff1a;Dubbo协议简介 2&#xff1a;Dubbo协议优点 3&#xff1a;Dubbo协议帧的组成 (一)&#xff1a;幻数 (二)&#xff1a;2Way (三)&#xff1a;event (四)&#xff1a;Serilization ID (五)&#xff1a;status …

【C++进阶】继承、多态的详解(多态篇)

【C进阶】继承、多态的详解&#xff08;多态篇&#xff09; 目录 【C进阶】继承、多态的详解&#xff08;多态篇&#xff09;多态的概念多态的定义及实现多态的构成条件&#xff08;重点&#xff09;虚函数虚函数的重写&#xff08;覆盖、一种接口继承&#xff09;C11 override…

常见指令以及权限理解

常见指令以及权限理解 命令格式&#xff1a; command [-options] parameter1 parameter1 命令 选项 参数1 参数2 1.command为命令名称&#xff0c;例如变化目录的cd等 2.中括号[ ]实际在命令中是不存在的&#xff0c;这个中括号代表可选&#xff0c;通常选项前面会添加一个符号…

K8S deployment挂载

挂载到emptyDir 挂载在如下目录&#xff0c;此目录是pod所在的node节点主机的目录&#xff0c;此目录下的data即对应容器里的/usr/share/nginx/html&#xff0c;实现目录挂载&#xff1b;图1红框里的号对应docker 的name中的编号&#xff0c;如下俩个图 apiVersion: apps/v1 k…

Sentinel规则持久化

首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中&#xff0c;接着注册的写数据源会将新的规则保存到本地的文件中。 示例代码&#xff1a; 1.编写处理类 //规则持久化 public class FilePersistence implements InitFunc {Value("spring.application:n…

Qt应用开发(基础篇)——高级纯文本窗口 QPlainTextEdit

一、前言 QPlainTextEdit类继承于QAbstractScrollArea&#xff0c;QAbstractScrollArea继承于QFrame&#xff0c;是Qt用来显示和编辑纯文本的窗口。 滚屏区域基类https://blog.csdn.net/u014491932/article/details/132245486?spm1001.2014.3001.5501框架类QFramehttps://blo…

服务器数据库中了360后缀勒索病毒怎么办?360后缀勒索病毒的加密形式

随着信息技术的发展&#xff0c;企业的计算机服务器数据库变得越来越重要。然而&#xff0c;在数字时代&#xff0c;网络上的威胁也日益增多。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的计算机服务器遭到了360后缀勒索病毒的攻击&#xff0c;导致服务器内的所有…

【计算机视觉】相机基本知识(还在更新)

1.面阵工业相机与线阵工业相机 1.1 基本概念区别 面阵相机则主要采用的连续的、面状扫描光线来实现产品的检测&#xff1b; 线阵相机即利用单束扫描光来进行物体扫描的工作的。 1.2 优缺点 &#xff08;1&#xff09;面阵CCD工业相机&#xff1a; 优点&#xff1a;应用面…

Maven - 统一构建规范:Maven 插件管理最佳实践

文章目录 Available Plugins开源项目中的使用插件介绍maven-jar-pluginmaven-assembly-pluginmaven-shade-pluginShade 插件 - 标签artifactSetrelocationsfilters 完整配置 Available Plugins https://maven.apache.org/plugins/index.html Maven 是一个开源的软件构建工具&…

图数据库_Neo4j和SpringBoot整合使用_创建节点_删除节点_创建关系_使用CQL操作图谱---Neo4j图数据库工作笔记0009

首先需要引入依赖 springboot提供了一个spring data neo4j来操作 neo4j 可以看到它的架构 这个是下载下来的jar包来看看 有很多cypher对吧 可以看到就是通过封装的驱动来操作graph database 然后开始弄一下 首先添加依赖

核能的发展与应用

目录 1.核能的概念 2.核能的实现原理 3.核能的利与弊 4.核能未来的发展趋势 1.核能的概念 核能是指利用核反应过程中释放出的能量来产生电力或其他形式能量的能源形式。核能主要通过核裂变和核聚变两种方式产生。 1. 核裂变&#xff1a;核裂变是指重核&#xff08;通常是铀、…