龙空技术网

Calcite 之 JavaCC 应用概述

SapphireCoder 143

前言:

眼前大家对“cc与java”都比较珍视,同学们都想要知道一些“cc与java”的相关文章。那么小编在网络上网罗了一些对于“cc与java””的相关文章,希望兄弟们能喜欢,朋友们一起来学习一下吧!

导读:本文主要讨论 JavaCC 在 Calcite 中的应用,内容主要为以下三点:

一些相关的基础概念JavaCC 概述及生成的语法解析器的工作原理JavaCC 在 Calcite 中的应用基础概念JavaCC(Java Compiler Compiler):是一个开源的语法分析器生成器和词法分析器生成器。JavaCC根据输入的文法生成由Java语言编写的分析器。语法分析(syntactic analysis):是根据某种给定的形式文法对由单词序列构成的输入文本进行分析并确定其语法结构的一种过程。语法分析器(parser)通常是作为编译器或解释器的组件出现的,它的作用是进行语法检查、并构建由输入的单词组成的数据结构(一般是语法分析树(具体)、抽象语法树(AST)等层次化的数据结构)。语法分析器通常使用一个独立的词法分析器从输入字符流中分离出一个个的“单词”,并将单词流作为其输入。词法分析(lexical analysis):是计算机科学中将字符序列转换为标记(token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(lexical analyzer,简称lexer)。词法分析器一般以函数的形式存在,供语法分析器调用。抽象语法树(Abstract Syntax Tree,AST ):是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。比如,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。和抽象语法树相对的是具体语法树(通常称作分析树)。一般的,在源代码的翻译和编译过程中,语法分析器创建出分析树,然后从分析树生成AST。一旦AST被创建出来,在后续的处理过程中,比如语义分析阶段,会添加一些信息。JavaCC

JavaCC 根据文法(.jj 文件)生成由 Java 语言编写的语法分析器。分析器组成如下:

XXXXX 解析类入口XXXXXTokenManager 词法分析器XXXXXConstants Token常量SimpleCharStream 词法分析器的输入流Token类TokenMgrError 语法错误提示ParseException 语法解析异常

下图为 JavaCC 生成的语法分析器工作原理:

输入数据流词法分析器从输入字符流中分离出一个个的字符串,并转换为 Token。接下来进行语法分析,进行语法检查并构建由输入的单词组成的数据结构(分析树)分析树生成 AST 树

关于 JavaCC 详细语法感兴趣的朋友可阅读 这篇文章。

JavaCC 在 Calcite 中的应用

Calcite 应用了 JavaCC,其语法文件名为 Parser.jj。

Parser.jj 文件结构

options {    JavaCC的选项} PARSER_BEGIN(解析器类名)package 包名;import 库名; public class 解析器类名 {    任意的Java代码}PARSER_END(解析器类名) 语义分析代码片段语法描述(Syntactical Descriptions)词法描述(Lexical Descriptions)

Calcite 使用 FreeMarker 作为模板引擎,在编译时将 Parser.jj、config.fmpp、parserImpls.ftl 整合生成最终的语法描述文件,并通过 JavaCC 生成由 Java 语言编写的语法分析器。

语法文件

以下为 Calcite 内置关于 parser 的过程,Calcite 内置 Parser类 为 org.apache.calcite.prepare.CalcitePrepareImpl 类。在该类中

org.apache.calcite.sql.parser.SqlParser.ConfigBuilder parserConfig = this.createParserConfig()  //语法参数设置  .setQuotedCasing(config.quotedCasing())  .setUnquotedCasing(config.unquotedCasing())  .setQuoting(config.quoting())  .setConformance(config.conformance())  .setCaseSensitive(config.caseSensitive())  // 此处默认指定 JavaCC生成的解析器SqlParserImpl,也可指定为自定义的解析器  .setParserFactory(UDSqlParserImpl.FACTORY);;SqlParserImplFactory parserFactory = (SqlParserImplFactory)config.parserFactory(SqlParserImplFactory.class, (Object)null);if (parserFactory != null) {  parserConfig.setParserFactory(parserFactory);}SqlParser parser = this.createParser(query.sql, parserConfig);SqlNode sqlNode;try {  // 解析  sqlNode = parser.parseStmt();  statementType = this.getStatementType(sqlNode.getKind());} catch (SqlParseException var23) {  throw new RuntimeException("parse failed: " + var23.getMessage(), var23);}
总结

Calcite 基于定义好的语法文件通过 JavaCC 生成语法解析器。使用语法解析器解析输入的 SQL 语句并形成 AST 语法树。了解了这些知识后,感兴趣的朋友们可以查阅相关资料,尝试编写自定义SQL解析器,解析自定义的语法。

感谢您的阅读,如果喜欢本文欢迎关注和转发,本头条号将坚持持续分享IT技术知识。对于文章内容有其他想法或意见建议等,欢迎提出共同讨论共同进步。

参考链接

标签: #cc与java