Skip to content

Commit a890e9d

Browse files
committed
Expose can_begin_expr as Expr::peek
1 parent 12f068c commit a890e9d

File tree

1 file changed

+37
-26
lines changed

1 file changed

+37
-26
lines changed

src/expr.rs

+37-26
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
use crate::attr::Attribute;
22
#[cfg(all(feature = "parsing", feature = "full"))]
33
use crate::error::Result;
4+
#[cfg(feature = "parsing")]
5+
use crate::ext::IdentExt as _;
46
#[cfg(feature = "full")]
57
use crate::generics::BoundLifetimes;
68
use crate::ident::Ident;
7-
#[cfg(feature = "full")]
9+
#[cfg(any(feature = "parsing", feature = "full"))]
810
use crate::lifetime::Lifetime;
911
use crate::lit::Lit;
1012
use crate::mac::Macro;
1113
use crate::op::{BinOp, UnOp};
12-
#[cfg(all(feature = "parsing", feature = "full"))]
14+
#[cfg(feature = "parsing")]
1315
use crate::parse::ParseStream;
1416
#[cfg(feature = "full")]
1517
use crate::pat::Pat;
@@ -889,6 +891,36 @@ impl Expr {
889891
parsing::parse_with_earlier_boundary_rule(input)
890892
}
891893

894+
/// Returns whether the next token in the parse stream is one that might
895+
/// possibly form the beginning of an expr.
896+
///
897+
/// This classification is a load-bearing part of the grammar of some Rust
898+
/// expressions, notably `return` and `break`. For example `return < …` will
899+
/// never parse `<` as a binary operator regardless of what comes after,
900+
/// because `<` is a legal starting token for an expression and so it's
901+
/// required to be continued as a return value, such as `return <Struct as
902+
/// Trait>::CONST`. Meanwhile `return > …` treats the `>` as a binary
903+
/// operator because it cannot be a starting token for any Rust expression.
904+
#[cfg(feature = "parsing")]
905+
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
906+
pub fn peek(input: ParseStream) -> bool {
907+
input.peek(Ident::peek_any) // value name or keyword
908+
|| input.peek(token::Paren) // tuple
909+
|| input.peek(token::Bracket) // array
910+
|| input.peek(token::Brace) // block
911+
|| input.peek(Lit) // literal
912+
|| input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
913+
|| input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
914+
|| input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
915+
|| input.peek(Token![|]) && !input.peek(Token![|=]) // closure
916+
|| input.peek(Token![&]) && !input.peek(Token![&=]) // reference
917+
|| input.peek(Token![..]) // range
918+
|| input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
919+
|| input.peek(Token![::]) // absolute path
920+
|| input.peek(Lifetime) // labeled loop
921+
|| input.peek(Token![#]) // expression attributes
922+
}
923+
892924
#[cfg(all(feature = "parsing", feature = "full"))]
893925
pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
894926
match self {
@@ -1147,8 +1179,6 @@ pub(crate) mod parsing {
11471179
FieldValue, Index, Member,
11481180
};
11491181
#[cfg(feature = "full")]
1150-
use crate::ext::IdentExt as _;
1151-
#[cfg(feature = "full")]
11521182
use crate::generics::BoundLifetimes;
11531183
use crate::ident::Ident;
11541184
#[cfg(feature = "full")]
@@ -1266,25 +1296,6 @@ pub(crate) mod parsing {
12661296
}
12671297
}
12681298

1269-
#[cfg(feature = "full")]
1270-
fn can_begin_expr(input: ParseStream) -> bool {
1271-
input.peek(Ident::peek_any) // value name or keyword
1272-
|| input.peek(token::Paren) // tuple
1273-
|| input.peek(token::Bracket) // array
1274-
|| input.peek(token::Brace) // block
1275-
|| input.peek(Lit) // literal
1276-
|| input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
1277-
|| input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
1278-
|| input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
1279-
|| input.peek(Token![|]) && !input.peek(Token![|=]) // closure
1280-
|| input.peek(Token![&]) && !input.peek(Token![&=]) // reference
1281-
|| input.peek(Token![..]) // range notation
1282-
|| input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
1283-
|| input.peek(Token![::]) // global path
1284-
|| input.peek(Lifetime) // labeled loop
1285-
|| input.peek(Token![#]) // expression attributes
1286-
}
1287-
12881299
#[cfg(feature = "full")]
12891300
fn parse_expr(
12901301
input: ParseStream,
@@ -2439,7 +2450,7 @@ pub(crate) mod parsing {
24392450
attrs: Vec::new(),
24402451
return_token: input.parse()?,
24412452
expr: {
2442-
if can_begin_expr(input) {
2453+
if Expr::peek(input) {
24432454
Some(input.parse()?)
24442455
} else {
24452456
None
@@ -2477,7 +2488,7 @@ pub(crate) mod parsing {
24772488
attrs: Vec::new(),
24782489
yield_token: input.parse()?,
24792490
expr: {
2480-
if can_begin_expr(input) {
2491+
if Expr::peek(input) {
24812492
Some(input.parse()?)
24822493
} else {
24832494
None
@@ -2690,7 +2701,7 @@ pub(crate) mod parsing {
26902701
}
26912702

26922703
input.advance_to(&ahead);
2693-
let expr = if can_begin_expr(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2704+
let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
26942705
Some(input.parse()?)
26952706
} else {
26962707
None

0 commit comments

Comments
 (0)