
com.ajaxjs.jsonparser.syntax.FMS Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ajaxjs-base Show documentation
Show all versions of ajaxjs-base Show documentation
A pure Java library that provides many tools, utils, and functions.
/**
* Copyright Sp42 [email protected]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ajaxjs.jsonparser.syntax;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
import com.ajaxjs.jsonparser.JsonParseException;
import com.ajaxjs.jsonparser.lexer.Lexer;
import com.ajaxjs.jsonparser.lexer.Token;
import com.ajaxjs.jsonparser.lexer.Tokens;
/**
* 语法解析的状态机 Thanks to blog.csdn.net/yimengqiannian/article/details/53701275
*/
public class FMS implements States {
/**
* 词法分析器实例
*/
private Lexer lex;
/**
* 堆栈管理器
*/
private Operator opt;
/**
* 当前状态
*/
private State status;
/**
* 创建一个状态机
*
* @param json JSON 字符串
*/
public FMS(String json) {
Objects.requireNonNull(json, "没有输入的 JSON 字符串。");
lex = new Lexer(json);
opt = new Operator(lex);
}
/**
* 开始解析 JSON 字符串
*
* @return MAP|LIST
*/
public Object parse() {
status = BGN;
State oldStatus = status; // 上一个状态
Token tk;
while ((tk = lex.next()) != Tokens.EOF) {
if (tk == null)
throw lex.exceptionFactory("发现不能识别的 token:" + lex.getCurChar());
if (status == VAL || status == EOF || status == ERR)
throw lex.exceptionFactory(String.format(strTpl, oldStatus.getDescription(), "结束", tk.toString()));
oldStatus = status;
status = states[oldStatus.getId()][tk.getType()];
if (status == ERR) {
String expectStr = ETS[oldStatus.getId()];
throw lex.exceptionFactory(String.format(strTpl, oldStatus.getDescription(), expectStr, tk.toString()));
}
Method m = TKOL[tk.getType()];
try {
if (m != null) // 输入 Token 操作 有点像 js 的 call/apply
status = (State) m.invoke(opt, oldStatus, status, tk);
m = status.getHandler();
if (m != null) // 目标状态操作
status = (State) m.invoke(opt, oldStatus, status, tk);
} catch (IllegalArgumentException e) {
throw lex.exceptionFactory("【反射调用】传入非法参数", e);
} catch (IllegalAccessException e) {
throw lex.exceptionFactory("【反射调用】私有方法无法调用", e);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof JsonParseException)
throw (JsonParseException) e.getTargetException();
else
throw lex.exceptionFactory("运行时异常", e);
}
}
return opt.getCurValue();
}
private final static String strTpl = "当前状态【 %s 】, 期待【 %s 】; 但却返回 %s";
/**
* Token 输入操作列表
*/
/* INPUT —— STR NUM DESC SPLIT ARRS OBJS ARRE OBJE FALSE TRUE NIL BGN */
private static final Method[] TKOL = { null, null, null, null, Operator.getMethod("arrs"),
Operator.getMethod("objs"), null, null, null, null, null, null };
// STR NUM DESC SPLIT ARRS OBJS ARRE OBJE FALSE TRUE NIL BGN
final static String[] allText = { "字符串", "数字", Tokens.DESC.getTypeNameChinese(), Tokens.SPLIT.getTypeNameChinese(),
Tokens.ARRS.getTypeNameChinese(), Tokens.OBJS.getTypeNameChinese(), Tokens.ARRE.getTypeNameChinese(),
Tokens.OBJE.getTypeNameChinese(), Tokens.FALSE.getTypeNameChinese(), Tokens.TRUE.getTypeNameChinese(),
Tokens.NIL.getTypeNameChinese(), Tokens.BGN.getTypeNameChinese(), };
// BGN ARRBV ARRAV OBJBK OBJAK OBJBV OBJAV VAL EOF ERR
final static String[] ETS = { getExpectStr(BGN.getId()), getExpectStr(ARRBV.getId()), getExpectStr(ARRAV.getId()),
getExpectStr(OBJBK.getId()), getExpectStr(OBJAK.getId()), getExpectStr(OBJBV.getId()),
getExpectStr(OBJAV.getId()), Tokens.EOF.getTypeNameChinese(), Tokens.EOF.getTypeNameChinese(),
Tokens.EOF.getTypeNameChinese() };
/**
* 获取期望 Token 描述字符串
*
* @param stateId 状态 id
* @return 期望 Token 描述字符串
*/
static String getExpectStr(int stateId) {
State[] stateArr = States.states[stateId];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < stateArr.length; i++) {
State s = stateArr[i];
if (s != ERR) {
sb.append(allText[i]).append('|');
}
}
return sb.length() == 0 ? null : sb.deleteCharAt(sb.length() - 1).toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy