ANTLR 实战_从零开始构建自定义语言解析器

news2025/4/12 12:07:07

1. 引言

1.1 什么是 ANTLR

ANTLR(Another Tool for Language Recognition)是一个强大的解析器生成器,用于构建语言解析器、编译器和解释器。

1.2 ANTLR 的历史与发展

ANTLR 由 Terence Parr 创建,最初发布于 1995 年。经过多次版本更新,ANTLR 已成为构建解析器的首选工具之一。

1.3 ANTLR 的应用场景

  • 编译器开发:构建自定义编程语言的编译器。
  • DSL(领域特定语言):解析和处理特定领域的语言。
  • 配置文件解析:解析各种配置文件格式。
  • 脚本解释器:构建脚本解释器。

2. 安装与配置

2.1 安装 ANTLR 工具

下载并安装 ANTLR 工具。

# 下载 ANTLR JAR 文件
curl -O https://www.antlr.org/download/antlr-4.9.3-complete.jar

# 将 JAR 文件添加到 PATH
export CLASSPATH=".:/path/to/antlr-4.9.3-complete.jar:$CLASSPATH"
alias antlr4='java -jar /path/to/antlr-4.9.3-complete.jar'
alias grun='java org.antlr.v4.gui.TestRig'

2.2 配置开发环境

使用 IDE(如 IntelliJ IDEA 或 Eclipse)配置 ANTLR 插件。

2.3 创建第一个 ANTLR 项目

创建一个新的 ANTLR 项目并编写简单的文法。

mkdir antlr-example
cd antlr-example
touch Calculator.g4

3. 基本概念

3.1 词法分析器(Lexer)

词法分析器负责将输入字符串分解为一系列词法单元(tokens)。

3.2 语法分析器(Parser)

语法分析器负责根据词法单元生成抽象语法树(AST)。

3.3 抽象语法树(AST)

抽象语法树是一种树状结构,表示输入字符串的语法结构。

4. 编写 ANTLR 文法

4.1 词法规则

定义词法规则,将输入字符串分解为词法单元。

// Calculator.g4
grammar Calculator;

expr:   expr ('*' | '/') expr   # MulDiv
    |   expr ('+' | '-') expr   # AddSub
    |   INT                     # Int
    |   '(' expr ')'            # Parens
    ;

INT :   [0-9]+ ;
WS  :   [ \t\r\n]+ -> skip ;

4.2 语法规则

定义语法规则,生成抽象语法树。

// Calculator.g4
grammar Calculator;

expr:   expr ('*' | '/') expr   # MulDiv
    |   expr ('+' | '-') expr   # AddSub
    |   INT                     # Int
    |   '(' expr ')'            # Parens
    ;

INT :   [0-9]+ ;
WS  :   [ \t\r\n]+ -> skip ;

4.3 示例:简单的计算器语言

编写一个简单的计算器语言文法。

// Calculator.g4
grammar Calculator;

expr:   expr ('*' | '/') expr   # MulDiv
    |   expr ('+' | '-') expr   # AddSub
    |   INT                     # Int
    |   '(' expr ')'            # Parens
    ;

INT :   [0-9]+ ;
WS  :   [ \t\r\n]+ -> skip ;

5. 生成解析器代码

5.1 使用 ANTLR 工具生成代码

使用 ANTLR 工具生成解析器代码。

antlr4 Calculator.g4

5.2 生成的代码结构

生成的代码包括词法分析器和语法分析器类。

CalculatorLexer.java
CalculatorParser.java
CalculatorBaseListener.java
CalculatorListener.java
CalculatorBaseVisitor.java
CalculatorVisitor.java

5.3 示例:生成计算器解析器代码

生成计算器解析器代码并查看生成的类。

antlr4 Calculator.g4

6. 实现解析器

6.1 加载和解析输入

加载输入字符串并使用解析器生成抽象语法树。

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class CalculatorTest {
   
    public static void main(String[] args) throws Exception {
   
        String input = "3 + 5 * (10 - 4)";
        CalculatorLexer lexer = new CalculatorLexer(CharStreams.fromString(input));
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        CalculatorParser parser = new CalculatorParser(tokens);
        ParseTree tree = parser.expr();
        System.out.println(tree.toStringTree(parser));
    }
}

6.2 遍历抽象语法树

遍历抽象语法树并执行计算。

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class CalculatorVisitor extends CalculatorBaseVisitor<Integer> {
   
    @Override
    public Integer visitMulDiv(CalculatorParser.MulDivContext ctx) {
   
        int left = visit(ctx.expr(0));
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == CalculatorParser.MUL) {
   
            return left * right;
        } else {
   
            return left / right;
        }
    }

    @Override
    public Integer visitAddSub(CalculatorParser.AddSubContext ctx) {
   
        int left = visit(ctx.expr(0));
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == CalculatorParser.ADD) {
   
            return left + right;
        } else {
   
            return left - right;
        }
    }

    @Override
    public Integer visitInt(CalculatorParser.IntContext ctx) {
   
        return Integer.parseInt(ctx.INT().getText());
    }

    @Override
    public Integer visitParens(CalculatorParser.ParensContext ctx) {
   
        return visit(ctx.expr());
    }
}

6.3 示例:实现计算器解析器

实现计算器解析器并执行计算。

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class CalculatorTest {
   
    public static void main(String[] args) throws Exception {
   
        String input = "3 + 5 * (10 - 4)"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2329987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CTF类题目复现总结-hashcat 1

一、题目地址 https://buuoj.cn/challenges#hashcat二、复现步骤 1、下载附件&#xff0c;解压得到What kind of document is this_文件&#xff1b; 2、用010 Editor打开What kind of document is this_文件&#xff0c;发现是office文件&#xff1b; 3、将后缀名改为ppt时…

4月5日作业

需求&#xff1a; 1.按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2.要求SW 1为VLAN 2/3的主根及主网关 SW2为VLAN 20/30的主根及主网关&#xff0c;SW1和 SW2互为备份 3.可以使用super vlan 4.上层通过静态路由协议完成数据通信过程 5.AR1为企业出口路由器…

Bert论文解析

文章目录 BERT&#xff1a;用于语言理解的深度双向转换器的预训练一、摘要三、BERT介绍BERT及其详细实现答疑&#xff1a;为什么没有标注的数据可以用来预训练模型&#xff1f;1. 掩码语言模型&#xff08;Masked Language Model, MLM&#xff09;2. 下一句预测&#xff08;Nex…

无招回归阿里

这两天&#xff0c;无招回归阿里的新闻被刷屏了。无招创业成立的两氢一氧公司无招的股份也被阿里收购&#xff0c;无招以这种姿态回归阿里&#xff0c;并且出任钉钉的 CEO。有人说&#xff0c;这是对 5 年前“云钉一体”战略的纠偏。现在确实从云优先到 AI 优先&#xff0c;但云…

初探:简道云平台架构及原理

一、系统架构概述 简道云作为一款低代码开发平台&#xff0c;其架构设计以模块化和云端协同为核心&#xff0c;主要分为以下层次&#xff1a; 1. 前端层 可视化界面&#xff1a;基于Web的拖拽式表单设计器&#xff0c;支持动态渲染&#xff08;React/Vue框架&#xff09;。多…

Redis(笔记)

简介&#xff1a; 常用数据类型: 常用操作命令&#xff1a; Redis的Java客户端&#xff1a; 操作字符串类型的数据&#xff1a; 操作Hash类型的数据&#xff1a; 操作列表类型的数据&#xff1a; 操作集合类型的数据&#xff1a; 操作有序集合类型数据&#xff1a; 通用命令…

bootloader+APP中,有些APP引脚无法正常使用?

问&#xff1a;bootloaderAPP程序中&#xff0c;为什么有些APP引脚无法正常使用&#xff1f;无法设置高低电平 主控芯片GD32F415&#xff0c;参考案例bootloader中的引脚使用&#xff1a; 参考案例APP程序的引脚使用&#xff1a; 以及个人使用的无线模组&#xff0c;高电平使能…

高并发内存池:原理、设计与多线程性能优化实践

高并发内存池是一种专门为多线程环境设计的内存管理机制&#xff0c;其核心目标是通过优化内存分配和释放过程&#xff0c;解决传统内存分配器&#xff08;如malloc/free&#xff09;在高并发场景下的性能瓶颈&#xff0c;显著提升多线程程序的内存访问效率。 目录 一、核心设计…

基于内容的课程推荐网站的设计与实现00(SSM+htmlL)

基于内容的课程推荐网站的设计与实现(SSMhtml) 该系统是一个基于内容的课程推荐网站&#xff0c;旨在为用户提供个性化的课程推荐。系统包含多个模块&#xff0c;如教学视频、教学案例、课程信息、系统公告、个人中心和后台管理。用户可以通过首页访问不同的课程分类&#xff…

生活电子常识--删除谷歌浏览器搜索记录

前言 谷歌浏览器会记录浏览器历史搜索,如果不希望看到越来越多的搜索记录,可以如下设置 解决 设置-隐私-自动填充表单 这个和浏览器记录的密码没有关系,可以放心删除

学习threejs,使用Texture纹理贴图,测试repeat重复纹理贴图

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️Texture 纹理贴图1.1.1 ☘️…

蓝桥杯基础算法-字符串与集合

对集合的考察集中在集合的特性和功能。 set-唯一性 list-有序性 集合元素的个数 思路分析&#xff1a;set的唯一性&#xff0c;取出重复的子串 eg&#xff1a; 下标0截取的范围&#xff1a;【0&#xff0c;最大下标】 下标1截取的范围&#xff1a;【1&#xff0c;最大下标…

animals_classification动物分类

数据获取 深度学习训练中第一个是获取数据集&#xff0c;数据集的质量很重要&#xff0c;我们这里做的是动物分类&#xff0c;大致会选择几个动物&#xff0c;来做一个简单的多分类问题&#xff0c;数据获取的方法&#xff0c;鼠鼠我这里选择使用爬虫的方式来对数据进行爬取&a…

解决Oracle PL/SQL中“表或视图不存在“错误的完整指南

解决Oracle PL/SQL中"表或视图不存在"错误的完整指南 前言问题概述根本原因分析一、 编译时与运行时验证差异二、权限问题三、 Schema命名问题 实际案例演示案例1&#xff1a;动态分表查询案例2&#xff1a;权限不足的场景 实用排查步骤排查流程图最佳实践建议解决方…

SSH远程连接服务器(cursor)

安装Remote-SSH插件 Cursor是基于VSCode的&#xff0c;因此支持VSCode的Remote-SSH功能。打开Cursor&#xff0c;进入扩展市场&#xff08;左侧活动栏的“Extensions”图标&#xff09;。搜索“Remote - SSH”插件并安装&#xff08;由Microsoft提供&#xff09;。 配置SSH 在…

idea gitlab 操作

1.拉取脚本 账号登录 就可以获取git代码 2. 版本回退 hard暴力回退到暂存区 缓存区消失 3.版本合并 切换到目标分区 选择点击开发分区 进行合并

【MATLAB第113期】基于MATLAB的EFAST扩展傅里叶幅度敏感性分析方法(有目标函数)

【MATLAB第113期】基于MATLAB的EFAST扩展傅里叶幅度敏感性分析方法&#xff08;有目标函数&#xff09; 一、方法概述 扩展傅里叶幅度敏感性检验&#xff08;EFAST&#xff09;是一种基于频域分析的全局敏感性分析方法&#xff0c;能够同时评估模型参数的一阶敏感性&#xff…

Unity3D开发AI桌面精灵/宠物系列 【三】 语音识别 ASR 技术、语音转文本多平台 - 支持科大讯飞、百度等 C# 开发

Unity3D 交互式AI桌面宠物开发系列【三】ASR 语音识别 该系列主要介绍怎么制作AI桌面宠物的流程&#xff0c;我会从项目开始创建初期到最终可以和AI宠物进行交互为止&#xff0c;项目已经开发完成&#xff0c;我会仔细梳理一下流程&#xff0c;分步讲解。 这篇文章主要讲有关于…

Qt -信号与槽

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【暂无】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 目录 前言引入connect调用链模板类型的connectQObject::connectImplQObjectPrivate::connectImpl qobject_p_p.hconnect作用总结ai对信号与槽的模拟实现 前言 面向对象&am…

Django中使用不同种类缓存的完整案例

Django中使用不同种类缓存的完整案例 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 Django中使用不同种类缓存的完整案例步骤1:设置Django项目步骤2:设置URL路由步骤3:视图级别…