Antlr4

月伴飞鱼 2024-11-10 12:13:05
框架相关
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!

Antlr 是一个强大的跨语言语法解析器。

  • 可以用来读取、处理、执行或翻译结构化文本或二进制文件。

Antlr可以从语法上来生成一个可以构建和遍历解析树的解析器。

我们无法仅从一个个单个的字符,去理解一句话完整的意思的。

  • 因为单个的字符并没有意义,一句话之所以有含义,是因为组成它的每一个单词具有意义。

ANTLR 的语法分析过程与我们解读某句话意义的过程是相同的。

ANTLR 官方网址:http://www.antlr.org/

ANTLR 官方 Github:https://github.com/antlr/antlr4

大量语法文件例子:https://github.com/antlr/grammars-v4

基本概念

抽象语法树 (AST) :

  • 抽象语法树是源代码结构的一种抽象表示,它以树的形状表示语言的语法结构。

语法解析器 (Parser) 语法解析器:

  • 进行语法检查,并构建由输入单词(Token)组成的数据结构(即抽象语法树)。

词法分析器 (Lexer) 词法分析:

  • 是指在计算机科学中,将 字符序列 转换为单词(Token)的过程。

  • 执行 词法分析 的程序便称为词法分析器。

  • 词法分析器(Lexer)一般是用来供 语法解析器(Parser) 调用的。

ANTLR语法分析过程

首先进行词法分析,它是将字符聚集为单词或者符号的过程。

通过词法分析,ANTLR 根据事先定义的词法规则,将用户的输入字符解析为词法符号。

  • 并根据各个词法符号出现的位置,匹配语法规则,生成一颗语法分析树。

通过遍历 ANTLR 生成的语法分析树,就能够根据我们自己的需求,实现自定义的语法功能。

安装插件

IDEA作为开发工具,在Preference->Plugins中搜索Antlr然后安装即可。

定义语法和词法

需要创建一个.g4文件,用于定义词法分析器(Lexer)和语法解析器(Parser)。

下面是一个简单的例子:Hello.g4

// file Hello.g4
// Define a grammar called Hello
grammar Hello; // 1. grammer name
@header { package pers.me.expression.parser; } // 2. java package
r  : 'hello' ID ;         // 3. match keyword hello followed by an identifier
ID : [a-z]+ ;             // match lower-case identifiers
WS : [ \t\r\n]+ -> skip ; // 4. skip spaces, tabs, newlines

定义了 grammar 的名字,名字需要与文件名对应。

定义生成的Java类的package

r 定义的语法,会使用到下方定义的正则表达式词法。

定义了空白字符,后面的 skip 是一个特殊的标记,标记空白字符会被忽略。

生成代码

IDEA中右键点击.g4文件,选择Generate ANTLR Recognizer,插件会自动在gen目录下生成一堆Java代码。

  • 我们需要移动到对应的package中。

如果定义了@headerIDEA也会自动生成package信息。

63b615da99c4e50b649cd54470523bff

测试

利用下面这段代码来测试一下ParseTree

public class HelloTest {
    public static void main(String[] args) throws Exception {
        HelloLexer lexer = new HelloLexer(CharStreams.fromString("hello parrt"));
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        HelloParser parser = new HelloParser(tokens);
        ParseTree tree = parser.r();
        System.out.println(tree.toStringTree(parser));
    }
}

运行上面的代码可以得到如下输出,程序识别出输入的字符串符合r的语法。

(r hello parrt)

Listener和Visitor

ANTLR 提供了两种方法来访问ParseTree

  • 一种是通过Parse-Tree Listener的方法。
  • 另一种是通过Parse-Tree Visitor的方法。

Listener有以下特点:

访问AST的所有节点。

重写(Override)进入时(enterXXX方法)和退出时(exitXXX方法)要执行的方法。

要重写的方法没有返回值,因此需要在属性中保留所需的值。

Visitor有以下特点:

并非所有 AST 节点都被访问。

根据目的重写进入节点时要执行的过程(visitXXX方法)。

重写方法有一个返回值,因此不必在属性中保存所需的值。

最大的区别是Listener会自动访问 AST 的所有节点,而Visitor如果要访问当前节点的子树,则需要手工实现。

Visitor 较为简单方便,继承 HelloBaseVisitor 类即可,内部的方法与 g4 文件定义相对应,对照看即可理解。

实现了 visitor 之后,就可以完成一个简单的自定义解析器了。

支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!