@@ -163,19 +163,15 @@ function findBinaryFunction(tokens: ExprElement[], fn: string) {
163163 }
164164}
165165
166- // When all minuses have been parsed as functions (i.e. an `ExprFunction` with a single argument), we find binary
167- // functions by looking for a minus function preceded by a number or variable .
168- function findBinaryLeadingMinus ( tokens : ExprElement [ ] ) {
166+ // Some minuses have been parsed as functions (i.e. an `ExprFunction` with a single argument).
167+ // If they are preceded by something, we need to treat the expression as a unary minus .
168+ function findBinaryMinusFunctions ( tokens : ExprElement [ ] ) {
169169 for ( let i = 1 ; i < tokens . length ; i ++ ) {
170170 const token = tokens [ i ] ;
171171 if ( token instanceof ExprFunction && token . fn === '−' ) {
172172 const a = tokens [ i - 1 ] ;
173173 const b = token . args [ 0 ] ;
174174
175- if ( a instanceof ExprOperator ) {
176- throw ExprError . consecutiveOperators ( a . o , token . fn ) ;
177- }
178-
179175 const args = [ removeBrackets ( a ) , removeBrackets ( b ) ] ;
180176 tokens . splice ( i - 1 , 2 , new ExprFunction ( '−' , args ) ) ;
181177 i -= 1 ;
@@ -334,24 +330,30 @@ export function collapseTerm(tokens: ExprElement[]): ExprElement {
334330 }
335331 }
336332
337- // Replace all operator minuses with functions. Each function takes only one argument, the next token in sequence.
338- for ( let i = 0 ; i < tokens . length - 1 ; i ++ ) {
333+ // Replace all operator minuses, not preceded by numbers, with functions. Each function takes only one argument,
334+ // the next token in sequence.
335+ // Move backwards to correctly handle nested expressions. For example, " - - a" should be parsed as function "−" with
336+ // argument [function "-" with argument ["a"]].
337+ for ( let i = tokens . length - 1 ; i >= 0 ; i -- ) {
339338 // Treat ± as a minus.
340339 if ( isOperator ( tokens [ i ] , '− ±' ) ) {
340+ if ( tokens [ i - 1 ] instanceof ExprNumber ) continue ;
341+
341342 tokens . splice ( i , 2 , new ExprFunction ( '−' , [ tokens [ i + 1 ] ] ) ) ;
342343 }
343344 }
344345
345346 // Match multiplication operators.
346347 tokens = findAssociativeFunction ( tokens , '× * ·' , true ) ;
347348
348- // Match - operators, nested within the replaced minus functions.
349- findBinaryLeadingMinus ( tokens ) ;
349+ findBinaryFunction ( tokens , '- −' ) ;
350350
351351 // Match + operators.
352352 if ( isOperator ( tokens [ 0 ] , '+' ) ) tokens = tokens . slice ( 1 ) ;
353353 tokens = findAssociativeFunction ( tokens , '+' ) ;
354354
355+ findBinaryMinusFunctions ( tokens ) ;
356+
355357 if ( tokens . length > 1 ) throw ExprError . invalidExpression ( ) ;
356358 return tokens [ 0 ] ;
357359}
0 commit comments