searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Antlr4 Java使用

2024-11-08 09:21:15
0
0

创建 ANTLR4 语法文件

ANTLR4 使用 .g4 文件来定义语法,如下图

image.png

lexer grammar Comments;
​
import Symbol;
​
BLOCK_COMMENT:  '/*' .*? '*/' -> channel(HIDDEN);
INLINE_COMMENT: '--' ~[\r\n]* ('\r'? '\n' | EOF) -> channel(HIDDEN);

生成解析器和词法分析器类

**使用 **maven 命令 工具生成 词法分析器类语法分析器类抽象语法树(AST)访问类

mvn clean process-sources

image.png

编写 Java 代码

public class OracleSQLParser implements ISQLParser {
    @NonNull
    protected final CommonTokenStream tokenStream;
    @NonNull
    protected final OracleStatementParser parser;
    @NonNull
    protected final SQLParserOption option;
​
    public OracleSQLParser(@NonNull String sql, @NonNull SQLParserOption option) {
        // String `SQL`转 `Stream`
        CharStream input = CharStreams.fromString(sql);
        // 创建词法分析器
        OracleStatementLexer lexer = new OracleStatementLexer(input);
        // 创建 token 流
        tokenStream = new CommonTokenStream(lexer);
        // 创建语法分析器
        parser = new OracleStatementParser(tokenStream);
        this.option = option;
    }
​
    @NonNull
    @Override
    public Parser getParser() {
        return parser;
    }
}

SQLStream

CharStream input = CharStreams.fromString(sql);

创建词法分析器

OracleStatementLexer lexer = new OracleStatementLexer(input);

创建语法分析器

parser = new OracleStatementParser(tokenStream);

语法树访问

为了处理和解析语法树,我们需要实现一个语法树访问者类

定义语法树访问者类

public class OracleASTNodeBuildVisitor extends OracleStatementBaseVisitor<ISQLDataNode> implements ISQLASTNodeBuildVisitor {
    @NonNull
    private final List<ISQLStatement> statements;
    @NonNull
    private final TokenStream tokenStream;
    @NonNull
    private final Set<Token> visitHiddenTokens;
    @NonNull
    private final SQLParserOption option;
​
    public OracleASTNodeBuildVisitor(@NonNull final List<ISQLStatement> statements,
                                     @NonNull final TokenStream tokenStream,
                                     @NonNull final SQLParserOption option) {
        this.statements = statements;
        this.tokenStream = tokenStream;
        this.visitHiddenTokens = new LinkedHashSet<>();
        this.option = option;
    }
​
    @Override
    public void addVisitHiddenToken(@NonNull Token token) {
        visitHiddenTokens.add(token);
    }
​
    @Override
    public Set<Token> getVisitHiddenTokens() {
        return visitHiddenTokens;
    }
​
    @Override
    public ISQLDataNode visitExecute(ExecuteContext ctx) {
        ISQLStatement preStatement = null;
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            // EOF
            if (isEOF(child)) {
                continue;
            }
            ISQLDataNode childSQLNode = child.accept(this);
            if (childSQLNode == null) {
                continue;
            }
​
            if (childSQLNode.isISQLStatement()) {
                ISQLStatement statement = (ISQLStatement) childSQLNode;
​
                beforeAddStatement(statement);
                statements.add(statement);
​
                preStatement = statement;
            } else if (childSQLNode.isSQLTerminalNode()) {
                SQLTerminalNode terminalNode = (SQLTerminalNode) childSQLNode;
                if (preStatement != null) {
                    if (terminalNode.isSemi()) {
                        preStatement.setAfterSemi(terminalNode);
                    } else if (terminalNode.isSlash()) {
                        preStatement.setAfterSlash(terminalNode);
                    }
                }
            }
        }
        return null;
    }
​
    private void beforeAddStatement(@NonNull ISQLStatement statement) {
        // pretty
        statement.setFormatKind(option.getFormatKind());
    }
}

调用语法树访问者类

// 转换 自定义 AST
    @NonNull
    @Override
    public List<ISQLStatement> parseStatements() {
        List<ISQLStatement> statements = new ArrayList<>();
​
        OracleASTNodeBuildVisitor visitor = new OracleASTNodeBuildVisitor(statements, tokenStream, option);
        parser.execute().accept(visitor);
​
        return statements;
    }

总结

通过以上步骤,你可以在 Java 中使用 ANTLR4 构建和使用解析器。ANTLR4 提供了强大的工具和灵活的语法定义方式,使得构建复杂语言处理器变得相对简单。希望这篇文章对你有所帮助

0条评论
0 / 1000
Kent
2文章数
0粉丝数
Kent
2 文章 | 0 粉丝
Kent
2文章数
0粉丝数
Kent
2 文章 | 0 粉丝
原创

Antlr4 Java使用

2024-11-08 09:21:15
0
0

创建 ANTLR4 语法文件

ANTLR4 使用 .g4 文件来定义语法,如下图

image.png

lexer grammar Comments;
​
import Symbol;
​
BLOCK_COMMENT:  '/*' .*? '*/' -> channel(HIDDEN);
INLINE_COMMENT: '--' ~[\r\n]* ('\r'? '\n' | EOF) -> channel(HIDDEN);

生成解析器和词法分析器类

**使用 **maven 命令 工具生成 词法分析器类语法分析器类抽象语法树(AST)访问类

mvn clean process-sources

image.png

编写 Java 代码

public class OracleSQLParser implements ISQLParser {
    @NonNull
    protected final CommonTokenStream tokenStream;
    @NonNull
    protected final OracleStatementParser parser;
    @NonNull
    protected final SQLParserOption option;
​
    public OracleSQLParser(@NonNull String sql, @NonNull SQLParserOption option) {
        // String `SQL`转 `Stream`
        CharStream input = CharStreams.fromString(sql);
        // 创建词法分析器
        OracleStatementLexer lexer = new OracleStatementLexer(input);
        // 创建 token 流
        tokenStream = new CommonTokenStream(lexer);
        // 创建语法分析器
        parser = new OracleStatementParser(tokenStream);
        this.option = option;
    }
​
    @NonNull
    @Override
    public Parser getParser() {
        return parser;
    }
}

SQLStream

CharStream input = CharStreams.fromString(sql);

创建词法分析器

OracleStatementLexer lexer = new OracleStatementLexer(input);

创建语法分析器

parser = new OracleStatementParser(tokenStream);

语法树访问

为了处理和解析语法树,我们需要实现一个语法树访问者类

定义语法树访问者类

public class OracleASTNodeBuildVisitor extends OracleStatementBaseVisitor<ISQLDataNode> implements ISQLASTNodeBuildVisitor {
    @NonNull
    private final List<ISQLStatement> statements;
    @NonNull
    private final TokenStream tokenStream;
    @NonNull
    private final Set<Token> visitHiddenTokens;
    @NonNull
    private final SQLParserOption option;
​
    public OracleASTNodeBuildVisitor(@NonNull final List<ISQLStatement> statements,
                                     @NonNull final TokenStream tokenStream,
                                     @NonNull final SQLParserOption option) {
        this.statements = statements;
        this.tokenStream = tokenStream;
        this.visitHiddenTokens = new LinkedHashSet<>();
        this.option = option;
    }
​
    @Override
    public void addVisitHiddenToken(@NonNull Token token) {
        visitHiddenTokens.add(token);
    }
​
    @Override
    public Set<Token> getVisitHiddenTokens() {
        return visitHiddenTokens;
    }
​
    @Override
    public ISQLDataNode visitExecute(ExecuteContext ctx) {
        ISQLStatement preStatement = null;
        for (int i = 0; i < ctx.getChildCount(); i++) {
            ParseTree child = ctx.getChild(i);
            // EOF
            if (isEOF(child)) {
                continue;
            }
            ISQLDataNode childSQLNode = child.accept(this);
            if (childSQLNode == null) {
                continue;
            }
​
            if (childSQLNode.isISQLStatement()) {
                ISQLStatement statement = (ISQLStatement) childSQLNode;
​
                beforeAddStatement(statement);
                statements.add(statement);
​
                preStatement = statement;
            } else if (childSQLNode.isSQLTerminalNode()) {
                SQLTerminalNode terminalNode = (SQLTerminalNode) childSQLNode;
                if (preStatement != null) {
                    if (terminalNode.isSemi()) {
                        preStatement.setAfterSemi(terminalNode);
                    } else if (terminalNode.isSlash()) {
                        preStatement.setAfterSlash(terminalNode);
                    }
                }
            }
        }
        return null;
    }
​
    private void beforeAddStatement(@NonNull ISQLStatement statement) {
        // pretty
        statement.setFormatKind(option.getFormatKind());
    }
}

调用语法树访问者类

// 转换 自定义 AST
    @NonNull
    @Override
    public List<ISQLStatement> parseStatements() {
        List<ISQLStatement> statements = new ArrayList<>();
​
        OracleASTNodeBuildVisitor visitor = new OracleASTNodeBuildVisitor(statements, tokenStream, option);
        parser.execute().accept(visitor);
​
        return statements;
    }

总结

通过以上步骤,你可以在 Java 中使用 ANTLR4 构建和使用解析器。ANTLR4 提供了强大的工具和灵活的语法定义方式,使得构建复杂语言处理器变得相对简单。希望这篇文章对你有所帮助

文章来自个人专栏
Antlr4
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0