diff options
Diffstat (limited to 'syn/src/stmt.rs')
-rw-r--r-- | syn/src/stmt.rs | 333 |
1 files changed, 0 insertions, 333 deletions
diff --git a/syn/src/stmt.rs b/syn/src/stmt.rs deleted file mode 100644 index acee5a3..0000000 --- a/syn/src/stmt.rs +++ /dev/null @@ -1,333 +0,0 @@ -use super::*; - -ast_struct! { - /// A braced block containing Rust statements. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct Block { - pub brace_token: token::Brace, - /// Statements in a block - pub stmts: Vec<Stmt>, - } -} - -ast_enum! { - /// A statement, usually ending in a semicolon. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub enum Stmt { - /// A local (let) binding. - Local(Local), - - /// An item definition. - Item(Item), - - /// Expr without trailing semicolon. - Expr(Expr), - - /// Expression with trailing semicolon. - Semi(Expr, Token![;]), - } -} - -ast_struct! { - /// A local `let` binding: `let x: u64 = s.parse()?`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct Local { - pub attrs: Vec<Attribute>, - pub let_token: Token![let], - pub pat: Pat, - pub init: Option<(Token![=], Box<Expr>)>, - pub semi_token: Token![;], - } -} - -#[cfg(feature = "parsing")] -pub mod parsing { - use super::*; - - use crate::parse::discouraged::Speculative; - use crate::parse::{Parse, ParseStream, Result}; - use crate::punctuated::Punctuated; - use proc_macro2::TokenStream; - - impl Block { - /// Parse the body of a block as zero or more statements, possibly - /// including one trailing expression. - /// - /// *This function is available if Syn is built with the `"parsing"` - /// feature.* - /// - /// # Example - /// - /// ``` - /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token}; - /// use syn::parse::{Parse, ParseStream}; - /// - /// // Parse a function with no generics or parameter list. - /// // - /// // fn playground { - /// // let mut x = 1; - /// // x += 1; - /// // println!("{}", x); - /// // } - /// struct MiniFunction { - /// attrs: Vec<Attribute>, - /// fn_token: Token![fn], - /// name: Ident, - /// brace_token: token::Brace, - /// stmts: Vec<Stmt>, - /// } - /// - /// impl Parse for MiniFunction { - /// fn parse(input: ParseStream) -> Result<Self> { - /// let outer_attrs = input.call(Attribute::parse_outer)?; - /// let fn_token: Token![fn] = input.parse()?; - /// let name: Ident = input.parse()?; - /// - /// let content; - /// let brace_token = braced!(content in input); - /// let inner_attrs = content.call(Attribute::parse_inner)?; - /// let stmts = content.call(Block::parse_within)?; - /// - /// Ok(MiniFunction { - /// attrs: { - /// let mut attrs = outer_attrs; - /// attrs.extend(inner_attrs); - /// attrs - /// }, - /// fn_token, - /// name, - /// brace_token, - /// stmts, - /// }) - /// } - /// } - /// ``` - pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> { - let mut stmts = Vec::new(); - loop { - while let Some(semi) = input.parse::<Option<Token![;]>>()? { - stmts.push(Stmt::Semi(Expr::Verbatim(TokenStream::new()), semi)); - } - if input.is_empty() { - break; - } - let s = parse_stmt(input, true)?; - let requires_semicolon = if let Stmt::Expr(s) = &s { - expr::requires_terminator(s) - } else { - false - }; - stmts.push(s); - if input.is_empty() { - break; - } else if requires_semicolon { - return Err(input.error("unexpected token")); - } - } - Ok(stmts) - } - } - - impl Parse for Block { - fn parse(input: ParseStream) -> Result<Self> { - let content; - Ok(Block { - brace_token: braced!(content in input), - stmts: content.call(Block::parse_within)?, - }) - } - } - - impl Parse for Stmt { - fn parse(input: ParseStream) -> Result<Self> { - parse_stmt(input, false) - } - } - - fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> { - let mut attrs = input.call(Attribute::parse_outer)?; - - // brace-style macros; paren and bracket macros get parsed as - // expression statements. - let ahead = input.fork(); - if let Ok(path) = ahead.call(Path::parse_mod_style) { - if ahead.peek(Token![!]) && (ahead.peek2(token::Brace) || ahead.peek2(Ident)) { - input.advance_to(&ahead); - return stmt_mac(input, attrs, path); - } - } - - if input.peek(Token![let]) { - stmt_local(input, attrs).map(Stmt::Local) - } else if input.peek(Token![pub]) - || input.peek(Token![crate]) && !input.peek2(Token![::]) - || input.peek(Token![extern]) && !input.peek2(Token![::]) - || input.peek(Token![use]) - || input.peek(Token![static]) && (input.peek2(Token![mut]) || input.peek2(Ident)) - || input.peek(Token![const]) - || input.peek(Token![unsafe]) && !input.peek2(token::Brace) - || input.peek(Token![async]) - && (input.peek2(Token![unsafe]) - || input.peek2(Token![extern]) - || input.peek2(Token![fn])) - || input.peek(Token![fn]) - || input.peek(Token![mod]) - || input.peek(Token![type]) - || input.peek(item::parsing::existential) && input.peek2(Token![type]) - || input.peek(Token![struct]) - || input.peek(Token![enum]) - || input.peek(Token![union]) && input.peek2(Ident) - || input.peek(Token![auto]) && input.peek2(Token![trait]) - || input.peek(Token![trait]) - || input.peek(Token![default]) - && (input.peek2(Token![unsafe]) || input.peek2(Token![impl])) - || input.peek(Token![impl]) - || input.peek(Token![macro]) - { - let mut item: Item = input.parse()?; - attrs.extend(item.replace_attrs(Vec::new())); - item.replace_attrs(attrs); - Ok(Stmt::Item(item)) - } else { - stmt_expr(input, allow_nosemi, attrs) - } - } - - fn stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<Stmt> { - let bang_token: Token![!] = input.parse()?; - let ident: Option<Ident> = input.parse()?; - let (delimiter, tokens) = mac::parse_delimiter(input)?; - let semi_token: Option<Token![;]> = input.parse()?; - - Ok(Stmt::Item(Item::Macro(ItemMacro { - attrs, - ident, - mac: Macro { - path, - bang_token, - delimiter, - tokens, - }, - semi_token, - }))) - } - - fn stmt_local(input: ParseStream, attrs: Vec<Attribute>) -> Result<Local> { - Ok(Local { - attrs, - let_token: input.parse()?, - pat: { - let leading_vert: Option<Token![|]> = input.parse()?; - let mut pat: Pat = input.parse()?; - if leading_vert.is_some() - || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) - { - let mut cases = Punctuated::new(); - cases.push_value(pat); - while input.peek(Token![|]) - && !input.peek(Token![||]) - && !input.peek(Token![|=]) - { - let punct = input.parse()?; - cases.push_punct(punct); - let pat: Pat = input.parse()?; - cases.push_value(pat); - } - pat = Pat::Or(PatOr { - attrs: Vec::new(), - leading_vert, - cases, - }); - } - if input.peek(Token![:]) { - let colon_token: Token![:] = input.parse()?; - let ty: Type = input.parse()?; - pat = Pat::Type(PatType { - attrs: Vec::new(), - pat: Box::new(pat), - colon_token, - ty: Box::new(ty), - }); - } - pat - }, - init: { - if input.peek(Token![=]) { - let eq_token: Token![=] = input.parse()?; - let init: Expr = input.parse()?; - Some((eq_token, Box::new(init))) - } else { - None - } - }, - semi_token: input.parse()?, - }) - } - - fn stmt_expr( - input: ParseStream, - allow_nosemi: bool, - mut attrs: Vec<Attribute>, - ) -> Result<Stmt> { - let mut e = expr::parsing::expr_early(input)?; - - attrs.extend(e.replace_attrs(Vec::new())); - e.replace_attrs(attrs); - - if input.peek(Token![;]) { - return Ok(Stmt::Semi(e, input.parse()?)); - } - - if allow_nosemi || !expr::requires_terminator(&e) { - Ok(Stmt::Expr(e)) - } else { - Err(input.error("expected semicolon")) - } - } -} - -#[cfg(feature = "printing")] -mod printing { - use super::*; - - use proc_macro2::TokenStream; - use quote::{ToTokens, TokenStreamExt}; - - impl ToTokens for Block { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.brace_token.surround(tokens, |tokens| { - tokens.append_all(&self.stmts); - }); - } - } - - impl ToTokens for Stmt { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - Stmt::Local(local) => local.to_tokens(tokens), - Stmt::Item(item) => item.to_tokens(tokens), - Stmt::Expr(expr) => expr.to_tokens(tokens), - Stmt::Semi(expr, semi) => { - expr.to_tokens(tokens); - semi.to_tokens(tokens); - } - } - } - } - - impl ToTokens for Local { - fn to_tokens(&self, tokens: &mut TokenStream) { - expr::printing::outer_attrs_to_tokens(&self.attrs, tokens); - self.let_token.to_tokens(tokens); - self.pat.to_tokens(tokens); - if let Some((eq_token, init)) = &self.init { - eq_token.to_tokens(tokens); - init.to_tokens(tokens); - } - self.semi_token.to_tokens(tokens); - } - } -} |