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

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

Solr 使用Facet分组过程中与分词的矛盾解决办法

对于一般查询而言  ,  分词和存储都是必要的  .  比如  CPU  类型  ”Intel  酷睿  2  双核  P7570”,  拆分成  ”Intel”,”  酷睿  ”,”P7570”  这样一些关键字并分别索引  ,  可能提供更好的搜索体验  .  但是如果将  CPU  作为 Facet  字段  ,  最好不进行分词  .  这样就造成了矛盾  ,  解决方法

Oracle type (自定义类型的使用)

oracle - type   type定义: oracle中自定义数据类型 oracle中有基本的数据类型,如number,varchar2,date,numeric,float....但有时候我们需要特殊的格式, 如将name定义为(firstname,lastname)的形式,我们想把这个作为一个表的一列看待,这时候就要我们自己定义一个数据类型 格式 :create or repla

Python:豆瓣电影商业数据分析-爬取全数据【附带爬虫豆瓣,数据处理过程,数据分析,可视化,以及完整PPT报告】

**爬取豆瓣电影信息,分析近年电影行业的发展情况** 本文是完整的数据分析展现,代码有完整版,包含豆瓣电影爬取的具体方式【附带爬虫豆瓣,数据处理过程,数据分析,可视化,以及完整PPT报告】   最近MBA在学习《商业数据分析》,大实训作业给了数据要进行数据分析,所以先拿豆瓣电影练练手,网络上爬取豆瓣电影TOP250较多,但对于豆瓣电影全数据的爬取教程很少,所以我自己做一版。 目

HTML5自定义属性对象Dataset

原文转自HTML5自定义属性对象Dataset简介 一、html5 自定义属性介绍 之前翻译的“你必须知道的28个HTML5特征、窍门和技术”一文中对于HTML5中自定义合法属性data-已经做过些介绍,就是在HTML5中我们可以使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放,例如我们要在一个文字按钮上存放相对应的id: <a href="javascript:" d