目前在使用QtScriptEngine,在利用evaluate注册子函数时,要求用户输入的js文件中的内容仅仅是函数,函数体外不能出现一些变量的声明、函数的调用等其他代码。
反复咨询DeepSeek后,终于给出了一个目前测试可用的代码:
bool isPureFunctions(const QString& code) {
enum State {
Normal,
InFunctionBody,
InLineComment,
InBlockComment,
InString
};
State state = Normal;
int braceDepth = 0;
bool hasFunction = false;
QChar stringQuote;
int functionStartDepth = 0; // 记录函数起始层级的栈
for (int i = 0; i < code.length(); ++i) {
const QChar c = code[i];
const QChar next = (i < code.length()-1) ? code[i+1] : QChar();
switch (state) {
case Normal:
if (c.isSpace()) {
continue;
} else if (c == '/' && next == '*') {
state = InBlockComment;
i++; // 跳过 *
} else if (c == '/' && next == '/') {
state = InLineComment;
i++; // 跳过 /
} else if (c == 'f' && code.mid(i, 8) == "function") {
// 进入函数声明
i += 7; // 跳过 "function"
state = InFunctionBody;
braceDepth = 0;
hasFunction = true;
functionStartDepth = 0; // 重置层级计数器
} else {
// 非函数代码立即拒绝
if (hasFunction) return false; // 函数后出现其他代码
else return false; // 函数外出现其他代码
}
break;
case InFunctionBody:
if (c == '{') {
braceDepth++;
if (braceDepth == 1) functionStartDepth = i; // 记录函数起始位置
} else if (c == '}') {
if (--braceDepth == 0) {
state = Normal; // 函数体结束
} else if (braceDepth < 0) {
return false; // 花括号不匹配
}
} else if (c == '"' || c == '\'' || c == '`') {
state = InString;
stringQuote = c;
}
break;
case InLineComment:
if (c == '\n') state = Normal;
break;
case InBlockComment:
if (c == '*' && next == '/') {
state = Normal;
i++; // 跳过 /
}
break;
case InString:
if (c == stringQuote && (i == 0 || code[i-1] != '\\')) {
state = InFunctionBody;
}
break;
}
}
// 最终必须回到Normal状态且至少有一个函数
return state == Normal && hasFunction;
}
测试:
// 应返回 true 的有效用例
QString validCode =
"function foo1(){}\n"
"function foo2(){ if(true){} }";
qDebug() << isPureFunctions(validCode); // 输出 true
// 应返回 false 的无效用例
QString invalidCode =
"function foo(){}\n"
"console.log(123);\n"
"function bar(){}";
qDebug() << isPureFunctions(invalidCode); // 输出 false