当前位置: 首页 > news >正文

javacc学习笔记 02、JavaCC 语法描述文件的格式解析

文章目录

  • 前言
  • Javacc语法格式文件
  • demo代码及含义解释
  • demo代码注释
  • 参考文章
  • 资料获取

javacc学习笔记 02、JavaCC 语法描述文件的格式解析

前言

博主介绍:✌目前全网粉丝4W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。

涵盖技术内容:Java后端、大数据、算法、分布式微服务、中间件、前端、运维等。

博主所有博客文件目录索引:博客目录索引(持续更新)

CSDN搜索:长路

视频平台:b站-Coder长路

Javacc语法格式文件

JavaCC的语法描述文件格式如下所示:

options {JavaCC的选项
}PARSER_BEGIN(解析器类名)
package 包名;
import 库名;public class 解析器类名 {任意的Java代码
}
PARSER_END(解析器类名)扫描器的描述解析器的描述

JavaCC和java一样将解析器的内容 定义在单个类中 ,因此会在PARSER_BEGIN和PARSER_END之间描述这个类的相关内容。

下面拿一段实际代码来做示例,并对代码进行逐段拆分解析。

demo代码及含义解释

代码结构解析:

  1. options块中将STATIC选项设置为false, 将该选项设置为true的话JavaCC生成的所有成员及方法都将被定义为static,若将STATIC设置为true则所生成的解析器无法在多线程环境下使用,因此该选项总是被设置为false。(STATIC的默认值为true)
  2. 从PARSER_BEING(Adder)到PARSER_END(Adder)是解析器类的定义。解析器类中需要定义的成员和方法也写在这里。为了实现即使只有Adder类也能够运行,这里定义了main函数。
  3. 之后的SKIP和TOKEN部分定义了扫描器。SKIP表示要跳过空格、制表符(tab)和换行符。TOKEN表示扫描整数字符并生成token。
  4. long expr…开始到最后的部分定义了狭义的解析器。这部分解析token序列并执行某些操作。

main函数代码解析:

main函数将所有命令行参数的字符串作为计算对象的算式,依次用evaluate方法进行计算。evaluate方法中生成了Adder类的对象实例 。并让Adder对象来计算(解析)参数字符串src。要运行JavaCC生成的解析器类,需要下面2个步骤:

  1. 生成解析器类的对象实例
  2. 用生成的对象调用和需要解析的语句同名的方法

第1点:JavaCC4.0和JavaCC5.0生成的解析器中默认定义有如下四种类型的构造函数。

  • Parser(InputStream s):第1种的构造函数是通过传入InputStream对象来构造解析的。这个构造函数无法设定输入字符串的编码,因此无法处理中文字符等。
  • Parser (InputStream s, String encoding):第2种的构造函数除了InputStream对象外,还可以设置输入字符串的编码来生成解析器。但如果要解析中文字符串或注释的话,就必须使用第2种/3种构造函数。
  • Parser(Reader r):第3种的构造函数用于解析Reader对象所读入的内容。
  • Parser (x x x x TokenManager tm):第4种是将扫描器作为参数传入。

解析器生成后,用这个实例调用和需要解析的语法同名的方法。这里调用Adder对象的expr方法,接回开始解析,解析正常结束后会返回语义值。

options {STATIC = false;
}PARSER_BEGIN(Adder)
package com.susu.testJavaCC;
import java.io.*;
public class Adder {public static void main(String[] args) {for (String arg : args) {try {System.out.println(evaluate(arg));
//                return(evaluate(arg));} catch (ParseException ex) {System.err.println(ex.getMessage());}}}public static long evaluate(String src) throws ParseException {Reader reader = new StringReader(src);return new Adder(reader).expr();}
}
PARSER_END(Adder)SKIP: { <[" ", "\t", "\r", "\n"]> }
TOKEN: {<INTEGER: (["0"-"9"])+>
}long expr():
{Token x, y;
}
{x=<INTEGER> "+" y=<INTEGER> <EOF>{return Long.parseLong(x.image) + Long.parseLong(y.image);}
}

demo代码注释

// 设置选项,生成的parser类是否是静态的
options {STATIC = false; // 设置为false,意味着生成的parser类不是静态的
}// 定义解析器的开始,指定了解析器的类名
PARSER_BEGIN(Adder)// 定义了包名和导入的类
package com.susu.testJavaCC;
import java.io.*;// 定义了解析器的主体类
public class Adder {// 主函数,用于执行程序public static void main(String[] args) {// 遍历命令行参数for (String arg : args) {try {// 尝试计算表达式的值并打印结果System.out.println(evaluate(arg));// return(evaluate(arg)); // 这行被注释掉了,如果取消注释,将返回计算结果并退出} catch (ParseException ex) {// 如果解析过程中出现错误,打印错误信息System.err.println(ex.getMessage());}}}// 一个公共的静态方法,用于计算传入字符串表达式的值public static long evaluate(String src) throws ParseException {// 创建一个字符串读取器Reader reader = new StringReader(src);// 使用读取器作为输入,调用expr非终端符号,并返回结果return new Adder(reader).expr();}
}// 定义解析器的结束
PARSER_END(Adder)// 定义跳过的符号,即在解析过程中要忽略的字符,这里是空格、制表符、回车和换行符
SKIP: {<[" ", "\t", "\r", "\n"]> // 这些字符在解析过程中会被忽略
}// 定义一个TOKEN,即一个词法单元,这里定义了一个名为INTEGER的词法单元
TOKEN: {<INTEGER: (["0"-"9"])+> // 匹配一个或多个数字,构成一个整数
}// 定义一个非终端符号expr,它用于解析加法表达式,并返回计算结果
long expr():
{Token x, y;
}
{x=<INTEGER> "+" y=<INTEGER> <EOF>{// 当解析到两个由空格分隔的整数和一个加号时,计算这两个整数的和// Token是javacc定义的一个类,用于表示词法单元// image属性是Token匹配到的字符串return Long.parseLong(x.image) + Long.parseLong(y.image);}
}

参考文章

[1]. 3.JavaCC 语法描述文件的格式解析

资料获取

大家点赞、收藏、关注、评论啦~

精彩专栏推荐订阅:在下方专栏👇🏻

  • 长路-文章目录汇总(算法、后端Java、前端、运维技术导航):博主所有博客导航索引汇总
  • 开源项目Studio-Vue—校园工作室管理系统(含前后台,SpringBoot+Vue):博主个人独立项目,包含详细部署上线视频,已开源
  • 学习与生活-专栏:可以了解博主的学习历程
  • 算法专栏:算法收录

更多博客与资料可查看👇🏻获取联系方式👇🏻,🍅文末获取开发资源及更多资源博客获取🍅

http://www.dtcms.com/a/313787.html

相关文章:

  • iOS 内测上架流程详解:跨平台团队如何快速部署 TestFlight
  • iostat 系统IO监控命令学习
  • 墨者学院SQL过滤字符后手工注入漏洞测试(第1题)
  • uniapp快遞上門提貨的時間選擇的插件
  • Perl 面向对象编程深入解析
  • 【Git】常见命令整理
  • 工作流绑定卡片优化用户体验-练习我要找工作智能体
  • 人类学家与建筑师:解析 UX 研究与项目管理的需求分析差异​
  • 豆包新模型+PromptPilot深度评测:提示词工程的智能化突破
  • 数据结构:合并两个单链表(merging two linked lists)
  • 下面是修正后的完整版 doit_effects.c,已经做了三大关键修复(文件开头也有注释说明)
  • 使用opencv基于realsense D435i展示基本的图像
  • 如何基于MQ实现分布式事务
  • 深入浅出 RabbitMQ:简单队列实战指南
  • 消防器材检测数据集介绍-9,600 张图片 智慧安防系统 建筑施工安全监管 AI 消防巡检机器人 自动审核系统 公共场所安全监测
  • 深入解析线程同步中WaitForSingleObject的超时问题
  • Flutter 事件总线 Event Bus
  • 【2025WACV-最佳论文】RayGauss:基于体积高斯的光线投射,用于逼真的小说视图合成
  • 【机器学习】(算法优化二)提升算法之:AdaBoost与随机梯度
  • Java 中 BigDecimal、Float、Double 的取整与保留小数处理方法详解
  • 从 0 到 1 开发图书管理系统:飞算 JavaAI 让技术落地更简单
  • 13.Home-面板组件封装
  • 如何设计和实施高效的向量化数据检索解决方案
  • 阿里云-通义灵码:解锁云原生智能开发新能力,让云开发更“灵”~
  • Clion STM32CubeMX LED闪灯
  • 为什么叫电磁兼容?
  • 【Java】一篇详解HashMap的扩容机制!!
  • SCI论文选词炼句(下)
  • vue3指定设置了dom元素的ref但是为null问题
  • Druid手写核心实现案例 实现一个简单Select 解析,包含Lexer、Parser、AstNode