fix: treating unary minus in calcString (#784)

# PR Checklist
- [ ] Have you checked if it works normally in all models? *Ignore this
if it doesn't use models.*
- [ ] Have you checked if it works normally in all web, local, and node
hosted versions? If it doesn't, have you blocked it in those versions?
- [ ] Have you added type definitions?

# Description
It has been reported that calcString incorrectly calculates expressions
when a negative number appears on the right-hand side. This pull request
addresses this issue.
This commit is contained in:
kwaroran
2025-03-17 16:02:22 +09:00
committed by GitHub

View File

@@ -17,6 +17,7 @@ function toRPN(expression:string) {
'≤': {precedence: 1, associativity: 'Left'}, '≤': {precedence: 1, associativity: 'Left'},
'≥': {precedence: 1, associativity: 'Left'}, '≥': {precedence: 1, associativity: 'Left'},
'=': {precedence: 1, associativity: 'Left'}, '=': {precedence: 1, associativity: 'Left'},
'≠': {precedence: 1, associativity: 'Left'},
'!': {precedence: 5, associativity: 'Right'}, '!': {precedence: 5, associativity: 'Right'},
}; };
const operatorsKeys = Object.keys(operators); const operatorsKeys = Object.keys(operators);
@@ -27,7 +28,11 @@ function toRPN(expression:string) {
let lastToken = '' let lastToken = ''
for(let i = 0; i < expression.length; i++) { for(let i = 0; i < expression.length; i++) {
if(operatorsKeys.includes(expression[i])) { const char = expression[i]
if (char === '-' && (i === 0 || operatorsKeys.includes(expression[i - 1]) || expression[i - 1] === '(')) {
lastToken += char
}
else if (operatorsKeys.includes(char)) {
if(lastToken !== '') { if(lastToken !== '') {
expression2.push(lastToken) expression2.push(lastToken)
} }
@@ -35,10 +40,10 @@ function toRPN(expression:string) {
expression2.push('0') expression2.push('0')
} }
lastToken = '' lastToken = ''
expression2.push(expression[i]) expression2.push(char)
} }
else{ else{
lastToken += expression[i] lastToken += char
} }
} }
@@ -94,6 +99,7 @@ function calculateRPN(expression:string) {
case '≤': stack.push(a <= b ? 1 : 0); break; case '≤': stack.push(a <= b ? 1 : 0); break;
case '≥': stack.push(a >= b ? 1 : 0); break; case '≥': stack.push(a >= b ? 1 : 0); break;
case '=': stack.push(a === b ? 1 : 0); break; case '=': stack.push(a === b ? 1 : 0); break;
case '≠': stack.push(a !== b ? 1 : 0); break;
case '!': stack.push(b ? 0 : 1); break; case '!': stack.push(b ? 0 : 1); break;
} }
} }
@@ -121,7 +127,14 @@ function executeRPNCalculation(text:string) {
return "0" return "0"
} }
return parsed.toString() return parsed.toString()
}).replace(/&&/g, '&').replace(/\|\|/g, '|').replace(/<=/g, '≤').replace(/>=/g, '≥').replace(/==/g, '=').replace(/null/gi, '0') })
.replace(/&&/g, '&')
.replace(/\|\|/g, '|')
.replace(/<=/g, '≤')
.replace(/>=/g, '≥')
.replace(/==/g, '=')
.replace(/!=/g, '≠')
.replace(/null/gi, '0')
const expression = toRPN(text); const expression = toRPN(text);
const evaluated = calculateRPN(expression); const evaluated = calculateRPN(expression);
return evaluated return evaluated