微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从ANTLR解析树中提取特定令牌

如何解决从ANTLR解析树中提取特定令牌

我正在尝试从ANTLR解析树中提取数据,但没有完全掌握应如何正确完成操作

假设我有以下两个SQL查询

        // language=sql
        val sql3 = """
        CREATE TABLE session(
            id           uuid                    not null
                constraint account_pk
                    primary key,created     timestamp   default Now() not null
        )
        """.trimIndent()

        // language=sql
        val sql4 = """
            CREATE TABLE IF NOT EXISTS blah(
                id           uuid                    not null
                constraint account_pk
                    primary key,created     timestamp   default Now() not null
            )
        """.trimIndent()

现在我同时解析它们:

        val visitor = Visitor()
        listof(sql3,sql4).forEach { sql ->
            val lexer = sqlLexer(CharStreams.fromString(sql))
            val parser = sqlParser(CommonTokenStream(lexer))

            visitor.visit(parser.sql())
            println(visitor.tableName)

        }

在我的访客中,如果我访问tableCreateStatement,我会得到解析树,但是显然抓取child1将对sql3有效,但对sql4无效,因为sql4中的child1为{ {1}}

IF NOT EXISTS

有没有办法在解析树中找到特定的令牌?

我假设有效载荷与它有关,但是由于它的类型为class Visitor : sqlParserBaseVisitor<Unit>() { var tableName = "" override fun visitCreate_table_statement(ctx: sqlParser.Create_table_statementContext?) { tableName = ctx?.getChild(1)?.text ?: "" super.visitCreate_table_statement(ctx) } } ,所以我不确定要对它进行检查吗

Any

编辑 :. g4文件来自 https://github.com/pgcodekeeper/pgcodekeeper/tree/master/apgdiff/antlr-src

解决方法

这似乎可行

    override fun visitCreate_table_statement(ctx: SQLParser.Create_table_statementContext?) {
        ctx?.children?.forEach {
            if (it.payload.javaClass == Schema_qualified_nameContext::class.java) {
                tableName = it.text
            }
        }
        super.visitCreate_table_statement(ctx)
    }

对于分支树

    fun walkLeaves(
        childTree: ParseTree = internalTree,leave: (childTree: ParseTree) -> Unit) {

        if (childTree.childCount == 0) {
            if (!childTree.text?.trim().isNullOrBlank()) {
                leave(childTree)
            }
        } else {
            for (i in 0 until childTree.childCount) {
                walkLeaves(childTree = childTree.getChild(i),leave = leave)
            }
        }
    }
fun extractSQL(
    childTree: ParseTree,tokens: MutableList<String> = mutableListOf()
): String {

    walkLeaves(childTree = childTree) { leave ->
        tokens.add(leave.text)
    }

    ...

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。