c++优化
This commit is contained in:
@@ -2386,202 +2386,162 @@ export class CppCodeExecutor {
|
||||
return position;
|
||||
}
|
||||
|
||||
// 字符串表达式
|
||||
if (expr.includes('"') || expr.includes("'")) {
|
||||
return expr.replace(/['"]/g, '');
|
||||
// 整个表达式是字符串字面量时才当字符串;含引号的 API 调用走后面的算术解析
|
||||
if ((expr.startsWith('"') && expr.endsWith('"')) ||
|
||||
(expr.startsWith("'") && expr.endsWith("'"))) {
|
||||
return expr.slice(1, -1);
|
||||
}
|
||||
|
||||
// 使用改进的表达式解析器处理复杂表达式
|
||||
return this.parseComplexExpression(expr);
|
||||
}
|
||||
|
||||
// 新增:改进的表达式解析器,支持括号嵌套和运算优先级
|
||||
// 递归下降:一元 +/- ,然后 * / % 优先于 + -
|
||||
parseComplexExpression(expr) {
|
||||
try {
|
||||
// 移除所有空格
|
||||
expr = expr.replace(/\s+/g, '');
|
||||
|
||||
// 处理括号
|
||||
while (expr.includes('(')) {
|
||||
const lastOpenParen = expr.lastIndexOf('(');
|
||||
const closeParen = expr.indexOf(')', lastOpenParen);
|
||||
|
||||
if (closeParen === -1) {
|
||||
debugLog(`⚠️ 括号不匹配: ${expr}`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const innerExpr = expr.substring(lastOpenParen + 1, closeParen);
|
||||
const innerResult = this.parseComplexExpression(innerExpr);
|
||||
|
||||
expr = expr.substring(0, lastOpenParen) + innerResult + expr.substring(closeParen + 1);
|
||||
}
|
||||
|
||||
// 处理一元运算符(负号)
|
||||
expr = this.handleUnaryOperators(expr);
|
||||
|
||||
// 按正确的运算优先级解析:
|
||||
// 加法和减法是最低优先级,因此在此处最先切分。
|
||||
// 切分后的每一项将交给 parseAdditionSubtraction,在其中处理更高级别的乘除法。
|
||||
return this.parseAdditionSubtraction(expr);
|
||||
|
||||
this._exprTokens = this.lexArithmetic(expr);
|
||||
this._exprPos = 0;
|
||||
if (this._exprTokens.length === 0) return 0;
|
||||
const result = this.parseAddExpr();
|
||||
return typeof result === 'number' && !Number.isNaN(result) ? result : 0;
|
||||
} catch (error) {
|
||||
debugLog(`⚠️ 表达式解析错误: ${expr}, 错误: ${error.message}`);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理一元运算符
|
||||
handleUnaryOperators(expr) {
|
||||
// 先处理开头的负号
|
||||
if (expr.startsWith('-')) {
|
||||
const restExpr = expr.substring(1);
|
||||
if (/^\d+/.test(restExpr)) {
|
||||
// 负数
|
||||
const match = restExpr.match(/^\d+/);
|
||||
const number = match[0];
|
||||
const remaining = restExpr.substring(number.length);
|
||||
return (-parseInt(number)) + remaining;
|
||||
} else if (/^[a-zA-Z_]\w*/.test(restExpr)) {
|
||||
// 负变量
|
||||
const match = restExpr.match(/^[a-zA-Z_]\w*/);
|
||||
const varName = match[0];
|
||||
const remaining = restExpr.substring(varName.length);
|
||||
if (this.variables.has(varName)) {
|
||||
return (-this.variables.get(varName)) + remaining;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
// 解析乘法、除法和模运算(高优先级)
|
||||
parseMultiplicationDivision(expr) {
|
||||
const tokens = this.tokenizeExpression(expr, ['*', '/', '%']);
|
||||
let result = this.evaluateToken(tokens[0]);
|
||||
|
||||
for (let i = 1; i < tokens.length; i += 2) {
|
||||
const operator = tokens[i];
|
||||
const operand = this.evaluateToken(tokens[i + 1]);
|
||||
|
||||
if (operator === '*') {
|
||||
result *= operand;
|
||||
} else if (operator === '/') {
|
||||
result = Math.floor(result / operand); // C++整数除法
|
||||
} else if (operator === '%') {
|
||||
result = result % operand; // 模运算
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 解析加法和减法(低优先级)
|
||||
parseAdditionSubtraction(expr) {
|
||||
const tokens = this.tokenizeExpressionSmart(expr, ['+', '-']);
|
||||
let result = this.evaluateToken(tokens[0]);
|
||||
|
||||
for (let i = 1; i < tokens.length; i += 2) {
|
||||
const operator = tokens[i];
|
||||
const operand = this.evaluateToken(tokens[i + 1]);
|
||||
|
||||
if (operator === '+') {
|
||||
result += operand;
|
||||
} else if (operator === '-') {
|
||||
result -= operand;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 智能分词器,考虑到负号可能是一元运算符
|
||||
tokenizeExpressionSmart(expr, operators) {
|
||||
lexArithmetic(expr) {
|
||||
const tokens = [];
|
||||
let current = '';
|
||||
let i = 0;
|
||||
const isIdChar = (ch) => /[a-zA-Z0-9_.]/.test(ch);
|
||||
|
||||
while (i < expr.length) {
|
||||
const char = expr[i];
|
||||
|
||||
if (operators.includes(char)) {
|
||||
// 检查是否是一元负号
|
||||
if (char === '-' && (i === 0 || operators.includes(expr[i-1]) || expr[i-1] === '(')) {
|
||||
// 这是一元负号,继续收集
|
||||
current += char;
|
||||
} else {
|
||||
// 这是二元运算符
|
||||
if (current.trim()) {
|
||||
tokens.push(current.trim());
|
||||
current = '';
|
||||
}
|
||||
tokens.push(char);
|
||||
const ch = expr[i];
|
||||
if (/\s/.test(ch)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if ('+-*/%()'.includes(ch)) {
|
||||
tokens.push({ type: ch });
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (/\d/.test(ch)) {
|
||||
let num = '';
|
||||
while (i < expr.length && /\d/.test(expr[i])) {
|
||||
num += expr[i++];
|
||||
}
|
||||
} else {
|
||||
current += char;
|
||||
tokens.push({ type: 'num', value: parseInt(num, 10) });
|
||||
continue;
|
||||
}
|
||||
if (/[a-zA-Z_]/.test(ch)) {
|
||||
let id = '';
|
||||
while (i < expr.length && isIdChar(expr[i])) {
|
||||
id += expr[i++];
|
||||
}
|
||||
if (expr[i] === '(') {
|
||||
let depth = 0;
|
||||
let call = id;
|
||||
while (i < expr.length) {
|
||||
const c = expr[i++];
|
||||
call += c;
|
||||
if (c === '(') depth++;
|
||||
else if (c === ')') {
|
||||
depth--;
|
||||
if (depth === 0) break;
|
||||
}
|
||||
}
|
||||
tokens.push({ type: 'call', value: call });
|
||||
} else {
|
||||
tokens.push({ type: 'id', value: id });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (current.trim()) {
|
||||
tokens.push(current.trim());
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
// 将表达式分解为标记
|
||||
tokenizeExpression(expr, operators) {
|
||||
const tokens = [];
|
||||
let current = '';
|
||||
peekExprToken() {
|
||||
return this._exprTokens[this._exprPos] || { type: 'eof' };
|
||||
}
|
||||
|
||||
for (let i = 0; i < expr.length; i++) {
|
||||
const char = expr[i];
|
||||
consumeExprToken() {
|
||||
return this._exprTokens[this._exprPos++] || { type: 'eof' };
|
||||
}
|
||||
|
||||
if (operators.includes(char)) {
|
||||
if (current.trim()) {
|
||||
tokens.push(current.trim());
|
||||
current = '';
|
||||
}
|
||||
tokens.push(char);
|
||||
parseAddExpr() {
|
||||
let left = this.parseMulExpr();
|
||||
while (this.peekExprToken().type === '+' || this.peekExprToken().type === '-') {
|
||||
const op = this.consumeExprToken().type;
|
||||
const right = this.parseMulExpr();
|
||||
left = op === '+' ? left + right : left - right;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
parseMulExpr() {
|
||||
let left = this.parseUnaryExpr();
|
||||
while (['*', '/', '%'].includes(this.peekExprToken().type)) {
|
||||
const op = this.consumeExprToken().type;
|
||||
const right = this.parseUnaryExpr();
|
||||
if (op === '*') {
|
||||
left *= right;
|
||||
} else if (op === '/') {
|
||||
left = right === 0 ? 0 : Math.trunc(left / right);
|
||||
} else {
|
||||
current += char;
|
||||
left %= right;
|
||||
}
|
||||
}
|
||||
|
||||
if (current.trim()) {
|
||||
tokens.push(current.trim());
|
||||
}
|
||||
|
||||
return tokens;
|
||||
return left;
|
||||
}
|
||||
|
||||
// 计算单个标记的值
|
||||
evaluateToken(token) {
|
||||
token = token.trim();
|
||||
if (!token) return 0;
|
||||
|
||||
// 如果包含乘除法或模运算,交给乘除法解析器处理
|
||||
if (token.includes('*') || token.includes('/') || token.includes('%')) {
|
||||
return this.parseMultiplicationDivision(token);
|
||||
parseUnaryExpr() {
|
||||
const type = this.peekExprToken().type;
|
||||
if (type === '-') {
|
||||
this.consumeExprToken();
|
||||
return -this.parseUnaryExpr();
|
||||
}
|
||||
if (type === '+') {
|
||||
this.consumeExprToken();
|
||||
return this.parseUnaryExpr();
|
||||
}
|
||||
return this.parsePrimaryExpr();
|
||||
}
|
||||
|
||||
// 布尔常量
|
||||
parsePrimaryExpr() {
|
||||
const token = this.peekExprToken();
|
||||
if (token.type === 'num') {
|
||||
this.consumeExprToken();
|
||||
return token.value;
|
||||
}
|
||||
if (token.type === 'id') {
|
||||
this.consumeExprToken();
|
||||
return this.evaluateAtom(token.value);
|
||||
}
|
||||
if (token.type === 'call') {
|
||||
this.consumeExprToken();
|
||||
return this.evaluateAtom(token.value);
|
||||
}
|
||||
if (token.type === '(') {
|
||||
this.consumeExprToken();
|
||||
const value = this.parseAddExpr();
|
||||
if (this.peekExprToken().type === ')') {
|
||||
this.consumeExprToken();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
debugLog(`⚠️ 无法解析标记: ${token.type}`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
evaluateAtom(token) {
|
||||
if (token === 'true') return 1;
|
||||
if (token === 'false') return 0;
|
||||
|
||||
// 数字
|
||||
if (/^-?\d+$/.test(token)) {
|
||||
return parseInt(token);
|
||||
}
|
||||
|
||||
// 变量查找
|
||||
if (this.variables.has(token)) {
|
||||
return this.variables.get(token);
|
||||
}
|
||||
|
||||
// 对象属性访问 (如 pos.x, pos.y, pos.z)
|
||||
if (token.includes('.')) {
|
||||
const [objName, propName] = token.split('.');
|
||||
if (this.variables.has(objName)) {
|
||||
@@ -2592,7 +2552,6 @@ export class CppCodeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
// 游戏API调用
|
||||
if (token.includes('player_data(')) {
|
||||
const match = token.match(/player_data\s*\(\s*"(.+?)"\s*\)/);
|
||||
if (match) return window.cppGameAPI.player_data(match[1]);
|
||||
|
||||
Reference in New Issue
Block a user