【编译原理】Antlr 入门使用

这篇具有很好参考价值的文章主要介绍了【编译原理】Antlr 入门使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前面文章我们学习了编译器前端的词法和语法分析工具,本篇我们来看看如何借助 Antlr 工具,快速生成词法和语法分析代码。

一、安装

mac 环境:
1)安装

brew install antlr

2)配置 classpath
(把 Antlr 的 JAR 文件设置到 CLASSPATH 环境变量中,以便顺利编译所生成的 Java 源代码。)

vi ~/.bash_profile

# 替换成你的 antlr jar 路径
CLASSPATH=".:/opt/homebrew/Cellar/antlr/4.13.1/antlr-4.13.1-complete.jar:$CLASSPATH"

source ~/.bash_profile

有了这个玩意,你可以用很简单的方式定义好词法和语法文件,他会自动生成对应的解析文件,给你生成出 AST 来。

你可以从生成的类文件中,看看是如何生成 AST 树的。
对于我们之前遇到的左递归问题,它又是如何解决的,也是用循环代替递归么?

生成 AST 树,算完成了词法分析和语法分析。
根据这棵树做什么,就是语义分析了。

二、开发 Java 项目

1、创建一个 maven 项目
2、pom 中添加 Antlr 库

        <dependency>
            <groupId>org.antlr</groupId>
            <artifactId>antlr4-runtime</artifactId>
            <version>4.10</version>
        </dependency>

3、编写一个 antlr 文件 Expr.g4。位置随意,可以放到 src 目录

grammar Expr;

expr: expr op=(ADD|SUB) expr      # AddSub
| INT                             # int
;

ADD: '+';
SUB: '-';

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

4、编译项目 (这样可以生成一些antlr的解析器的类代码,方便后面编程)

mvn compile

你应该能在项目根目录看到一个 gen 文件夹,打开后里面是生成的 java 类
【编译原理】Antlr 入门使用

把这部分代码放到你的 src 包路径下 src/main/java/com/xxx/my_antlr_demo/antlr4
5、编写调用代码
EvalVisitor.java

import com.shuofxz.my_antlr_demo.antlr4.ExprBaseVisitor;
import com.shuofxz.my_antlr_demo.antlr4.ExprLexer;
import com.shuofxz.my_antlr_demo.antlr4.ExprParser;

public class EvalVisitor extends ExprBaseVisitor<Integer> {
    @Override
    public Integer visitAddSub(ExprParser.AddSubContext ctx) {
        Integer left = visit(ctx.expr(0));  // should call "visit", not "visitChildren"
        Integer right = visit(ctx.expr(1));
        if (ctx.op.getType() == ExprLexer.ADD) {
            return left + right;
        } else {
            return left - right;
        }
    }

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

AppDemo.java

import com.shuofxz.my_antlr_demo.antlr4.ExprLexer;
import com.shuofxz.my_antlr_demo.antlr4.ExprParser;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;

public class AppDemo {
    public static void main(String[] args) {
        String input = null;
        // 此处把输入的参数,直接赋值了
        args = new String[2];
        args[0] = "-input";
        args[1] = "1+2+3-4";
        for (int i=0; i<args.length; i++) {
            if (args[i].equals("-input")) {
                input = args[++i];
            }
        }

        if (input == null) {
            System.out.println("args:  -input <expression>");
            return;
        }

        CodePointCharStream charStream = CharStreams.fromString(input);
        ExprLexer lexer = new ExprLexer(charStream);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        ExprParser parser = new ExprParser(tokens);
        ParseTree tree = parser.expr();
        EvalVisitor visitor = new EvalVisitor();

        Object result = visitor.visit(tree);
        System.out.println("output=" + result);
    }
}

6、运行就能看到结果了。

你可能会有疑问:
兜了这么一大圈这有啥用呢?

那我们把 Antrl 文件修改一下 Expr.g4
ADDSUB 两个操作符换成其他的符号。

grammar Expr;

expr: expr op=(ADD|SUB) expr      # AddSub
| INT                             # int
;

ADD: '@';
SUB: '#';

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

记得重新执行第四步生成代码并替换。

然后我们可以把输入字符换为 1@2@3#4
你大概猜到了这里就实现了类似操作符重载的功能。
那么后面我们就可以用这个工具,实现我们自己的语法解析工具了。

三、Antlr 中都做了什么?

antlr 语法文件中写的都是啥?

  • 分为两个部分:词法规则和语法规则
  • 词法规则定义了语言的基本词汇元素,即词法单元(Tokens)。它们通常包括标识符、常量、关键字和符号等。通常以大写字母开头,如 ADD、INT 等
  • 语法规则定义了语言的结构,说明了不同词法单元是如何组合起来形成语言结构的。语法规则描述了语句、表达式、声明等高级结构,如 expr。

接下来我们解释一下关键执行步骤中都做了什么事情:文章来源地址https://www.toymoban.com/news/detail-845855.html

// 将字符串转换为 antlr 能接受的 CodePointCharStream 类型
CodePointCharStream charStream = CharStreams.fromString(input);

// 创建一个词法分析器实例
ExprLexer lexer = new ExprLexer(charStream);
// 创建一个记号流实例
CommonTokenStream tokens = new CommonTokenStream(lexer);
// 创建一个语法分析器实例
ExprParser parser = new ExprParser(tokens);

// 这是实际开始进行词法和语法分析的步骤,生成 AST
ParseTree tree = parser.expr();

// 遍历 AST。按照自己定义的 visitXxx() 方法执行实际的逻辑。
EvalVisitor visitor = new EvalVisitor();
Object result = visitor.visit(tree);
  • 词法分析器:词法分析的任务是将输入文本分割成一系列的记号(tokens),每个记号是语言中最小的有意义单元,如关键字、标识符、字面量等。
  • 记号流:用于从词法分析器中获取记号,并将它们组织成一个流,以便之后进行语法分析。
  • 语法分析器:对记号流tokens进行语法分析。

到了这里,关于【编译原理】Antlr 入门使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • PaddleX入门教程3:开始使用我们自己的模型进行推理

    首先我们要从网上下载几张图片,一张菠菜的、一张胡萝卜的、一张茄子的、一张西红柿的,建议找一些相对辨识度比较高的。因为我们现在的模型,可能没有那么强大。 如下:保存为jpg格式, 注意文件名的命名 。 然后,将 这些图片放置到前面我们的模型目录下。  此时

    2024年02月07日
    浏览(60)
  • 一篇文章让你彻底了解vuex的使用及原理(上)

    文章讲解的 Vuex 的版本为 4.1.0 ,会根据一些 api 来深入源码讲解,帮助大家更快掌握 vuex 的使用。 使用 Vue 实例的 use 方法把 Vuex 实例注入到 Vue 实例中。 use 方法执行的是插件的中的 install 方法 src/store.js 从上面可以看到 Vue 实例通过 provide 方法把 store 实例 provide 到了根实例

    2023年04月23日
    浏览(61)
  • Makefile编译原理 变量的使用

    -makefile中支持程序设计语言中变量的概念 -makefile中的变量只代表文本数据(字符串) -makefile中的变量名规则    - 变量名可以包含字符,数字,下划线。    - 不能包含 \\\":\\\"  \\\"#\\\"  \\\"=\\\"  \\\" \\\"    - 变量名大小写敏感 -简单赋值(:=) -递归赋值(=) -条件赋值(?=) -追加赋值(

    2024年02月01日
    浏览(43)
  • Antlr4学习笔记

    目录 背景 相关概念 流程说明 入门示例 简易计算器 环境准备 开发 java8方法提取 语法规则 常用的语法要点 设计语法 序列模式 选择模式 词法符号依赖 嵌套模式 总结 参考资料 在阅读shardingjdbc-4.1.1代码时,发现一段sql解析的逻辑,好奇它的实现,查阅相关资料发现解析引擎

    2024年02月06日
    浏览(31)
  • 什么叫面试八股文,一篇文章带你入门音视频(1),使用指南

    版税方式:按个收取 备注:WMA的全称是Windows Media Audio,它是微软公司推出的与MP3格式齐名的一种新的音频格式。由于WMA在压缩比和音质方面都超过了MP3,更是远胜于RA(Real Audio),即使在较低的采样频率下也能产生较好的音质,再加上WMA有微软的Windows Media Player做其强大的后盾

    2024年04月25日
    浏览(64)
  • 安卓反编译入门06-AndroidKiller的使用(1)

    1.主页窗口 直接点击打开,选择一个apk文件即可 经过解析后可查看工程信息 (1).工程信息窗口 能看到app的名称、包名、入口Activity、版本号、以及四大组件信息和权限相关。 (2).工程管理器窗口 包含 assets、res、smali、manifest 等信息 (3).工程搜索窗口 包含搜索字符、替换字符、

    2024年02月08日
    浏览(39)
  • ubuntu系统下如何使用vscode编译和调试#小白入门#

    编程环境:ubuntu系统为18.04.1,vscode版本为1.66.2 1、vscode安装完成后启动,在左侧externsions中搜索“简体中文”插件,并完成安装: 2、选择右下角齿轮形状的\\\"Manage\\\",选择第一项“command palette…“, 3、在右侧最上面输入栏选择\\\"configure display language”, 4、选择下拉中的第二项“zh

    2024年04月27日
    浏览(33)
  • Linux shell脚本set -e原理(set -o errexit 命令出错退出)(|| true屏蔽前面子命令返回值)(用if判断即使命令返回值不为零也不会退出)

    set -e 是 Linux shell 中的一个选项,它的作用是在脚本执行过程中,一旦出现任何命令执行失败(返回非零的退出状态码),脚本就会立即退出。 具体原理如下: 当设置了 set -e 选项后,shell 会在每个命令执行后检查其退出状态码。 如果命令的退出状态码为非零,表示命令执行

    2024年02月22日
    浏览(49)
  • 【LabVIEW FPGA入门】使用LabVIEW FPGA进行编程并进行编译

            在本文中会进行一个简单的FPGA编程演示,这通常可以验证编译工具链是否正常使用。在LabVIEW FPGA中和rt、PC编程一样使用数据流编程,但是需要注意的是FPGA中有些函数是不可以用的,因为这些函数很占用资源,且FPGA只能同时下载运行一个程序。         1.在FPGA终端

    2024年01月17日
    浏览(38)
  • Android ffmpeg入门(1)—— 使用NDK交叉编译ffmpeg集成到Android项目

    最近在学习android NDK开发相关内容,借ffmpeg练练手。ffmpeg是做音视频方面功能的基础,后面会随着个人的学习更新一系列ffmpeg博客,防止自己遗忘。 这个系列博客主要目的是基于ffmpeg通过NDK开发的方式完成一个基本的视频播放器。 本篇博客主要实现了 ffmpeg编译 以及 引入 a

    2023年04月08日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包