SQL - 词法/语法分析各种方案总结

SQL 词法/语法分析

一、技术实现方案

1. Lex + Yacc

  • Lex:词法分析 - flex
  • Yacc:语法分析 - bison
  • 搭载语言:C语言
  • 弊端:移植性不够,需要和以自动机为原理的YACC/LEX生成的一大堆整数表打交道。
    相当于从零开始造轮子,遂短时间不建议实验。
    不过也建议花十分钟简单看一下,在整个领域,他们实在太经典了,后面轻量级的 ANTLR 里面都有他们的思想。

2. ANTLR

  1. 参考资料:

  2. ANTLR 总览:
    工作总流程:词法分析,而后进行语法分析,语义分析,构建sql的AST

    • 词法分析器(Lexer):
      词法分析器的工作是分析量化那些本来毫无意义的字符流,将他们翻译成离散的字符组(也就是一个一个的Token),包括关键字,标识符,符号(symbols)和操作符 供语法分析器使用。
    • 语法分析器(Parser):
      编译器又称为Syntactical analyser。在分析字符流的时候,Lexer不关心所生成的单个Token的语法意义及其与上下文之间的关系,而这就是Parser的工作。语法分析器将收到的Tokens组织起来,并转换成为目标语言语法定义所允许的序列。

      无论是Lexer还是Parser都是一种识别器,Lexer是字符序列识别器而Parser是Token序列识别器。他们在本质上是类似的东西,而只是在分工上有所不同而已。
    • 树分析器 (tree parser):
      树分析器可以用于对语法分析生成的抽象语法树进行遍历,并能执行一些相关的操作。
    • ANTLR:
      ANTLR将上述结合起来,它允许我们定义识别字符流的词法规则 和 用于解释Token流的语法分析规则。
      然后,ANTLR将根据用户提供的语法文件自动生成相应的词法/语法分析器。
      用户可以利用他们将输入的文本进行编译,并转换成其他形式(如AST—Abstract Syntax Tree,抽象的语法树)。

  3. ANTLR环境安装:

  4. ANTLR 语法结构:

        //声明语法头,类似于java类的定义
        grammar Name; 
    
        //选项,如语言选项,输出选项,回溯选项,记忆选项等等
        options {...}
        import ... ;
    
        // 符号(Token)名大写开头
        // 解析规则(Parser rule)名小写开头,后面可以跟字母、数字、下划线    
        tokens {...}
        channels {...} // lexer only
        @actionName {...}
    
        // rule - 这是核心,表示规则,以 “:” 开始, “;” 结束, 多规则以 "|" 分隔。    
        rule1 // parser and lexer rules, possibly intermingled
        ...
        ruleN
    
  5. ANTLR 使用流程:
    ANTLR 官方demo:https://github.com/antlr/grammars-v4
    官方仓库中提供了 ANTLR 多个方向的 ANTLR,关于 SQL 的 词法/语法解析,该仓库中也有提供。
    ANTLR使用过程如下

    • 编写文法文件(g4后缀)
    • 使用g4文法文件通过antlr工具生成lexer词法解析器、parser语法解析器、visitor和listener的runtime target文件(支持多种语言)
    • 直接使用输出的runtime target文件模块进行开发工作
  6. ANTLR 实战:
    参考我的另一篇博客:ANTLR 实战 SQL 词法/语法分析
    https://blog.csdn.net/pentiumCM/article/details/106077486


3. ANTLR 的 IDE ——ANTLRWorks2

  • 参考资料:https://blog.csdn.net/u014454538/article/details/86351781


4. jsqlparser - 基于javacc实现的解析器JSqlParser

  1. 调用 Java 的 jar 包(相当于直接使用别人封装好的,自己拿过来使用即可)
  2. 搭载语言:java
  3. 参考资料:
  4. 使用方式:
    • maven 的 pom.xml 中添加如下的依赖:
      <!-- jsqlparser解析SQL工具类-->
      <dependency>
          <groupId>com.github.jsqlparser</groupId>
          <artifactId>jsqlparser</artifactId>
          <version>1.4</version>
      </dependency>
      
    • jsqlparser 语法demo:
      package indi.pentiumcm.utils;
      
      import net.sf.jsqlparser.JSQLParserException;
      import net.sf.jsqlparser.expression.Expression;
      import net.sf.jsqlparser.parser.CCJSqlParser;
      import net.sf.jsqlparser.parser.CCJSqlParserUtil;
      import net.sf.jsqlparser.parser.ParseException;
      import net.sf.jsqlparser.schema.Column;
      import net.sf.jsqlparser.statement.Statement;
      import net.sf.jsqlparser.statement.Statements;
      import net.sf.jsqlparser.statement.select.Select;
      import net.sf.jsqlparser.statement.select.SelectBody;
      import net.sf.jsqlparser.util.AddAliasesVisitor;
      import net.sf.jsqlparser.util.SelectUtils;
      import net.sf.jsqlparser.util.TablesNamesFinder;
      
      import java.util.List;
      
      /**
       * @projName: JavaSkillStack
       * @packgeName: indi.pentiumcm.utils
       * @className: jsqlparserUtils
       * @author: pentiumCM
       * @email: 842679178@qq.com
       * @date: 2020/5/11 22:22
       * @describe: jsqlparser工具类
       */
      public class jsqlparserUtils {     
      
          public static void main(String[] args) throws JSQLParserException, ParseException {
      
              //1、简单的语句解析
              // 1.1 单个语句
              String sql = "SELECT * FROM TABLE1";
              //方法1
              Statement statement = CCJSqlParserUtil.parse(sql);
              //方法2
              CCJSqlParser ccjSqlParser = new CCJSqlParser(sql);
              Statement statement2 = ccjSqlParser.Statement();
      
              // 1.2 多个语句
              String sqls = "SELECT * FROM TABLE1;SELECT * FROM TABLE2";
              //方法1
              Statements statements = CCJSqlParserUtil.parseStatements(sqls);
              //方法2
              CCJSqlParser ccjSqlParser2 = new CCJSqlParser(sqls);
      //        Statements statements3 = ccjSqlParser.Statements();
      
              List<Statement> statementList = statements.getStatements();
      
      
              // 2、简单的表达式解析
              //表达式
              Expression expression = CCJSqlParserUtil.parseExpression("a+b*c");
              //条件表达式
              Expression expression2 = CCJSqlParserUtil.parseCondExpression("A='123'");
      
      
              // 3、从SQL中提取表名
              String sql3 = "SELECT * FROM TABLE1";
              Statement statement3 = CCJSqlParserUtil.parse(sql);
              TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
              List<String> tableList = tablesNamesFinder.getTableList(statement);
      
      
              // 4、将别名应用于所有表达式
              Select select = (Select) CCJSqlParserUtil.parse("SELECT A,B,C FROM TABLE1");//此处的运行时类是Select
              SelectBody selectBody = select.getSelectBody();
              AddAliasesVisitor addAliasesVisitor = new AddAliasesVisitor();
              addAliasesVisitor.setPrefix("B");//设置前缀(如不进行设置默认为“A”)
              selectBody.accept(addAliasesVisitor);
              System.out.println(selectBody.toString());//SELECT A AS B1, B AS B2, C AS B3 FROM TABLE1
      
      
              // 5、向SELECT添加一列或表达式
              Select select5 = (Select) CCJSqlParserUtil.parse("SELECT A FROM TABLE1");
              SelectUtils.addExpression(select, new Column("B"));
              System.out.println(select);//SELECT A, B FROM TABLE1
          }
      }
      

4. Javacc/AST

  1. Javacc/AST简介:
    JavaCC 是一个代码生成器,可以根据输入的语言定义输出一个词法分析器和解析器,JavaCC 输出的代码是合法的可编译Java代码.

    解析器和词法分析器本身就是一个冗长而复杂的组件,手工编写一个这样的程序需要仔细考虑各条件的相互作用,总的来说,通过javacc完成一些字符串的分析,还是比较方便,现在普遍使用AST了。
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
西安电子科技大学(西电)的SQL词法分析器是一种用于解析SQL语言的工具。SQL(Structured Query Language)是用于操作关系型数据库的标准语言,用于创建、查询、修改和管理数据库中的数据。 词法分析器是编译器的一部分,它负责将从源代码中读取的字符序列转化为有意义的独立单元,这些单元被称为"词法记号"。SQL词法分析器的主要任务是确定输入的SQL语句中的关键字、标识符、运算符、分隔符等信息,并对其进行分类。 在西电的SQL词法分析器中,首先会对输入的SQL语句进行字符扫描,将其划分为独立的字符序列。然后,通过词法规则和状态转换机制,将这些字符序列识别为不同的词法记号。常见的词法记号包括SELECT、FROM、WHERE等关键字,以及表名、列名等标识符。 词法分析器还可以识别SQL语句中的运算符(如等于、大于、小于等)、分隔符(如逗号、分号等)以及注释。通过对词法分析的结果进行分类和记录,可以为后续的语法分析和语义分析提供有效的输入。 西电的SQL词法分析器不仅可以在编译器设计与实现课程中起到教学作用,还可以用于实际的数据库管理系统中,提高对SQL语句的解析和处理效率。通过将SQL语句转化为独立的词法记号,可以方便地进行后续的语法分析、优化和执行计划生成等操作,从而实现高效的数据库查询和管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值