-
Add
Expr::parse_without_eager_brace
to parse expressions in ambiguous syntactic position.Rust grammar has an ambiguity where braces sometimes turn a path expression into a struct initialization and sometimes do not. In the following code, the expression
S {}
is one expression. Presumably there is an empty structstruct S {}
defined somewhere which it is instantiating.let _ = *S {}; // parsed by rustc as: `*(S {})`
We would want to parse the above using
Expr::parse
after the=
token.But in the following,
S {}
is not a struct init expression.if *S {} {} // parsed by rustc as: // // if (*S) { // /* empty block */ // } // { // /* another empty block */ // }
For that reason we would want to parse if-conditions using
Expr::parse_without_eager_brace
after theif
token. Same for similar syntactic positions such as the condition expr after awhile
token or the expr at the top of amatch
.The Rust grammar's choices around which way this ambiguity is resolved at various syntactic positions is fairly arbitrary. Really either parse behavior could work in most positions, and language designers just decide each case based on which is more likely to be what the programmer had in mind most of the time.
if return S {} {} // parsed by rustc as: // // if (return (S {})) { // } // // but could equally well have been this other arbitrary choice: // // if (return S) { // } // {}
Note the grammar ambiguity on trailing braces is distinct from precedence and is not captured by assigning a precedence level to the braced struct init expr in relation to other operators. This can be illustrated by
return 0..S {}
vsmatch 0..S {}
. The former parses asreturn (0..(S {}))
implying tighter precedence for struct init than..
, while the latter parses asmatch (0..S) {}
implying tighter precedence for..
than struct init, a contradiction.