Open pnkfelix opened 8 years ago
FYI, this covers more than predicates:
// Does it cover `let x = y` (a predicate?) or just `y`?
while let x = y {
}
// no predicate in sight
for a in b {
}
@Stebalien I am not quite sure how to interpret your comment.
For example, while let x = y { ... }
is not the result of composing while <expr> { ... }
with some internal let x = y
... let x = y
is not an expression. Instead, while let
is its own expression construct in Rust's grammar.
Sorry, I meant to write "covers more than predicates" instead of "covers more than pred". My point was that neither y
nor b
are predicates (although let x = y
technically acts like a predicate but that's not really that important) so we'll need to think of some better name. However, after re-reading your post, you clearly realized this so I'm just going to shut up now...
@Stebalien ah yes; the name pred
may not be ideal, since in cases like the ones you name, its not that the expression in question returns a boolean, but rather e.g. for while let
returns an enum (and we're matching a particular variant), or for for a in b
, the b
needs to return something that implements IntoIterator
-- so the connection to pred
there is certainly tenuous at best.
Really the most attractive thing about the token pred
to me is just that it is short. I don't know if it really has all that much else going for it...
I might be having a brain fart, but what situations in the current grammar have expressions followed by {
? I guess struct literals are path { ... }
, and a path is an expr. Is that it?
In terms of bikeshedding the name:
pred
if $p:pred { $($body:tt)* }
nbe
or nbex
tt
is precedent for using acronyms as fragment specifierssrc/grammar
refers to this construct as expr_nostruct
, if I'm reading it right, so another acronym could be exns
Another crazy idea is "silent adaptation" -- if you put $e:expr {
in a macro rule, it becomes a matcher for a moelarry
instead of a full expr
. This is probably a bad idea.
if you put
$e:expr {
in a macro rule, it becomes a matcher for a moelarry instead of a full expr. This is probably a bad idea
Yeah, it probably is bad; consider e.g. the macro pattern $a:expr $($b:expr)* { stuff }*
. Is the $b
still an nbe
? If so, how about $a
?
@pnkfelix IMO, that's unambiguous. $a
is an nbe
because it might be followed by an expression (which could start with {
). $b
is an nbe
because it's repeated.
@Stebalien in that case I think we would be better served by a separately named fragment class. Having the potentially matched forms of a NT depend on patterns potentially arbitrarily far ahead in the macro LHS seems bad
@pnkfelix
potentially arbitrarily far ahead
Unless I'm mistaken, it only depends on the next pattern. However, I'm certainly not opposed to making it explicit (I just can't think of a name).
Sorry I think my example failed to express what I'm concerned about; look e.g. at:
$a:expr $(, $b:expr )* { stuff }
(Where I have now added a comma before $b so that we don't worry the two exprs right next to each other)
In this case, a {
may still come right after the $a, but the reader must look at the whole of the LHS to see it. That's what I am concerned with.
In this case, a `
Steven Allen
As part of this RFC (or maybe a separate one), can we expand a couple of follow sets with things they should logically already include, for macro writing convenience?
OpenDelim(Bracket)
is already in FOLLOW(ty/path)
, but Interpolated(NtBlock(_))
should be as well.FOLLOW(pat)
should include Colon
.Did I miss any?
@durka those sounds like good things, but I would put them in a separate RFC. Actually I'd put them into an amendment of the macro-future proofing RFC -- that is likely to ensure that it gets approved faster.
See #1494.
(spawned off of https://github.com/rust-lang/rfcs/pull/1384#issuecomment-160165525 )
I've been leaving links to the above comment in all sorts of places, so I finally decided it was time to open an RFC issue for this idea.
Namely, to add some fragment class, which I'll call
pred
for now, that represents "the subset of expressions that do not have{
in their follow set, and thus the presence of a{
as the next token tells the parser that it is definitely done parsing the expression."In particular, this is the subset of expressions that we use for the test in an
if test { then } else { other }
Such an fragment class would be useful for writing
macro_rules!
that naturally want a{
to come after them in the input pattern.We used to superficially "allow" such macros, but they didn't actually work in general; see https://github.com/rust-lang/rust/issues/26739