文章目录

  • 什么是ANTLR4
  • ANTLR4的特点
  • ANTLR4的语法规则
    • 语法规则的声明
    • .g4文件的代码规则
      • 词法规则
      • 语法规则
      • 语法规则中的操作
  • 如何使用ANTLR4
  • 实战
    • IDEA安装ANTLR插件
    • 新建项目
    • 创建一个.g4文件
    • 通过插件生成java代码
    • 创建一个EvalVisitor遍历AST
    • 测试

什么是ANTLR4

ANTLR4(全称为"ANother Tool for Language Recognition")是一种用于构建语言识别器的强大工具。它是一个自动生成的解析器生成器,使用ANTLR4可以帮助开发人员快速创建自定义的语言或DSL。

ANTLR4的特点

  • 支持多种目标语言,包括Java、C#、Python、JavaScript等。
  • 支持LL(*)(LL star)语法分析器,可以处理包含任意数目的向前看标记(lookahead)的语法。
  • 支持词法和语法错误处理,可以生成清晰的错误消息和恢复策略。
  • 支持生成AST(抽象语法树),方便语言处理器进行语法分析和代码生成。
  • 提供了丰富的API和工具集,可以自定义和优化ANTLR4生成的解析器。

ANTLR4的语法规则

语法规则的声明

ANTLR4的语法规则必须以“grammar”关键字开始,后面跟着语法规则的名称。例如:

grammar MyGrammar;

这里声明了一个名为"MyGrammar"的语法规则。

.g4文件的代码规则

词法规则

ANTLR4语法规则以词法规则(lexer rules)开始。词法规则定义了输入文本中的各个单词(或标记),这些单词将被语法规则使用。每个词法规则定义一个单词的名称和匹配该单词的正则表达式。

以下是一个简单的例子:

// 定义变量名为一个字母后跟零个或多个字母、数字或下划线
ID : [a-zA-Z] [a-zA-Z0-9_]*;

在这个例子中,我们定义了一个名为ID的词法规则,该规则匹配一个以字母开头,后跟零个或多个字母、数字或下划线的字符串。在语法规则中,我们可以使用ID来匹配变量名。

语法规则

ANTLR4语法规则定义了输入文本的结构。语法规则由词法规则和其他语法规则组成,定义了输入文本的结构。语法规则通常以一个称为start的语法规则开始,这个语法规则定义了整个输入文本的结构。

以下是一个简单的例子:

// 定义一个简单的算术表达式语法规则
expr : INT| expr op=('*' | '/') expr| expr op=('+' | '-') expr| '(' expr ')';INT : [0-9]+;

在这个例子中,我们定义了一个名为expr的语法规则,该规则定义了一个简单的算术表达式。该规则由四个子规则组成,每个子规则定义了一种表达式。第一个子规则匹配整数,第二个和第三个子规则匹配乘法、除法、加法和减法,最后一个子规则匹配括号中的表达式。我们还定义了一个名为INT的词法规则,该规则匹配一个或多个数字。在这个例子中,我们使用INT来匹配整数。

语法规则中的操作

// 定义一个带有语义谓词的语法规则
expr : INT { $INT.text.equals("0")}

在这个例子中,我们定义了一个名为expr的语法规则,该规则匹配整数,并使用语义谓词来指定该规则是否适用于输入文本。在这个例子中,语义谓词检查整数是否为零。

如何使用ANTLR4

  1. 下载并安装ANTLR4:只需要下载官方网站上提供的ANTLR4 JAR文件,然后将其添加到您的Java类路径中即可。您还可以选择安装ANTLR4插件来集成到您的IDE中,以便更方便地使用ANTLR4。下面我们演示如何在IDEA中使用ANTLR4插件。

  2. 编写语法文件:在ANTLR4中,您需要编写一个.g4文件来定义词法和语法规则。您可以使用文本编辑器编写.g4文件。

  3. 生成代码:一旦您编写了.g4文件,您可以使用ANTLR4生成Java代码。使用以下命令可以生成Java代码:

java -jar antlr-4.9.2-complete.jar YourGrammar.g4

在上面的命令中,您需要将YourGrammar.g4替换为您的.g4文件的名称。

  1. 编写解析器:一旦您生成了Java代码,您可以编写一个Java解析器来解析输入文本。您可以使用ANTLR4提供的Java API来编写解析器。
CharStream input = CharStreams.fromStream(System.in);
YourGrammarLexer lexer = new YourGrammarLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
YourGrammarParser parser = new YourGrammarParser(tokens);
YourGrammarParser.StartContext tree = parser.start();

在上面的代码中,您需要将YourGrammarLexer和YourGrammarParser替换为您生成的Lexer和Parser类的名称。您还需要替换start()方法,该方法应该返回您的语法规则中的start规则的ParseTree对象。

实战

我们来做一个具体的例子,经典的计算器,主要是实现四则运算,带括号等等。

IDEA安装ANTLR插件

File->Settings->Plugins->Marketplace

新建项目

新建一个maven项目

pom.xml引入antlr的依赖

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

创建一个.g4文件

grammar Arithmetic;/** Parser rules*/parse: expr EOF;expr: term (('+'|'-') term)*;term: factor (('*'|'/') factor)*;factor: NUMBER| '(' expr ')';/** Lexer rules*/NUMBER: DIGIT+ ('.' DIGIT+)?;DIGIT: [0-9];WHITESPACE: [ \t\n\r] -> skip;

在这个语法规则中,我们定义了四个规则:

  • parse:最高级别的规则,表示一个完整的表达式。它由一个expr规则后面跟着一个EOF标记组成。
  • expr:表示一个加法或减法表达式。它由一个term规则后面跟着零个或多个加法或减法符号,后面再跟着一个term规则组成。
  • term:表示一个乘法或除法表达式。它由一个factor规则后面跟着零个或多个乘法或除法符号,后面再跟着一个factor规则组成。
  • factor:表示一个数字或括号内的表达式。它可以是一个数字,或者是一个由左括号、一个表达式和右括号组成的组合。

注意,在这个示例中,我们还定义了一些Lexer规则,用于识别数字和忽略空格和换行符。

我们可以通过idea的antlr插件来检查我们的语法规则:
如下图,点击ANTLR Preview可以来到如下界面。左边的框填写需要校验的表达式,右边就是语法树解析的结果。

接下来,我们需要使用ANTLR来生成Java代码。

通过插件生成java代码

右键.g4文件,选择Configure ANTLR,配置java文件的生成路径。

再次右键.g4文件,选择Generate ANTLR Reconizer 即可生成java代码

创建一个EvalVisitor遍历AST

我们创建一个EvalVisitor遍历AST,并计算表达式的值。最终,我们打印计算结果。
EvalVisitor是一个我们需要自己实现的类,它继承了ArithmeticBaseVisitor,并重写了其中的方法。下面是一个简单的实现示例:
新建类EvalVisitor.java

public class EvalVisitor  extends ArithmeticBaseVisitor<Double> {// 使用一个Map来存储变量名和值的映射关系Map<String, Double> memory = new HashMap<String, Double>();// 重写visitExpr方法,用于计算加法和减法@Overridepublic Double visitExpr(ArithmeticParser.ExprContext ctx) {Double result = visit(ctx.term(0));for (int i = 1; i < ctx.term().size(); i++) {String op = ctx.getChild(2*i - 1).getText();Double term = visit(ctx.term(i));if (op.equals("+")) {result += term;} else {result -= term;}}return result;}// 重写visitTerm方法,用于计算乘法和除法@Overridepublic Double visitTerm(ArithmeticParser.TermContext ctx) {Double result = visit(ctx.factor(0));for (int i = 1; i < ctx.factor().size(); i++) {String op = ctx.getChild(2*i - 1).getText();Double factor = visit(ctx.factor(i));if (op.equals("*")) {result *= factor;} else {result /= factor;}}return result;}// 重写visitFactor方法,用于计算数字和括号内的表达式@Overridepublic Double visitFactor(ArithmeticParser.FactorContext ctx) {if (ctx.NUMBER() != null) {// 如果是一个数字,直接返回其值return Double.parseDouble(ctx.NUMBER().getText());} else {// 如果是括号内的表达式,递归调用visit方法return visit(ctx.expr());}}
}

测试

新建测试类Test.java

public class Test {public static void main(String[] args) throws Exception {String input = "(1+2)*3-4";// 创建一个词法分析器,用于将输入转换为标记ArithmeticLexer lexer = new ArithmeticLexer(CharStreams.fromString(input));// 创建一个标记流,用于将标记传递给解析CommonTokenStream tokens = new CommonTokenStream(lexer);// 创建一个解析器,用于将标记转换为ASTArithmeticParser parser = new ArithmeticParser(tokens);// 调用解析器的parse方法,生成ASTParseTree tree = parser.parse();// 创建一个AST遍历器,用于计算表达式的值EvalVisitor eval = new EvalVisitor();// 遍历AST,并计算表达式的值double result = eval.visit(tree);// 打印计算结果System.out.println(result);}}

测试(1+2)*3-4结果如图:

ANTLR4入门【打造你自己的语法规则】相关推荐

  1. python中if和else语句的格式要求_Python小白入门:if测试和语法规则

    本章节的内容,主要讲解if语句,if语句是三大复合语句之一(其他两个是while和for),能处理编程中大多数逻辑运算 本章的重点内容如下: 1.if语句的基本形式(多路分支) 2.布尔表达式 3.i ...

  2. HTML第一章 (WEB基础知识、 HTML入门、HTML的语法规则、HTML常用标签汇总、图片与超链接、HBuilder的快捷键)

    目录 一.WEB基础知识 二.HTML入门 三.HTML的语法规则 四.HTML标签 五.图片与超链接 六.HBuilder的快捷键 每日一句 一.WEB基础知识 我们可以做什么? WEB前端 大前端 ...

  3. ANTLR4入门(三):使用mave ANTLR4插件(antlr4-maven-plugin)执行语法解析生成器

    在上篇博客<ANTLR4入门(二):图示说明eclipse安装Antlr4IDE插件的过程>,我费半天劲装好了Eclise的AntlrIDE插件,简单的创建一个ANTLR 4 工程,感受了 ...

  4. JSON基础入门实战讲解在线视频课程-JSON语法规则,json对象,json数组的定义和使用

    JSON 语法 微信小程序交流群:111733917 | 微信小程序从0基础到就业的课程:https://edu.csdn.net/topic/huangjuhua JSON 语法是 JavaScri ...

  5. Antlr4入门(三)如何编写语法文件

    本章我们将会学习词法及语法规则,以及四种抽象的计算机语言模式.因为ANTLR的语法规则跟正则表达式是很类似的,所以还是推荐先阅读下正则表达式的相关内容,这样在编写语法文件时可以事半功倍. 一.四种语言 ...

  6. 炎炎夏日,深夜详谈nginx的配置中location和rewrite的语法规则(从入门到高手的第六步)

    前言 在生产实际中,当用户页面请求后,很多是需要自动跳转到其他特定页面,这个时候往往可以利用nginx配置中location规则或rewrite语法进行设置. Nginx提供的全局变量或自己设置的变量 ...

  7. Antlr4入门(安装、配置、简单实例)

    Antlr4入门(安装.配置.简单实例) 2020.5.28 仅本人初次使用Antlr4的经历分享 目前所知有3种使用Antlr4的方式: 通过命令行使用: 在Eclipse中安装Antlr4插件:( ...

  8. LLVM一些语法规则

    LLVM一些语法规则 LLVM文档 LLVM编译器基础架构支持广泛的项目,从工业强度编译器到专门的JIT应用程序,再到小型研究项目. 同样,文档分为几个针对不同受众的高级别分组: LLVM设计概述 几 ...

  9. 一文详解CMakeLists文件编写语法规则详解

    作者丨zhanghm1995@blog 来源丨https://blog.csdn.net/zhanghm1995/article/details/80902807 编辑丨3D视觉工坊 基本语法规则 C ...

最新文章

  1. 那年高考“坑爹“的金思力
  2. 如何解决使用JSON.stringify时遇到的循环引用问题
  3. 2021“MINIEYE杯”中国大学生算法设计超级联赛(2)I love exam(背包)
  4. VUE初始化一个项目
  5. 跨平台RTSP/RTMP转RTMP转发SDK
  6. 计算机中丢失xapofx1 5.dll,xapofx1 5 dll丢失怎么办_系统提示xapofx1 5 dll丢失的解决方法...
  7. 平流式沉淀池表面负荷怎么计算_推荐收藏关于斜管(板)沉淀池的知识点汇总,及常见问题解决!...
  8. python爬取内容_Python爬取小说内容
  9. 新入职我们应该注意些什么?
  10. Spring知识点复习(第一次)
  11. Redis实现邮件激活码保存
  12. 基于matlab的车牌识别系统的实现
  13. “(null)” is of a model that is not supported by this version of Xcode. Ple
  14. ftp服务器空文件夹不让删,FTP不能删除(修改)文件夹的问题?(转载)
  15. uniapp做自己的启动页
  16. esxi 内核 linux,大娃套小娃系列-ESXI虚拟机安装Debian系统实现Docker容器
  17. FreeBSD中编译JDK
  18. Kaggle时间序列(Time Series)教程 6-使用机器学习预测(forecasting-with-machine-learning)
  19. 汇编语言||基本传送指令MOV的用法详解
  20. 转载:毕业半年在富士康的经历

热门文章

  1. 微信小程序版 九宫格数独游戏
  2. 几种基本的约束和外键(一对一 多对多 多对一)级联关系
  3. gem5下用se模式运行自己的测试程序
  4. 乱七八糟的笔记(%)
  5. codeforces1064E Dwarves, Hats and Extrasensory Abilities
  6. day6python基础数据补充
  7. matlab数组删除指定行列元素
  8. BPMN2.0 泳池与泳道
  9. 通过cmd窗口导入导出mysql数据库
  10. sql server编程之 T-SQL函数