Skip to content

Commit

Permalink
Extract non-full expr scanner to module
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Nov 2, 2024
1 parent ceaf4d6 commit 7c102c3
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 80 deletions.
83 changes: 3 additions & 80 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ pub(crate) mod parsing {
use crate::parse::discouraged::Speculative as _;
use crate::parse::{Parse, ParseStream};
use crate::restriction::{FieldMutability, Visibility};
#[cfg(not(feature = "full"))]
use crate::scan_expr::scan_expr;
use crate::token;
use crate::ty::Type;
use crate::verbatim;
Expand Down Expand Up @@ -276,7 +278,7 @@ pub(crate) mod parsing {
let mut discriminant: Result<Expr> = ahead.parse();
if discriminant.is_ok() {
input.advance_to(&ahead);
} else if scan_lenient_discriminant(input).is_ok() {
} else if scan_expr(input).is_ok() {
discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input)));
}
discriminant?
Expand All @@ -294,85 +296,6 @@ pub(crate) mod parsing {
}
}

#[cfg(not(feature = "full"))]
pub(crate) fn scan_lenient_discriminant(input: ParseStream) -> Result<()> {
use crate::expr::Member;
use crate::lifetime::Lifetime;
use crate::lit::Lit;
use crate::lit::LitFloat;
use crate::op::{BinOp, UnOp};
use crate::path::{self, AngleBracketedGenericArguments};
use proc_macro2::Delimiter::{self, Brace, Bracket, Parenthesis};

let consume = |delimiter: Delimiter| {
Result::unwrap(input.step(|cursor| match cursor.group(delimiter) {
Some((_inside, _span, rest)) => Ok((true, rest)),
None => Ok((false, *cursor)),
}))
};

macro_rules! consume {
[$token:tt] => {
input.parse::<Option<Token![$token]>>().unwrap().is_some()
};
}

let mut initial = true;
let mut depth = 0usize;
loop {
if initial {
if consume![&] {
initial = consume![mut] || !consume![raw] || consume![const] || consume![mut];
} else if consume![if] || consume![match] || consume![while] {
depth += 1;
} else if input.parse::<Option<Lit>>()?.is_some()
|| (consume(Brace) || consume(Bracket) || consume(Parenthesis))
|| (consume![async] || consume![const] || consume![loop] || consume![unsafe])
&& (consume(Brace) || break)
{
initial = false;
} else if consume![let] {
while !consume![=] {
if !((consume![|] || consume![ref] || consume![mut] || consume![@])
|| (consume![!] || input.parse::<Option<Lit>>()?.is_some())
|| (consume![..=] || consume![..] || consume![&] || consume![_])
|| (consume(Brace) || consume(Bracket) || consume(Parenthesis)))
{
path::parsing::qpath(input, true)?;
}
}
} else if input.parse::<Option<Lifetime>>()?.is_some() && !consume![:] {
break;
} else if input.parse::<UnOp>().is_err() {
path::parsing::qpath(input, true)?;
initial = consume![!] || depth == 0 && input.peek(token::Brace);
}
} else if input.is_empty() || input.peek(Token![,]) {
return Ok(());
} else if depth > 0 && consume(Brace) {
if consume![else] && !consume(Brace) {
initial = consume![if] || break;
} else {
depth -= 1;
}
} else if input.parse::<BinOp>().is_ok() || (consume![..] | consume![=]) {
initial = true;
} else if consume![.] {
if input.parse::<Option<LitFloat>>()?.is_none()
&& (input.parse::<Member>()?.is_named() && consume![::])
{
AngleBracketedGenericArguments::do_parse(None, input)?;
}
} else if consume![as] {
input.parse::<Type>()?;
} else if !(consume(Brace) || consume(Bracket) || consume(Parenthesis)) {
break;
}
}

Err(input.error("unsupported expression"))
}

#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for FieldsNamed {
fn parse(input: ParseStream) -> Result<Self> {
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,9 @@ pub use crate::restriction::{FieldMutability, VisRestricted, Visibility};

mod sealed;

#[cfg(all(feature = "parsing", feature = "derive", not(feature = "full")))]
mod scan_expr;

mod span;

#[cfg(all(feature = "parsing", feature = "printing"))]
Expand Down
80 changes: 80 additions & 0 deletions src/scan_expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use crate::expr::Member;
use crate::lifetime::Lifetime;
use crate::lit::Lit;
use crate::lit::LitFloat;
use crate::op::{BinOp, UnOp};
use crate::parse::{ParseStream, Result};
use crate::path::{self, AngleBracketedGenericArguments};
use crate::token;
use crate::ty::Type;
use proc_macro2::Delimiter::{self, Brace, Bracket, Parenthesis};

pub(crate) fn scan_expr(input: ParseStream) -> Result<()> {
let consume = |delimiter: Delimiter| {
Result::unwrap(input.step(|cursor| match cursor.group(delimiter) {
Some((_inside, _span, rest)) => Ok((true, rest)),
None => Ok((false, *cursor)),
}))
};

macro_rules! consume {
[$token:tt] => {
input.parse::<Option<Token![$token]>>().unwrap().is_some()
};
}

let mut initial = true;
let mut depth = 0usize;
loop {
if initial {
if consume![&] {
initial = consume![mut] || !consume![raw] || consume![const] || consume![mut];
} else if consume![if] || consume![match] || consume![while] {
depth += 1;
} else if input.parse::<Option<Lit>>()?.is_some()
|| (consume(Brace) || consume(Bracket) || consume(Parenthesis))
|| (consume![async] || consume![const] || consume![loop] || consume![unsafe])
&& (consume(Brace) || break)
{
initial = false;
} else if consume![let] {
while !consume![=] {
if !((consume![|] || consume![ref] || consume![mut] || consume![@])
|| (consume![!] || input.parse::<Option<Lit>>()?.is_some())
|| (consume![..=] || consume![..] || consume![&] || consume![_])
|| (consume(Brace) || consume(Bracket) || consume(Parenthesis)))
{
path::parsing::qpath(input, true)?;
}
}
} else if input.parse::<Option<Lifetime>>()?.is_some() && !consume![:] {
break;
} else if input.parse::<UnOp>().is_err() {
path::parsing::qpath(input, true)?;
initial = consume![!] || depth == 0 && input.peek(token::Brace);
}
} else if input.is_empty() || input.peek(Token![,]) {
return Ok(());
} else if depth > 0 && consume(Brace) {
if consume![else] && !consume(Brace) {
initial = consume![if] || break;
} else {
depth -= 1;
}
} else if input.parse::<BinOp>().is_ok() || (consume![..] | consume![=]) {
initial = true;
} else if consume![.] {
if input.parse::<Option<LitFloat>>()?.is_none()
&& (input.parse::<Member>()?.is_named() && consume![::])
{
AngleBracketedGenericArguments::do_parse(None, input)?;
}
} else if consume![as] {
input.parse::<Type>()?;
} else if !(consume(Brace) || consume(Bracket) || consume(Parenthesis)) {
break;
}
}

Err(input.error("unsupported expression"))
}

0 comments on commit 7c102c3

Please sign in to comment.