davidbonnet / astring

🌳 Tiny and fast JavaScript code generator from an ESTree-compliant AST.
https://david.bonnet.cc/astring/demo/
MIT License
1.17k stars 57 forks source link

Dropping unnecessary parentheses for binary expression with the same operator precedence #710

Open maxkoretskyi opened 2 months ago

maxkoretskyi commented 2 months ago

The library is great in that it can drop unncessary parentheses for operators with different precedence, e.g. '1+(2*3)' -> 1+2*3.

I'm wondering though, if there is any way to enable dropping parenthesis in the binary expression that has the same operator precedence? For example, the expression '1+(2+3)', in which both the parent and child node has the same operator precedence for the + operator.

import { parse } from 'acorn';
import { generate } from 'astring';

const exp = parse('1+(2+3)', { ecmaVersion: 2020 });
const n = (exp.body[0] as any).expression;

const output = generate(n);
console.log(output); // '1+(2+3)'

here ideally I'd want to get '1+2+3'.

This seems tricky, since in the case of the expression '1-(2+3)', where the operator - has the same precendence as +, the parenthesis should be preserved (it's the way the library works now).

davidbonnet commented 2 months ago

Hi @maxkoretskyi, thanks for asking this. Astring does not alter the structure of the AST it generates. It only removes parentheses if the precedence remains unchanged without them. For example, (1 + 2) + 3 and 1 + 2 + 3 are evaluated in the same order, so Astring generates the latter form, which is what you are looking for. However, 1 + (2 + 3) is evaluated differently from 1 + 2 + 3. While this difference is inconsequential for numbers, it could be significant for references or other expressions.

Therefore, I recommend updating the AST before passing it to Astring to ensure the desired output.

maxkoretskyi commented 2 months ago

thanks a lot for you answer!

For example, (1 + 2) + 3 and 1 + 2 + 3 are evaluated in the same order... However, 1 + (2 + 3) is evaluated differently from 1 + 2 + 3.

what defines that? it's not associativity ?

I recommend updating the AST before passing it to Astring to ensure the desired output.

I did a search, but couldn't find any library that allows tranformation of AST to drop parenthesis? do you maybe know any?