Skip to content
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

Should a || b || c and a || (b || c) be parsed to the same AST? #246

Open
thorn0 opened this issue Mar 3, 2021 · 10 comments
Open

Should a || b || c and a || (b || c) be parsed to the same AST? #246

thorn0 opened this issue Mar 3, 2021 · 10 comments

Comments

@thorn0
Copy link

thorn0 commented Mar 3, 2021

Seems like this hasn't been discussed yet. Effectively, there is no difference between these two expressions, but currently JS parsers parse them differently, which doesn't serve any good purpose and conflicts with the general approach of ESTree that insignificant parentheses shouldn't be reflected in the AST. Can be something done about this? Or is it too late?

@RReverser
Copy link
Member

I think this would be a significant breaking change to split up commutative operations vs non-commutative in separate nodes. It shouldn't be hard to rebalance tree afterwards if it's something you need though. What is your use-case?

@bradzacher
Copy link

but currently JS parsers parse them differently

Could you give an example of differences?

@thorn0
Copy link
Author

thorn0 commented Mar 3, 2021

@bradzacher I mean the result of parsing these two expressions is different whereas e.g. for a + b + c and (a + b) + c it is not.

{
  "type": "LogicalExpression",
  "left": {
    "type": "LogicalExpression",
    "left": { "type": "Identifier", "name": "a" },
    "right": { "type": "Identifier", "name": "b" }
  },
  "right": { "type": "Identifier", "name": "c" }
}

vs

{
  "type": "LogicalExpression",
  "left": { "type": "Identifier", "name": "a" },
  "right": {
    "type": "LogicalExpression",
    "left": { "type": "Identifier", "name": "b" },
    "right": { "type": "Identifier", "name": "c" }
  }
}

@RReverser What will break if parsers start ignoring these parentheses? I don't really have a use case (I'd be glad to remove the rebalancing from Prettier though). I just see a conceptual inconsistency here.

@bradzacher
Copy link

I mean the result of parsing these two expressions is different whereas e.g. for a + b + c and (a + b) + c it is not.

If you parse a binary expression with parens in the same location as your logic expression example (a + (b + c)), it causes the same rough AST structure as the equivalent logic expression.

https://astexplorer.net/#/gist/4b9d37f1cec26a191eded3386f330868/6662eea8c0f5754f38802fd2634655ccd00aebac

@bradzacher
Copy link

My understanding of this is that it's just easier for parsers to follow one set of logic.

The logic of "parse in source order pairings, but group by parens first" is simpler to build, and easier to achieve consistency on rather than "parse in source order pairings, but group by parens first; unless the precedence of the operator is such that the parens are unnecessary"

Also for most use cases I'd assume that they don't care about the commutativity of the expressions.

@thorn0
Copy link
Author

thorn0 commented Mar 3, 2021

This is not really about precedence or commutativity (associativity probably?). Rather about short-circuiting. Because it's short-circuiting that makes these two expressions equivalent. Note that a + (b + c) isn't equivalent to a + b + c.

@bradzacher
Copy link

Note that a + (b + c) isn't equivalent to a + b + c.

How so? What operations are applied to additions that would change the outcome based on parentheses?

@thorn0
Copy link
Author

thorn0 commented Mar 3, 2021

'1'+(2+3)
"15"
'1'+2+3
"123"

(1 + 1e100) + -1e100 
0
1 + (1e100 + -1e100)
1

@sebiniemann
Copy link
Contributor

sebiniemann commented Jan 21, 2022

This behaviour is also not JavaScript-specific. Standard IEEE 754 floating-point arithmetic is simply not associative due to rounding errors.

I think this issue could therefore be closed because a + (b + c) and (a + b) + c are different expressions (in the sense that they could have different results).

@thorn0
Copy link
Author

thorn0 commented Feb 3, 2022

The issue is about short-circuit operators: ||, &&, ??, not about +.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants