|
1 | 1 | use crate::attr::Attribute;
|
2 | 2 | #[cfg(all(feature = "parsing", feature = "full"))]
|
3 | 3 | use crate::error::Result;
|
| 4 | +#[cfg(feature = "parsing")] |
| 5 | +use crate::ext::IdentExt as _; |
4 | 6 | #[cfg(feature = "full")]
|
5 | 7 | use crate::generics::BoundLifetimes;
|
6 | 8 | use crate::ident::Ident;
|
7 |
| -#[cfg(feature = "full")] |
| 9 | +#[cfg(any(feature = "parsing", feature = "full"))] |
8 | 10 | use crate::lifetime::Lifetime;
|
9 | 11 | use crate::lit::Lit;
|
10 | 12 | use crate::mac::Macro;
|
11 | 13 | use crate::op::{BinOp, UnOp};
|
12 |
| -#[cfg(all(feature = "parsing", feature = "full"))] |
| 14 | +#[cfg(feature = "parsing")] |
13 | 15 | use crate::parse::ParseStream;
|
14 | 16 | #[cfg(feature = "full")]
|
15 | 17 | use crate::pat::Pat;
|
@@ -889,6 +891,36 @@ impl Expr {
|
889 | 891 | parsing::parse_with_earlier_boundary_rule(input)
|
890 | 892 | }
|
891 | 893 |
|
| 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 | + |
892 | 924 | #[cfg(all(feature = "parsing", feature = "full"))]
|
893 | 925 | pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
|
894 | 926 | match self {
|
@@ -1147,8 +1179,6 @@ pub(crate) mod parsing {
|
1147 | 1179 | FieldValue, Index, Member,
|
1148 | 1180 | };
|
1149 | 1181 | #[cfg(feature = "full")]
|
1150 |
| - use crate::ext::IdentExt as _; |
1151 |
| - #[cfg(feature = "full")] |
1152 | 1182 | use crate::generics::BoundLifetimes;
|
1153 | 1183 | use crate::ident::Ident;
|
1154 | 1184 | #[cfg(feature = "full")]
|
@@ -1266,25 +1296,6 @@ pub(crate) mod parsing {
|
1266 | 1296 | }
|
1267 | 1297 | }
|
1268 | 1298 |
|
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 |
| - |
1288 | 1299 | #[cfg(feature = "full")]
|
1289 | 1300 | fn parse_expr(
|
1290 | 1301 | input: ParseStream,
|
@@ -2439,7 +2450,7 @@ pub(crate) mod parsing {
|
2439 | 2450 | attrs: Vec::new(),
|
2440 | 2451 | return_token: input.parse()?,
|
2441 | 2452 | expr: {
|
2442 |
| - if can_begin_expr(input) { |
| 2453 | + if Expr::peek(input) { |
2443 | 2454 | Some(input.parse()?)
|
2444 | 2455 | } else {
|
2445 | 2456 | None
|
@@ -2477,7 +2488,7 @@ pub(crate) mod parsing {
|
2477 | 2488 | attrs: Vec::new(),
|
2478 | 2489 | yield_token: input.parse()?,
|
2479 | 2490 | expr: {
|
2480 |
| - if can_begin_expr(input) { |
| 2491 | + if Expr::peek(input) { |
2481 | 2492 | Some(input.parse()?)
|
2482 | 2493 | } else {
|
2483 | 2494 | None
|
@@ -2690,7 +2701,7 @@ pub(crate) mod parsing {
|
2690 | 2701 | }
|
2691 | 2702 |
|
2692 | 2703 | 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)) { |
2694 | 2705 | Some(input.parse()?)
|
2695 | 2706 | } else {
|
2696 | 2707 | None
|
|
0 commit comments