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

news2024/11/13 9:45:34

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());
        }
    }
    

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python:逢七拍腿游戏

场景模拟&#xff1a; 通过在 for 循环中使用 continue 语句实现计算拍腿次数&#xff0c;即计算从1到100&#xff08;不包括100&#xff09;&#xff0c;一共有多少个尾数为7或7的倍数这样的游戏&#xff0c;代码如下&#xff1a; total 99 # 记…

解读李子园2023上半年财报:营收净利双增,未来持续聚焦大单品?

时至今日&#xff0c;饮料界已经分化出了诸多新品类&#xff0c;无糖气泡水、功能饮料、碳酸饮料、茶饮料、含乳饮料等等层出不穷&#xff0c;令人眼花缭乱。这一现象促使全行业产品都在向多样化转变&#xff0c;其中乳制品的结构分化尤为明显。 然而&#xff0c;身处“局中”…

AB跳转轮询:让你的独立站收款智能化

独立站在近两年成为跨境电商的热门布局之一&#xff0c;特别是在亚马逊封号潮后&#xff0c;许多卖家开始转向独立站运营。然而&#xff0c;在迅速发展的同时&#xff0c;也不可避免地出现了一些问题&#xff0c;比如很多卖家的资金经常被不同程度地冻结&#xff0c;好不容易出…

AI问答:JSBridge / WebView 与 Native 通信

一、理解JSBridge JSBridge是一种连接JavaScript和Native代码的桥梁&#xff0c;它提供了一种方法&#xff0c;使得JavaScript可以直接调用Native的代码&#xff0c;同时使得Native的代码也能直接调用JavaScript的方法&#xff0c;从而实现了JavaScript和Native之间的相互调用和…

GNN学习笔记

GNN b站课程跳转------->>>>> 【不愧是公认最好的【图神经网络GNN/GCN教程】&#xff0c;从基础到进阶再到实战&#xff0c;一个合集全部到位&#xff01;-人工智能/神经网络/图神经网络/深度学习。】 https://www.bilibili.com/video/BV1184y1x71H/?share_so…

【C#】条码管理操作手册

前言&#xff1a;本文档为条码管理系统操作指南&#xff0c;介绍功能使用、参数配置、资源链接&#xff0c;以及异常的解决等。思维导图如下&#xff1a; 一、思维导图 二、功能操作–条码打印&#xff08;客户端&#xff09; 2.1 参数设置 功能介绍&#xff1a;二维码图片样…

ELF文件格式分析(一)

目录 一、ELF 格式介绍二、ELF组成部分2.1) ELF Header2.2) Program Headers2.3&#xff09;Section Headers Table2.3.2&#xff09; Section 此篇文章介绍了ELF文件由哪些部分组成&#xff0c;他们的功能是什么&#xff0c;并在文章末尾给出了一份ELF文件解析的参考资料。 一…

通达信袋鼠尾形态选股公式,也称手指线

在《以交易为生》这本书中&#xff0c;作者埃尔德提到“袋鼠尾”形态&#xff08;也称“手指线”&#xff09;&#xff0c;这是作者比较认可的图表信号&#xff0c;很有吸引力&#xff0c;也容易辨认。 袋鼠靠尾巴推动前进&#xff0c;跳跃方向和它的尾巴方向相反&#xff0c;…

Docker容器监控系统

目录 简化描述 Cadvisor InfluxDBGrafana 监控组件架构图 部署 安装docker-ce 阿里云镜像加速器 下载组件镜像 创建自定义网络 创建influxdb容器 创建granafa容器 简化描述 Docker作为目前十分出色的容器管理技术&#xff0c;得到大量企业的青睐&#xff0c;在生产环…

深度解读波卡 2.0:多核、更有韧性、以应用为中心

本文基于 Polkadot 生态研究院整理&#xff0c;有所删节 随着波卡 1.0 的正式实现&#xff0c;波卡于 6 月 28 日至 29 日在哥本哈根举办了年度最重要的会议 Polkadot Decoded 2023&#xff0c;吸引了来自全球的行业专家、开发者和爱好者&#xff0c;共同探讨和分享波卡生态的…

数据结构 - 算法的时间效率和空间效率

一、时间效率 程序在计算机上执行所消耗的时间。 两种估算方式&#xff1a; 事后统计事前分析 算法运行时间 一个简单操作所需的时间X简单操作次数 算法运行总时间 Σ每条语句执行次数&#xff08;即&#xff1a;每条语句频度&#xff09;X该语句执行一次所需的时间 每条语…

【SpringCloud】Hystrix使用

文章目录 Hystrix重要概念使用POM启动类YML示例Global fallback 服务降级&#xff0c;客户端去调用服务端&#xff0c;碰上服务端宕机或关闭服务熔断HystrixCommand中commandProperties参数 Hystrix执行流程服务监控hystrixDashboardPOM Hystrix重要概念 https://github.com/N…

Golang Gorm 更新字段 save update updates

更新和删除操作的前提条件都是要在找到数据的情况下&#xff0c;先要查询到数据才可以做操作。 更新的前提的先查询到记录&#xff0c;Save保存所有字段&#xff0c;用于单个记录的全字段更新它会保控所有字段&#xff0c;即使零值也会保存。 在更新和删除之前&#xff0c;要利…

Python学习笔记_进阶篇(二)_django知识(一)

本章简介&#xff1a; Django 简介Django 基本配置Django urlDjango viewDjango 模板语言Django Form Django 简介 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MVC的软件设计模式&#xff0c;即模型M&#xff0c;视图V和控制器C。它最初是被开发来…

不知道开黑语音哪个软件好?

黑盒语音官方网站&#xff1a;https://chat.top 免费支持AI降噪免费支持高品质立体声免费支持码率128Kbps,192Kbps免费支持上传100M文件免费支持动态房间头像和横幅支持更多自定义动态表情即将支持更多免费功能

Lua 语言笔记(一)

1. 变量命名规范 弱类型语言(动态类型语言)&#xff0c;定义变量的时候&#xff0c;不需要类型修饰 而且&#xff0c;变量类型可以随时改变每行代码结束的时候&#xff0c;要不要分号都可以变量名 由数字&#xff0c;字母下划线组成&#xff0c;不能以数字开头&#xff0c;也不…

CSS:filter滤镜 详解(用法 + 代码 + 例子 + 效果)

文章目录 filter 滤镜blur() 模糊度例子 渐变光晕 brightness() 元素亮度contrast() 对比度grayscale() 元素灰度hue-rorate() 色相opacity() 透明度invert() 反转颜色saturate() 饱和度 backdrop-filter 蒙版&#xff0c;滤镜例子 卷轴展开 filter 滤镜 动图为效果添加前后对…

计算复杂度基础

1. 抽象问题 抽象问题包括决策问题和优化问题 注意&#xff1a;描述中&#xff0c;I的缩写是Instance&#xff0c;S的缩写是Solution。 2. 决策问题 3. 优化问题 将一个优化问题转换为决策问题后&#xff0c;不会变的更难。 \color {green}将一个优化问题转换为决策问题后&…

实验篇——多序列比对,构树

实验篇——多序列比对&#xff0c;构树 文章目录 前言一、名词解释二、实操1. 文件准备2. 多序列比对3. 对比对序列修剪4. 构建进化树5. 可视化进化树 总结 前言 系统发育树构建的软件大致有如下几种策略&#xff1a;从最简单的UPGMA法&#xff0c;到邻接法&#xff0c;最大简…

一文学会配置Fanuc控制柜端ROS2驱动

文章目录 前言一、RobotGuide是什么&#xff1f;二、实现步骤创建机器人工作单元导入程序TP程序Karel程序 构建程序配置控制柜配置机器人控制柜通讯配置可同时运行程序数量配置ROS_RELAY变量配置ROS_STATE变量设置启用标志 三、测试机器人状态反馈机器人命令接收整体运行测试 总…