javacc学习笔记 01、JavaCC本地安装与测试

发布于:2025-08-05 ⋅ 阅读:(10) ⋅ 点赞:(0)

javacc学习笔记 01、JavaCC本地安装与测试

前言

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

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

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

CSDN搜索:长路

视频平台:b站-Coder长路

本章节源码

当前文档配套相关源码地址:

  • gitee:https://gitee.com/changluJava/demo-exer/tree/master/java-sqlparser/demo-javacc/learn-javacc-demo
  • github:https://github.com/changluya/Java-Demos/tree/master/java-sqlparser/demo-javacc/learn-javacc-demo

一、什么是javacc

javacc官网:https://javacc.github.io/javacc/

介绍:JavaCC(Java Compiler Compiler)是一种广泛使用的解析器和词法分析器生成工具,主要用于处理编程语言、数据格式以及任何需要精确解析的文本输入。它最初是为Java语言设计的,但现在也可以用于其他编程环境。JavaCC帮助开发者通过定义语法和词法规则来创建编译器前端,包括词法分析器(Scanner)和语法分析器(Parser),从而简化了编译器开发的过程。

简单来说:JavaCC是一个能生成词法和语法的分析器的生成程序。

  • 词法分析器,就是对一串文本进行拆分,转换成一系列的Token。
  • 语法分析器,就是对词法分析器产生的Token,进行校验。

**应用场景:**JavaCC常被用来开发编译器、解释器、特定领域的语言处理器等,也适用于需要对文本进行复杂解析的应用程序中。例如,它可以用来解析SQL查询、JSON文档或者自定义配置文件格式。开始使用JavaCC时,你需要编写一个语法文件(.jj),在这个文件里定义你的语言的语法规则。之后,通过JavaCC工具处理这个文件,即可生成相应的Java代码,这些代码实现了你定义的解析逻辑。

二、Mac环境安装javacc

相关教程:

步骤如下:

1)首先提前安装Homebrew

2)下载和安装javacc

brew install javacc

查看javacc安装的目录:

// 目录位置:/opt/homebrew/opt/javacc
brew --prefix javacc

3)测试javacc

javacc -version

若是出现异常报错:

null

关于version版本范围表:https://blog.csdn.net/gaofenglxx/article/details/137559852

null

表示要使用jdk21,jdk21下载地址:https://www.oracle.com/java/technologies/downloads/#jdk21-mac

下载安装后修改下环境变量JAVA_HOME

vim ~/.zshrc

-- 原始jdk8
export JAVA_HOME="/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home"
-- 修改为jdk21
export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home"

source ~/.zshrc

null

指定jdk21即可,查看当前的javacc版本号。


三、javacc测试案例

1、编写词法描述文件

null

JavaCC的语法描述文件是 扩展名为.jj 的文件,测试所用的语法描述文件内容如下,该描述文件的功能是解析正整数加法运算,并进行计算的解析器的语法描述文件,设置名称为demo01.jj:

options {
    STATIC = false;
}

PARSER_BEGIN(Adder)
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);
    }
}  

2、借助javacc命令来处理demo01.jj文件

进入到对应jj文件所在的目录,执行命令:

javacc demo01.jj

null

此时就出现了生成的java文件:

null


3、idea配置输入参数,运行Adder类方法

我们将生成的代码移入到java源代码目录中:

null

实际上也可以在采用最原生的方式对目录中通过执行命令方式去执行我们生成的类:

javac Adder.java
  
java Adder 1+7

null

我们这里也可以直接idea工具来配置参数来快速测试,添加参数1+7:

null

接着我们来运行下该任务:

null

四、javacc文件编译类描述

4.1、demo1.jj文件生成内容描述&解析转换过程

在一开始的javacc的demo案例中通过javacc对demo1.jj文件来进行生成,得到的内容如下:

null

生成的各个类介绍描述如下:

  • XXXXX(指的是Adder):解析类入口
  • XXXXXConstants:Token常量,SKIP TOKEN 和TOKEN
  • XXXXXTokenManager:词法分析器
  • SimpleCharStream:词法分析器的输入流
  • Token:Token类
  • ParseException:语法解析异常
  • TokenMgrError:语法错误提示

引用大佬神图:https://github.com/quxiucheng/apache-calcite-tutorial/blob/a7d63273d0c7585fc65ad250c99a67a201bcb8b5/calcite-tutorial-2-parser/parser-2-javacc-tutorial/README.md

null


4.2、解析demo01.jj文件

目标:用于解析并计算形如"数字+数字"的字符串表达式。

选项部分

options {
    STATIC = false;
}
  • STATIC = false; 表示生成的解析器类不会是静态的。这意味着你可以创建该类的对象实例,并可能在多个解析任务之间共享状态。

解析器定义部分

PARSER_BEGIN(Adder)
// Java 代码块
PARSER_END(Adder)
  • 这一部分定义了名为Adder的解析器。其中包含了主函数mainevaluate方法。
  • evaluate方法接收一个字符串参数,将其转换为Reader对象,并调用expr()方法来解析并计算表达式的值。

跳过规则

SKIP: { <[" ", "\t", "\r", "\n"]> }
  • 定义了哪些字符应被跳过而不进行处理,这里包括空格、制表符、回车符和换行符,它们通常用于分隔输入中的不同元素。

令牌定义

TOKEN: {
    <INTEGER: (["0"-"9"])+>
}
  • 定义了一个名为INTEGER的令牌,它匹配一个或多个连续的数字字符(0-9)。

解析规则

long expr():
{
    Token x, y;
}
{
    x=<INTEGER> "+" y=<INTEGER> <EOF>
    {
        return Long.parseLong(x.image) + Long.parseLong(y.image);
    }
}
  • expr方法尝试匹配一个模式:一个整数后跟一个加号再跟另一个整数,最后是一个文件结束标记(<EOF>)。
  • 如果匹配成功,将两个Token对象的image属性(即实际匹配到的字符串)转换为长整型数值,并返回它们的和。

4.3、快速写一个支持合并字符串的javacc语法文件

null

options {
    STATIC = false;
}

PARSER_BEGIN(Adder)
import java.io.*;
public class Adder {
    public static void main(String[] args) {
        for (String arg : args) {
            try {
                System.out.println(evaluate(arg));
            } catch (ParseException ex) {
                System.err.println(ex.getMessage());
            }
        }
    }

    public static String evaluate(String src) throws ParseException {
        Reader reader = new StringReader(src);
        return new Adder(reader).concatExpr();
    }
}
PARSER_END(Adder)

SKIP: { <[" ", "\t", "\r", "\n"]> }

TOKEN: {
    <STRING_LITERAL: "\"" (~["\""])* "\""> | // 字符串字面量
    <IDENTIFIER: (["a"-"z", "A"-"Z"])+>      // 标识符或变量名
}

String concatExpr():
{
    Token x, y;
}
{
    x=<IDENTIFIER> "+" y=<IDENTIFIER> <EOF>
    {
        return x.image + y.image;
    }
}

null


参考文章

[1]. 1.JavaCC安装与测试

资料获取

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

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

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


网站公告

今日签到

点亮在社区的每一天
去签到