ANTLR中自定义语法分析过程

2024-03-29 10:18

本文主要是介绍ANTLR中自定义语法分析过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

自定义语法分析过程

语法中嵌入动作

除了使用监听器和访问器,我们还可以手动实现对语法分析树的访问

例如要对如下三列文本进行识别,打印指定的列,例如第一列为parrt tombu bke,列之间以Tab分割

parrt Terence Parr 101
tombu Tom Burns 020
bke Kevin Edgar 008

在语法文件Rows.g4中添加一些自定义的动作,通过members将RowParser注入到生成的语法分析器类中

grammar Rows;@parser::members { int col;public RowsParser(TokenStream input, int col) { // custom constructorthis(input);this.col = col;}
}file: (row NL)+ ;row
locals [int i=0]	//使用locals定义局部变量$i: (   STUFF{$i++;		if ( $i == col ) System.out.println($STUFF.text);		//$STUFF.text获取词法符号匹配的文本})+;TAB  :  '\t' -> skip ;   // match but don't pass to the parser
NL   :  '\r'? '\n' ;     // match and pass to the parser
STUFF:  ~[\t\r\n]+ ;     // match any chars except tab, newline

接下来在主程序中调用语法分析器,这里传入为RowsParser传入词法符号tokens和列号参数col,并且设置不自动生成语法分析树

public class Col {public static void main(String[] args) throws Exception {ANTLRInputStream input = new ANTLRInputStream(System.in);RowsLexer lexer = new RowsLexer(input);CommonTokenStream tokens = new CommonTokenStream(lexer);int col = Integer.valueOf(args[0]);RowsParser parser = new RowsParser(tokens, col); // 传递列好作为参数parser.setBuildParseTree(false); // 不需要自动生成语法树parser.file(); // parse}
}

构建项目并进行测试如下,可以看到输出了第一列的内容

D:\Code\antlr\demo\chapter4>antlr4 -no-listener Rows.g4D:\Code\antlr\demo\chapter4>javac Rows*.java Col.javaD:\Code\antlr\demo\chapter4>java Col 1 < t.rows
parrt
tombu
bke
语义判定

通过表达式{$i<=$n}?可以对匹配条件进行判定,从而执行不同的语法分支

例如要对如下的数字序列进行匹配,第一个数字为2,则往后匹配两个数9、10,接下来为3,向后匹配三个数1、2、3

2 9 10 3 1 2 3

使用如下语法文件对数字序列进行匹配,通过判定表达式实现向后匹配n个整数

grammar Data;file : group+ ;group: INT sequence[$INT.int] ;sequence[int n]
locals [int i = 1;]: ( {$i<=$n}? INT {$i++;} )* // 匹配n个整数;INT :   [0-9]+ ;             // match integers
WS  :   [ \t\n\r]+ -> skip ; // toss out all whitespace

词法分析器特性

孤岛语法:输入文件中包含多种语言,需要将模板表达式之外的文本按照不同方式处理。

ANTLR的词法分析模式(lexical model)可以对不同格式数据的文件进行处理,例如对XML文件进行处理时,当看到<时,词法分析器就会进入“标签内部”模式,看到>或者/>时就切回默认模式

重写输入流:TokenStreamRewriter可以对词法输入流进行修改之后再输出,它只是修改词法符号流的“视图”而非其本身的内容。如下所示为一个Java类的输入流中添加指定代码public static final long serialVersionUID = 1L;,重写监听器进入类的方法,在其中使用rewriter追加内容

import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.TokenStreamRewriter;public class InsertSerialIDListener extends JavaBaseListener {TokenStreamRewriter rewriter;public InsertSerialIDListener(TokenStream tokens) {rewriter = new TokenStreamRewriter(tokens);}@Overridepublic void enterClassBody(JavaParser.ClassBodyContext ctx) {String field = "\n\tpublic static final long serialVersionUID = 1L;";	//对输入流添加指定内容rewriter.insertAfter(ctx.start, field);}
}

这篇关于ANTLR中自定义语法分析过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/858332

相关文章

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

k8s中实现mysql主备过程详解

《k8s中实现mysql主备过程详解》文章讲解了在K8s中使用StatefulSet部署MySQL主备架构,包含NFS安装、storageClass配置、MySQL部署及同步检查步骤,确保主备数据一致... 目录一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

linux部署NFS和autofs自动挂载实现过程

《linux部署NFS和autofs自动挂载实现过程》文章介绍了NFS(网络文件系统)和Autofs的原理与配置,NFS通过RPC实现跨系统文件共享,需配置/etc/exports和nfs.conf,... 目录(一)NFS1. 什么是NFS2.NFS守护进程3.RPC服务4. 原理5. 部署5.1安装NF

MySQL使用EXISTS检查记录是否存在的详细过程

《MySQL使用EXISTS检查记录是否存在的详细过程》EXISTS是SQL中用于检查子查询是否返回至少一条记录的运算符,它通常用于测试是否存在满足特定条件的记录,从而在主查询中进行相应操作,本文给大... 目录基本语法示例数据库和表结构1. 使用 EXISTS 在 SELECT 语句中2. 使用 EXIS

SpringBoot AspectJ切面配合自定义注解实现权限校验的示例详解

《SpringBootAspectJ切面配合自定义注解实现权限校验的示例详解》本文章介绍了如何通过创建自定义的权限校验注解,配合AspectJ切面拦截注解实现权限校验,本文结合实例代码给大家介绍的非... 目录1. 创建权限校验注解2. 创建ASPectJ切面拦截注解校验权限3. 用法示例A. 参考文章本文

oracle 11g导入\导出(expdp impdp)之导入过程

《oracle11g导入导出(expdpimpdp)之导入过程》导出需使用SEC.DMP格式,无分号;建立expdir目录(E:/exp)并确保存在;导入在cmd下执行,需sys用户权限;若需修... 目录准备文件导入(impdp)1、建立directory2、导入语句 3、更改密码总结上一个环节,我们讲了