Antlr4学习2-Java开发

Antlr4学习2-Java开发

0x00 系列文章目录

  1. Antlr4学习1-基本概念和入门示例
  2. Antlr4学习2-Java开发

0x01 摘要

本文主要讲下使用Java来围绕Antlr开发和应用。

0x02 简单例子

2.1 Maven依赖

在pom.xml里加入以下依赖:

 <dependency>
            <groupId>org.antlr</groupId>
            <artifactId>antlr4</artifactId>
            <version>4.7.1</version>
</dependency>

2.2 解析文件

新建一个解析文件SelectExample1.g4

grammar SelectExample1;
sql : 'select' WHAT 'from' tables ';';
WHAT : [a-z]+ ;
tables : WHAT;
WS : [ \t\r\n]+ -> skip ;

这是一个很简单的例子,匹配一条最简单的sql。

2.3 自动生成解析相关java类

在类上点右键,然后如下图所示操作:
Antlr4学习2-Java开发
可以找到生成的一批java类如下图:
Antlr4学习2-Java开发
我们按需把这些文件拷贝到目录下。

2.4 编写解析测试类

创建一个SelectDemo.java文件如下内容:

package demos.antlr.select.demo1;

import demos.antlr.select.demo1.gen.SelectExample1Lexer;
import demos.antlr.select.demo1.gen.SelectExample1Parser;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;

/**
 * Created by chengc on 2018/9/30.
 */
public class SelectDemo
{
    public static void main(String[] args)
    {
        // first, form input charstream from string 
        CharStream input = CharStreams.fromString("select name from studetnt;");

        // 1. Lexer-Lexical analysis
        // Create a lexer that feeds off of input CharStream.
        SelectExample1Lexer lexer = new SelectExample1Lexer(input);

        // 2. Create a buffer of tokens pulled from the lexer.
        CommonTokenStream tokens = new CommonTokenStream(lexer);

        // 3. Parser-Syntax analysis
        // Create a parser that feeds off the tokens buffer.
        SelectExample1Parser parser = new SelectExample1Parser(tokens);

        // 4. Begin parsing at "select" rule.
        ParseTree tree = parser.sql();
        System.out.println(tree.toStringTree(parser));
    }
}

运行该main方法,输出的解析语法树结果如下:

(sql select name from (tables studetnt) ;)

0x03 语法树遍历模式

在idea里面通过.g4文件生成java代码的时候,可配两种方式:
Antlr4学习2-Java开发
默认是listener模式。

3.1 Listener模式 (观察者模式,通过结点监听,触发处理方法)

在遍历语法树时,自动回调Listener中回调方法。
实现简单,全自动,只需要实现listener中的各个接口方法。即可完成语义表达。并采用深度优先遍历。

优点:

  • 程序员不需要显示定义遍历语法树的顺序,实现简单

缺点:

  • 不能控制遍历语法树的顺序
  • 动作代码与文法产生式解耦,利于文法产生式的重用
  • 没有返回值,需要使用map、栈等结构在节点间传值

3.2 Vistor模式 (访问者模式,主动遍历)

则提供了可以控制遍历过程的一种方式,通过显示调用visit方法,可以访问子树节点。

特点如下:

  • 程序员可以显示定义遍历语法树的顺序
  • 不需要与antlr遍历类ParseTreeWalker一起使用,直接对tree操作
  • 动作代码与文法产生式解耦,利于文法产生式的重用
  • visitor方法可以直接返回值,返回值的类型必须一致,不需要使用map这种节点间传值方式,效率高

0xFE 总结

这是一个总结

0xFF 参考文档

Antlr4 入门