使用 ANTLR4 生成代码分析 MYSQL

2023年1月12日 2059点热度 0人点赞 0条评论
内容纲要

环境搭建和生成

首先安装 Java 8 以上的版本。

打开 https://www.antlr.org/download.html
找到 "ANTLR tool itself ",或者直接点击 https://www.antlr.org/download/antlr-4.11.1-complete.jar 下载包。

file

然后打开 https://github.com/antlr/grammars-v4
下载对应语法分析模板。

file

执行命令生成 java 代码。

 java -jar antlr-4.11.1-complete.jar .\MySqlLexer.g4 -Dlanguage=Java

执行命令生成 C# 代码:

 java -jar antlr-4.11.1-complete.jar .\MySqlLexer.g4 -Dlanguage=CSharp
 java -jar antlr-4.11.1-complete.jar .\MySqlParser.g4 -Dlanguage=CSharp

file

C# 分析 SQL

引入 Antlr4.Runtime 库。

C# 可以这样分析 SQL:

    internal class Program
    {
        static void Main()
        {
            String input = "ALTER TABLE <code>sjzy_user_center</code>.<code>t_system</code>ADD COLUMN <code>Token</code> varchar(1000) NULL DEFAULT NULL COMMENT '子系统token' AFTER <code>AssociatedInternalSubsystem</code>;";
            ICharStream stream = CharStreams.fromString(input);
            ITokenSource lexer = new MySqlLexer(stream);
            ITokenStream tokens = new CommonTokenStream(lexer);
            MySqlParser parser = new MySqlParser(tokens);
            parser.BuildParseTree = true;
            StartSlaveContext tree = parser.startSlave();
            Console.WriteLine(tree.ToStringTree());
            P(tree.children);
        }
        static void P(IList<IParseTree> tree)
        {
            foreach (var item in tree)
            {
                if (item.ChildCount != 0)
                {
                    List<IParseTree> child = new List<IParseTree>(0);
                    for (int i = 0; i < item.ChildCount; i++)
                    {
                        child.Add(item.GetChild(i));
                    }
                    P(child);
                }
                else
                {
                    Console.WriteLine(item.ToStringTree());
                }
            }
        }
    }

file

每个 Token 都对应了一个 Type 类型,可以在 MySqlLexer.tokens 或 MySqlParser.tokens 文件中搜索到。

首先使用 tree.children 获取所有子节点,返回 IList<IParseTree> 列表,每个 IParseTree 下面有个 Payload 属性,里面记载了这个 Token 的所有特性。

                var token = item.Payload as CommonToken;

例如,STRING_LITERAL 表示关键词属于一个命名,

如果想查找数据库或表名称,或字段名称,可以这样搜索:

                if(token.Type == MySqlParser.STRING_LITERAL)
                {

                }
                if (token.Type == 1141)
                {

                }

痴者工良

高级程序员劝退师

文章评论