🐛 Fix case like y=80%*x painting wrongly

This commit is contained in:
2025-09-14 14:46:09 +08:00
parent d26c29613b
commit d652df407f
4 changed files with 52 additions and 14 deletions

View File

@@ -43,22 +43,26 @@ class Parser {
Expr parseMul() {
var expr = parsePow();
skipSpaces();
while (!isEnd && (current == '*' || current == '/')) {
while (!isEnd &&
(current == '*' ||
current == '/' ||
current == '%' ||
RegExp(r'[a-zA-Z\d]').hasMatch(current) ||
current == '(')) {
if (current == '*' || current == '/') {
var op = current;
eat();
var right = parsePow();
if (op == '*') {
expr = MulExpr(expr, right);
} else {
expr = DivExpr(expr, right);
}
skipSpaces();
}
// Handle percentage operator
skipSpaces();
if (!isEnd && current == '%') {
expr = op == '*' ? MulExpr(expr, right) : DivExpr(expr, right);
} else if (current == '%') {
eat();
expr = PercentExpr(expr);
} else {
// implicit multiplication
var right = parsePow();
expr = MulExpr(expr, right);
}
skipSpaces();
}
return expr;
}

View File

@@ -48,7 +48,30 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
final input = _controller.text.trim();
final normalizedInput = input.replaceAll(' ', '');
// 使用solver检查是否为可绘制的函数表达
// 如果当前已经是函数模式,保持函数模
if (_isFunctionMode) {
// 重新检查表达式是否仍然可绘制(以防用户修改了表达式)
if (_solverService.isGraphableExpression(normalizedInput)) {
// 保持在函数模式,不做任何改变
return;
} else {
// 表达式不再可绘制,切换回普通模式
setState(() {
_isFunctionMode = false;
});
}
}
// 检查是否为函数表达式优先使用简单y=检测)
if (normalizedInput.toLowerCase().startsWith('y=')) {
setState(() {
_isFunctionMode = true;
_result = null;
});
return;
}
// 备用检查使用solver进行更复杂的表达式检测
if (_solverService.isGraphableExpression(normalizedInput)) {
setState(() {
_isFunctionMode = true;
@@ -57,6 +80,7 @@ class _CalculatorHomePageState extends State<CalculatorHomePage> {
return;
}
// 普通表达式求解
setState(() {
_isFunctionMode = false;
_isLoading = true;

View File

@@ -54,6 +54,12 @@ class _GraphCardState extends State<GraphCard> {
(match) => '${match.group(1)}*${match.group(2)}',
);
// 在 % 和变量或数字之间插入乘号 (如 80%x -> 80%*x)
functionExpr = functionExpr.replaceAllMapped(
RegExp(r'%([a-zA-Z\d])'),
(match) => '%*${match.group(1)}',
);
// 解析表达式
final parser = Parser(functionExpr);
final expr = parser.parse();

View File

@@ -130,6 +130,10 @@ void main() {
// 测试无y=前缀的表达式
final noPrefix = solver.prepareFunctionForGraphing('(x-1)(x+3)');
expect(noPrefix, 'x^2+2x-3');
// 测试百分比表达式
final percentExpr = solver.prepareFunctionForGraphing('y=80%x');
expect(percentExpr, '80%x');
});
});
}