Open modulovalue opened 9 months ago
Let's consider the example program:
void a() {
b..c = () => 0..d;
}
In the specified grammar, a <cascadeAssignment>
has the following syntax:
<cascadeAssignment> ::= <assignmentOperator> <expressionWithoutCascade>
This implies that the specified grammar must parse a prefix of () => 0..d
using <expressionWithoutCascade>
. The language specification grammar will happily derive () => 0..d
from <expressionWithoutCascade>
, because of the rampant ambiguity introduced by <functionExpression>
.
The grammar in Dart.g will also parse a prefix of () => 0..d
using <expressionWithoutCascade>
, but in this case we will use <functionExpressionWithoutCascade>
to parse the body (a prefix of 0..d
), which yields 0
.
So, indeed, the Dart.g grammar will give rise to a parsing with the structure (b..c = () => 0)..d
, and the grammar in the language specification will only arrive at b..c = (() => 0..d)
because it will parse () => 0..d
as an "expression without cascade".
I think the construct () => 0..d
is not a particularly convincing "expression without cascade", so the intended parse is probably going to be as follows:
void main() {
// Likely intended structure:
var v1 = b
..c = () => 0
..d;
// Less likely:
var v2 = b
..c = (() => 0..d);
}
I think this serves as yet another argument in favor of doing what Dart.g has done for years (that is, changing <functionExpression>
to <functionPrimary>
in <primary>
, adding <functionExpression>
to <expression>
, and adding <functionExpressionWithoutCascade>
to <expressionWithoutCascade>
; finally, changing <functionExpression>
and the one without cascades such that they only derive =>
functions).
I'll transfer this issue to the language repo, given that there is no reasonable solution (I think) without grammar changes.
@dart-lang/language-team, WDYT? Are we finally coming around to a solution to this ambiguity issue in the grammar?
The underlying issue with <functionExpression>
is described here.
The short version is that <primary>
is wildly ambiguous because it contains <functionExpression>
. We can fix this by changing the grammar such that <primary>
only derives {}
function literals, and =>
function literals are derived from <expression>
or <expressionWithoutCascade>
.
WDYT? Are we finally coming around to a solution to this ambiguity issue in the grammar?
SGTM.
Also, the cascade syntax is still bad. Even if we disambiguate the grammar for our parsers, actual humans will still be hopeless confused when presented with code like a..b = () => c..d
or, hell, even a..b = c..d
.
Consider the following program:
Which leads to the following parse trees:
It looks like the analyzer and a Dart.g-based parser disagree on the expression that
..d
is meant to belong to.The analyzer appears to assume the following:
And the Dart.g grammar appears to assume the following: