实现脚本引擎技术详解
脚本引擎概述与设计规范
JKScript引擎是一个专注于算术表达式求值的轻量级脚本引擎实现,其核心功能遵循以下技术规范:
功能特性
-
表达式求值规则:
- 仅支持二元运算表达式(操作数+运算符+操作数)
- 操作数支持十进制数字字面量(如
10.7
)和变量(如num1
) - 运算符限定为四则运算(
+
,-
,*
,/
) - 返回结果为
Double
类型对象
-
输入源支持:
// 支持String直接输入 engine.eval("10 + 90");// 支持Reader输入(单表达式) Reader reader = new StringReader("num1 * num2"); engine.eval(reader);
架构设计
采用三层核心类结构:
类名 | 职责 |
---|---|
Expression | 表达式解析与求值核心逻辑 |
JKScriptEngine | 实现ScriptEngine 接口的适配层 |
JKScriptEngineFactory | 服务发现机制实现 |
模块化部署
通过Java模块系统声明依赖关系:
// module-info.java
module jdojo.jkscript {requires java.scripting;provides javax.script.ScriptEngineFactorywith com.jdojo.jkscript.JKScriptEngineFactory;
}
模块设计特点:
- 强封装性(不导出任何包)
- 通过
java.scripting
模块获取基础API支持 - 服务注册机制实现自动发现
表达式解析原理
Expression
类采用正则表达式进行语法分析:
// 表达式模式定义
String pattern = "^([+-]?)([\\p{Alnum}\\p{Sc}_.]+)([\\s]*)([+*/-])([\\s]*)([+-]?)([\\p{Alnum}\\p{Sc}_.]+)$";
解析流程:
- 操作数符号提取(
+/-
前缀) - 操作数类型识别(数字字面量/绑定变量)
- 运算符验证
- 上下文变量查找(通过
ScriptContext
)
边界条件处理
引擎明确限制以下场景:
// 不支持的情况示例
engine.eval("0x2A + 0b1011"); // 非十进制数字
engine.eval("num1 % num2"); // 非四则运算符
engine.eval("a + b + c"); // 多元运算
核心实现类详解
Expression类
作为算术运算的核心处理器,主要包含:
关键字段:
private String op1; // 左操作数
private char op1Sign; // 左操作数符号
private char operation; // 运算符
private boolean parsed; // 解析状态标记
求值流程:
- 语法解析(
parse()
方法) - 操作数取值(
getOperandValue()
方法) - 运算执行(
eval()
方法)
典型用法:
ScriptContext context = engine.getContext();
Expression exp = new Expression("num1 * -5.2", context);
Double result = exp.eval();
JKScriptEngine类
继承AbstractScriptEngine
实现标准接口:
核心方法实现:
@Override
public Object eval(String script, ScriptContext context) {Expression exp = new Expression(script, context);return exp.eval();
}@Override
public Object eval(Reader reader, ScriptContext context) {// 多行表达式合并处理String script = reader.lines().collect(Collectors.joining());return eval(script, context);
}
JKScriptEngineFactory类
实现服务发现接口的关键配置:
引擎标识配置:
@Override
public List getNames() {return List.of("jks", "JKScript", "jkscript");
}@Override
public ScriptEngine getScriptEngine() {