ANTLR 4 入门

 项目流程:
(1)定义 .g4 语法文件;
(2)使用 ANTLR 4 工具,生成词法分析器(Lexer)和语法分析器(Parser)目标编程语言代码
(3)遍历 AST(抽象语法树):访问者模式(Visitor)和监听器模式(Listener)

文章目录:
一、安装 Antlr 4
二、基本流程 CMD
        1、编写文法
        2、生成分析器
        3、编译分析器,测试文法
三、IDEA Java 项目
        1、安装插件>新建项目>添加依赖
        2、编写文法,生成分析器
        3、集成到 Java 程序 
        4、可视化查看,语法解析树
        5、遍历并操作语法分析树
四、IDEA TS 项目
        1、初始化>添加依赖>新建项目
        2、编写文法,生成分析器
        3、集成到 TS 程序
        4、可视化查看 (同 Java 项目)
        5、遍历并操作语法分析树

参考:
ANTLR4安装(WIndows版,适合小白or新手)_antlr安装-CSDN博客
ANTLR学习(二):ANTLR入门项目-CSDN博客
入门 · ANTLR 4简明教程 (gitbooks.io)


一、安装 Antlr 4

(1)官网下载 ANTLR 4,放到某个文件夹中,最终效果如下图
(2)新建两个 txt 文件,输入内容后改后缀为 bat 文件类型,最终效果如下图
(3)配置环境变量,最终效果如下图
(4)检验安装

​  
 
 

二、基本流程 CMD

1、编写文法

新建文件夹,编写一段用于识别 hello world 短语的文法,其文件类型保存为 Hello.g4
        grammar Hello;          // 声明名为 Hello 的语法
        r   : 'hello' ID ;
        ID : [a-z]+ ;                  // 小写开头称为词法规则,大写开头称为语法规则
        WS : [ \t\r\n]+ -> skip;
注:第二句:定义名为 r 的情况:先出现 "hello" ,后面紧跟着一个小写字母组成的字符串
       第三句:定义名为ID的情况:至少由一个小写字母组成的字符串,都能被叫做 ID
       第四句:定义名为ws的情况:出现空格、制表符、回车和换行时,直接跳过解析,不管它

2、生成分析器

利用 ANTLR 工具,生成词法分析器(Lexer)和语法分析器(Parser)目标编程语言的代码
指定目标语言,是为了确保 ANTLR 生成的分析器的代码,适配我们的项目的代码。
由于 ANTLR 是 Java 写的,若不指定目标语言时,它会默认生成 Java 的分析器代码。

指定语言的方式有两种:
     法一:在 .g4 文件的头部添加指定的目标语言
     法二:在使用 ANTLR 工具的命令行参数中,指定目标语言
                若指定为 Java:antlr4 -Dlanguage=Java Hello.g4
                =Python、=C、=Cpp、=CSharp、=Go、=JavaScript、=TypeScript、=PHP ......

该命令会在相同目录下,生成后缀名为 tokens、interp 和 java 的 8 个源代码文件。

3、编译分析器,测试文法

编译由 ANTLR 生成的识别器的 Java 源文件,进而生成对应的类文件:javac Hello*.java
此时,就差一个主程序去加载这个类文件,就能启动语言识别器的程序了

ANTLR 运行库提供了 TestRig 的测试工具,可以不创建主程序,就能测试文法。
使用 TestRig 工具,打印识别期间创建的记号,像关键字 hello 和标识符 world 的词汇符号。

法一:以列表的方式,查看记号,每一行输出表示一个记号以及它的相关信息
                grun Hello r  -tokens                // Hello 是文法的名字,r 是开始的规则名字
                hello world                                // 输入并按回车
                EOF                                          // Windows 系统输入 Ctrl+Z 并按回车
         >>   [@0,0:4='hello',<1>,1:0]   ....    [@2,13:12='<EOF>',<-1>,2:0]
         含义:  @0 :记号索引(从 0 开始计数)
                      0:4 :记号开始与结束的位置(从 0 开始)
                      <1>:记号类型,具体数值和类型,存储在后缀名为 tokens 的文件中
                      10:记号在第1行(从1开始)从第6个字符开始(从0开始,制表符按字符计算

法二:以 LISP 风格的文本形式,查看记号:
                grun Hello r  -tree
         >>   (r hello world)
        含义:识别到一个词法规则 r ,匹配到的文本是 hello world

法三:以可视化的方式,查看语法分析树:
                grun Hello r  -gui ,返回一张图片

注:再次强调一下,r 是本篇文法中,最开始的规则的名字,不是所有文法的最开始规则都叫 r 

三、IDEA Java 项目

1、安装插件>新建项目>添加依赖

(1)安装 ANTLR v4 插件,最终效果如下图
(2)新建 Maven 项目,最终效果如下图
(3)添加 ANTLR 依赖。在 pom.xml 文件中的 </properties> 后,加上如下代码
         添加完后,记得要下载依赖(点击右侧的 m 图标,即可启动加载 or 重新加载)
  

<dependencies>
    <dependency>
        <groupId>org.antlr</groupId>
        <artifactId>antlr4-runtime</artifactId>
        <version>4.13.1</version>         
    </dependency>                        // 版本号与下面的要一致
</dependencies>


<build>
    <plugins>
        <plugin>
            <groupId>org.antlr</groupId>
            <artifactId>antlr4-maven-plugin</artifactId>
            <version>4.13.1</version>        
            <executions>                 // 版本号与上面的要一致
                <execution>
                    <id>antlr</id>
                    <goals>
                        <goal>antlr4</goal>
                    </goals>
                    <phase>none</phase>
                </execution>
            </executions>
            <configuration>
                    <outputDirectory>src/test/java</outputDirectory>
                    <listener>true</listener>
                    <treatWarningsAsErrors>true</treatWarningsAsErrors>
            </configuration>
        </plugin>
    </plugins>
</build>

2、编写文法,生成分析器

(1)编写文法,保存为 .g4 文件类型
(2)g4 文件右键,配置 ANTLR 工具(这一步了解即可)
(3)g4 文件右键,生成解析器代码(生成前会自动检查语法,若有问题会直接报错)

​ 
(1)Lexer 词法分析器:它根据定义的词法规则,将输入的文本,分割成一个个的词法单元。
(2)Parser 语法分析器:它基于词法单元 (tokens),按照定义的语法规则来构建语法分析树。
(3)令牌流:由一系列的令牌 [词法单元] (token),按照特定的顺序,组成的序列。

---------------------------------------- 遍历语法分析树,操作节点元素 --------------------------------------

(3)xxxBaseVisitor.java,xxxVisitor.java(访问者模式):后者是一个基类,它给每种可能的语法结构(比如句子、单词、数字等等)都准备了一个处理的方法。但是这些方法是一开始都是空的方法。我们可以继承这个基类,来创建自己的 Visitor 类,并重写某些行为的具体方法。

(4)xxxBaseListener.java,xxxListener.java(监听者模式):构建语法分析树之后,在遍历该树时,遍历器能够触发一些列回调,并通知监听器对象,第一个文件接口给出了这些回调方法的定义,第二个文件包含该接口的默认实现类

3、集成到 Java 程序 

package demo2;

import demo2.antlr.modelicaLexer;        // 导入自定义的词法分析器 
import demo2.antlr.modelicaParser;       // 导入自定义的语法分析器

import org.antlr.v4.runtime.*;           // 导入 ANTLR 运行时的相关类
import org.antlr.v4.runtime.tree.*;      // 导入与解析树相关的类

public class Main {   // 定义主类
    public static void run(String str) throws Exception {      //静态的解析函数
        ANTLRInputStream input = new ANTLRInputStream(str);    //输入的字符串转换为输入流
        ArrayInitLexer lexer = new ArrayInitLexer(input);        //用输入流创建词法分析器
        CommonTokenStream tokens = new CommonTokenStream(lexer); //用词法分析器创建令牌流
        ArrayInitParser parser = new ArrayInitParser(tokens);    //用令牌流创建语法分析器
        ParseTree tree = parser.init();           // 调用 Parser 的 `init` 方法获取解析树
        ......
    }
    public static void main(String[] args) throws Exception { ... run(xxx);... }}

4、可视化查看,语法解析树

5、遍历并操作语法分析树

使用 ANTLR 内置的语法分析树遍历器

进行深度优先遍历,然后在它触发的一系列回调函数中,进行适当的操作。

四、IDEA TS 项目

1、初始化>添加依赖>新建项目

(1)初始化:npm init -y
      将在当前目录自动创建 package.json 文件,包含项目基本信息,管理项目的依赖和配置。

(2)安装 TS 编译器:npm install --save-dev typescript
         
配置 TS 编译器:npx tsc --init
    注:若下载失败,输入" npm config set proxy null "重置,然后再进行安装。

(3)安装 ANTLR 4:npm install --save antlr4
      
   安装 ANTLR 4 的包,并自动将其作为依赖项添加到 package.json 的 dependencies 中            注:若下载失败,输入" npm config set proxy null "重置,然后再进行安装。
    注:若仍然失败,请关闭防火墙,再试一试

(4)新建主代码目录、新建 g4 文件、新建 ts 程序、新建用于存放分析器的目录(如下图)

2、编写文法,生成分析器

(1)g4 文件右键,配置 ANTLR 工具
(2)g4 文件右键,生成分析器代码(生成前会自动检查语法,若有问题会直接报错)
 

3、集成到 TS 程序

import { BufferedTokenStream, CharStream, CommonTokenStream } from "antlr4";
import ALangLexer from "./antlr/ALangLexer";
import ALangParser from "./antlr/ALangParser";     //导入自定义语法分析器

function run(str: string): void {
    const input = new CharStream(str);             // 将输入的字符串,转换为 ANTLR 输入流
    const lexer = new ALangLexer(input);           // 使用输入流,创建词法分析器
    const tokens: BufferedTokenStream = new CommonTokenStream(lexer);//用Lexer创建令牌流
    const parser = new ALangParser(tokens);        // 使用令牌流,创建语法分析器
    const tree = parser.prog();                    // 调用语法分析器的`prog`方法获取解析树
    console.log(tree.toStringTree(null,parser));   // 打印解析树的字符串表示
}

function main(): void {... run(s); ...}

main();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值