-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix(parser): correct pure percent addition and preserve relative perc… #3573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
|
Thanks so much for your submission! Sorry it's taken a few days to get to it.
You didn't put in a test on this case -- is your proposed parse
? I will admit to some concern that the code added to the parser is intricate and may make an already fragile hand-written parser noticeably more tricky to navigate. I will continue to review the PR -- perhaps your solution is how we will need to go to solve this (I would love to solve it once and for all, since it has been a recurring thorn in mathjs' side). The collection of tests is great, we should extend them even more to include as many cases as we can make a reasonable decision on the interpretation of, if possible. |
|
On: I do not think these are the correct/desired parses/behaviors. It seems to me that So your two examples should be 65 and 130, respectively. |
|
As the items I raised above for this PR motivated me to give the alternative proposal of making |
|
@philpeng1 did you see the feedback of Glen? |
…ent semantics; add tests
…etry; update grouping/ambiguous tests
fcca5b3 to
6ba0d3b
Compare
|
hi, sorry for the late response! Been dealing with some other stuff. Also, another apology for the messy commits.
|
Fixes #3563
Summary
Problem
Pure percent sums add arithmetically.
A ± B% keeps the existing relative semantics when A is not a pure-percent expression (e.g., numbers/variables/units).
Do not break modulo (%) or other operators.
Changes
Added helper isPurePercentageExpression to identify pure percentage expressions, including nested parentheses, unary +/- wrappers, and add/sub trees.
Prefer unary percent for the RHS when the LHS is a pure-percent sum by setting a temporary parser flag (state.preferUnaryPercentAfterPlus). This prevents mis-parsing % as modulo in chains like 10% + 20% + x.
Retain “relative percent” semantics for non-percent LHS by transforming A ± B% into A ± (A * B%) only when the LHS is not pure percent.
Guard parseMultiplyDivideModulus against creating mod (%) when we are in a context that must treat the upcoming % as unary percent.
Convert a misparsed “mod” shape like A % (B%) directly followed by + or - into unary percentage on A (A/100), matching the intended semantics.
Tests (test/unit-tests/expression/parse.test.js):
Added/adjusted coverage for:
Pure percent arithmetic and chaining:
10% + 20%, 10% - 20%, 10% + 20% + 30%, 10% + 50% - 20%, etc.
Relative percent on numbers and variables:
50 + 20% + 10% == 66
x + 20% + 10%, x - 10% - 20%
Grouping and associativity:
10% + 20% + x
(10%) + (20%), (10% + 20%) + 30%, 10% + (20% + 30%)
Multiplication with grouped percents:
x * (10% + 20%)
Units with % on the right:
10 cm + 20% == 12 cm
Modulo/unary interactions remain valid:
100-3% (unary %)
3%-100 (mod)
11%-3 (mod with bitwise-not)
Behavioral notes
I had a lotta fun trying to solve this issue. I’m happy to adjust implementation details, test coverage, or semantics per maintainer feedback and coding style preferences.