mysql词法分析antlr4_Antlr4 - 自定义SparkSQL解析

Antlr4 是一个强大的解析器的生成器,可以用来读取、处理、执行或翻译结构化文本,ANTLR可以从语法上来生成一个可以构建和遍历解析树的解析器,最出名的Spark计算引擎2.x就是用它来解析SQL的,是一个牛到没朋友的家伙。

IDEA测试

插件安装

9122814dccd8?utm_source=oschina-app

antlr-v4-grammar分析插件

g4语法文件使用的是sparkSQL的 SqlBase.g4 文件进行改造的 ArcSql.g4

右键选中 multiStatement 进行测试

9122814dccd8?utm_source=oschina-app

antlr4

测试SQL语法树

9122814dccd8?utm_source=oschina-app

antlr4-SQL-测试

生成解析配置

9122814dccd8?utm_source=oschina-app

antlr4-生成解析代码

右键ArcSQL.g4文件,在下拉选项Configure ANTLR即可出来。

第一个Output directory...要写上输出代码的路径。

比如把它放到当前项目的antlr4的包中/dounine/github/arc/src/main/scala/com/dounine/arc/antlr4

右键ArcSQL.g4文件,选中Generate ANTLR Recognizer即可生成

会生成如下几个文件

ArcSQL.interp

ArcSQL.tokens

ArcSQLBaseListener

ArcSQLBaseVisitor

ArcSQLLexer

ArcSQLLexer.interp

ArcSQLLexer.tokens

ArcSQLListener

ArcSQLParser

ArcSQLVisitor

代码测试

依赖

compile group: 'org.antlr', name: 'antlr4', version: '4.7.2'

被动模式(树解析到节点了通知)

val loadLexer = new ArcSQLLexer(CharStreams.fromString(

"""

select toUp(name) from log;

"""))

val tokens = new CommonTokenStream(loadLexer)

val parser = new ArcSQLParser(tokens)

val ctx = parser.multiStatement()

val listener = new ArcSQLBaseListener() {

override def exitQuerySpecification(ctx: ArcSQLParser.QuerySpecificationContext): Unit = {

val input = ctx.start.getTokenSource.asInstanceOf[ArcSQLLexer]._input

val start = ctx.start.getStartIndex

val stop = ctx.stop.getStopIndex

val interval = new Interval(start, stop)

val sqlText = input.getText(interval)

println("表名 => " + ctx.tableAlias().strictIdentifier().getText)

println("完整SQL =>" + sqlText)

}

}

ParseTreeWalker.DEFAULT.walk(listener, ctx)

输出(在ctx中还有很多关于sql树信息)

表名 => log

完整SQL =>select toUp(name) from log

主动模式(主动去要数据)

val vistor = new ArcSQLBaseVisitor[Unit] {

override def visitQuerySpecification(ctx: QuerySpecificationContext): Unit = {

val input = ctx.start.getTokenSource.asInstanceOf[ArcSQLLexer]._input

val start = ctx.start.getStartIndex

val stop = ctx.stop.getStopIndex

val interval = new Interval(start, stop)

val sqlText = input.getText(interval)

println("表名 => " + ctx.tableAlias().strictIdentifier().getText)

println("完整SQL =>" + sqlText)

}

}

vistor.visit(ctx)

9122814dccd8?utm_source=oschina-app


版权声明:本文为weixin_35732670原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。