Sparksql 语法词法分析

发布于:2022-11-01 ⋅ 阅读:(492) ⋅ 点赞:(0)

Sparksql 语法词法分析

努力是一件特别需要沉下心来,长久坚持的事,它成长的土壤需要一个人单打独斗,忍受无数个孤独寂寞的日子。
心可以碎,手不能停,该干什么干什么在奔溃中继续前行,这才是一个成年人的素养。

前言

在这里插入图片描述

      我们输入的SQL会经过Antlr进行词法语法的解析,然后生成一个Ast Tree(抽象语法树),然后对Ast Tree进行遍历生成一个未解析的逻辑执行计划。

Antlr是什么?

相关概念:
词法分析:
    主要是一门用来研究无意义的字母是如何组成有意义的单词,比如we,eat,apple这三个单词是有具体的含义的,而组成这些单词的字母’a’, ‘p’, ‘p’, ‘l’, 'e’本身是没有具体的含义的,只有有序组成apple这个单词后,才赋予了具体概念的意义。
语法解析:
    一门用来研究有意义的单词如何组成更复杂意义的句子的技术

      词法语法解析对应到我们的sql中去,我们的sql主要是各种符号,字母,单词组成,词法分析就是我们sql中的每个单词应该怎么组成,语法解析就是这些单词该以怎样的结构去组成一个sql。比如,在写sql的时候把from写在select的前面,这个sql肯定会报错的,其实这就是语法解析中的一个规则。

在sparksql中,是使用antlr来解决sql的词法语法解析的
官网链接:http://www.antlr.org/
      它是一门强大的语法分析器生成工具,可用于读取,处理,执行和翻译结构化的文本或二进制文件自动生成词法分析器(Lexer),语法分析器(Parser)和树分析器(Tree Parser)

上述说的比较官方,简单理解来说,就是有人写了代码生成antlr工具,我们利用这个工具再结合定义好的规则,在这个规则下解析你写的语句,这样的一个解析器。

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

流程图
在这里插入图片描述

案例

创建一个新的maven项目,导入相关的依赖

这里选择的版本是4.8,主要是因为spark3.2主要依赖的是antlr4.8

<dependencies>
  <dependency>
    <groupId>org.antlr</groupId>
    <artifactId>antlr4-runtime</artifactId>
    <version>4.8</version>
  </dependency>
</dependencies>

antlr的开发流程:

  1. 定义一个.g4结尾的语法文件
  2. 基于语法文件 使用antlr可以生成词法分析器和语法分析器目标编程语言代码,支持的编程语言:Java, JavaScript,Python, C 和C++等
  3. 遍历 AST, antlr 4支持两种模式:访问者模式(Visitor)和监听者模式(Listener)

在resources下面新建一个.g4文件

grammar CalExpr;


// parser
prog : stat+;

stat : expr                 #printExpr
|ID '=' expr NEWLINE    #assign
|NEWLINE                #blank
;

expr : expr op=('+'|'-') expr   # AddSub
| expr op=('*'|'/') expr    # MulDiv
| ID                        # id
| INT                       # int
| '(' expr ')'              # parens
;


// lexer
IN : [a-zA-Z]+ ; // 变量可以为大写小写字母的任意组合
INT : [0-9]+ ; // 运算数为整数的任意组合
NEWLINE : [\r\n]+ ; // 匹配换行
WS : [ \t]+ -> skip ; // 跳过空格和 \t

ADD : '+' ;
SUB : '-' ;
MUL : '*' ;
DIV : '/' ;

简化版本

grammar AddExpr;

// parser
stat : expr;


expr : expr op='+' expr   # AddSub
    | INT                 # int
    ;


// lexer
INT : [0-9]+ ;

ADD : '+' ;

。。。。未完待续。。。。

本文含有隐藏内容,请 开通VIP 后查看