1 use super::*; 2 3 ast_struct! { 4 /// A braced block containing Rust statements. 5 /// 6 /// *This type is available only if Syn is built with the `"full"` feature.* 7 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 8 pub struct Block { 9 pub brace_token: token::Brace, 10 /// Statements in a block 11 pub stmts: Vec<Stmt>, 12 } 13 } 14 15 ast_enum! { 16 /// A statement, usually ending in a semicolon. 17 /// 18 /// *This type is available only if Syn is built with the `"full"` feature.* 19 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 20 pub enum Stmt { 21 /// A local (let) binding. 22 Local(Local), 23 24 /// An item definition. 25 Item(Item), 26 27 /// Expr without trailing semicolon. 28 Expr(Expr), 29 30 /// Expression with trailing semicolon. 31 Semi(Expr, Token![;]), 32 } 33 } 34 35 ast_struct! { 36 /// A local `let` binding: `let x: u64 = s.parse()?`. 37 /// 38 /// *This type is available only if Syn is built with the `"full"` feature.* 39 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 40 pub struct Local { 41 pub attrs: Vec<Attribute>, 42 pub let_token: Token![let], 43 pub pat: Pat, 44 pub init: Option<(Token![=], Box<Expr>)>, 45 pub semi_token: Token![;], 46 } 47 } 48 49 #[cfg(feature = "parsing")] 50 pub mod parsing { 51 use super::*; 52 use crate::parse::discouraged::Speculative; 53 use crate::parse::{Parse, ParseBuffer, ParseStream, Result}; 54 use proc_macro2::TokenStream; 55 56 impl Block { 57 /// Parse the body of a block as zero or more statements, possibly 58 /// including one trailing expression. 59 /// 60 /// *This function is available only if Syn is built with the `"parsing"` 61 /// feature.* 62 /// 63 /// # Example 64 /// 65 /// ``` 66 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token}; 67 /// use syn::parse::{Parse, ParseStream}; 68 /// 69 /// // Parse a function with no generics or parameter list. 70 /// // 71 /// // fn playground { 72 /// // let mut x = 1; 73 /// // x += 1; 74 /// // println!("{}", x); 75 /// // } 76 /// struct MiniFunction { 77 /// attrs: Vec<Attribute>, 78 /// fn_token: Token![fn], 79 /// name: Ident, 80 /// brace_token: token::Brace, 81 /// stmts: Vec<Stmt>, 82 /// } 83 /// 84 /// impl Parse for MiniFunction { 85 /// fn parse(input: ParseStream) -> Result<Self> { 86 /// let outer_attrs = input.call(Attribute::parse_outer)?; 87 /// let fn_token: Token![fn] = input.parse()?; 88 /// let name: Ident = input.parse()?; 89 /// 90 /// let content; 91 /// let brace_token = braced!(content in input); 92 /// let inner_attrs = content.call(Attribute::parse_inner)?; 93 /// let stmts = content.call(Block::parse_within)?; 94 /// 95 /// Ok(MiniFunction { 96 /// attrs: { 97 /// let mut attrs = outer_attrs; 98 /// attrs.extend(inner_attrs); 99 /// attrs 100 /// }, 101 /// fn_token, 102 /// name, 103 /// brace_token, 104 /// stmts, 105 /// }) 106 /// } 107 /// } 108 /// ``` 109 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] parse_within(input: ParseStream) -> Result<Vec<Stmt>>110 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> { 111 let mut stmts = Vec::new(); 112 loop { 113 while let Some(semi) = input.parse::<Option<Token![;]>>()? { 114 stmts.push(Stmt::Semi(Expr::Verbatim(TokenStream::new()), semi)); 115 } 116 if input.is_empty() { 117 break; 118 } 119 let s = parse_stmt(input, true)?; 120 let requires_semicolon = if let Stmt::Expr(s) = &s { 121 expr::requires_terminator(s) 122 } else { 123 false 124 }; 125 stmts.push(s); 126 if input.is_empty() { 127 break; 128 } else if requires_semicolon { 129 return Err(input.error("unexpected token")); 130 } 131 } 132 Ok(stmts) 133 } 134 } 135 136 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 137 impl Parse for Block { parse(input: ParseStream) -> Result<Self>138 fn parse(input: ParseStream) -> Result<Self> { 139 let content; 140 Ok(Block { 141 brace_token: braced!(content in input), 142 stmts: content.call(Block::parse_within)?, 143 }) 144 } 145 } 146 147 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 148 impl Parse for Stmt { parse(input: ParseStream) -> Result<Self>149 fn parse(input: ParseStream) -> Result<Self> { 150 parse_stmt(input, false) 151 } 152 } 153 parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt>154 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> { 155 let begin = input.fork(); 156 let mut attrs = input.call(Attribute::parse_outer)?; 157 158 // brace-style macros; paren and bracket macros get parsed as 159 // expression statements. 160 let ahead = input.fork(); 161 if let Ok(path) = ahead.call(Path::parse_mod_style) { 162 if ahead.peek(Token![!]) 163 && (ahead.peek2(token::Brace) 164 && !(ahead.peek3(Token![.]) || ahead.peek3(Token![?])) 165 || ahead.peek2(Ident)) 166 { 167 input.advance_to(&ahead); 168 return stmt_mac(input, attrs, path); 169 } 170 } 171 172 if input.peek(Token![let]) { 173 stmt_local(input, attrs, begin) 174 } else if input.peek(Token![pub]) 175 || input.peek(Token![crate]) && !input.peek2(Token![::]) 176 || input.peek(Token![extern]) 177 || input.peek(Token![use]) 178 || input.peek(Token![static]) 179 && (input.peek2(Token![mut]) 180 || input.peek2(Ident) 181 && !(input.peek2(Token![async]) 182 && (input.peek3(Token![move]) || input.peek3(Token![|])))) 183 || input.peek(Token![const]) && !input.peek2(token::Brace) 184 || input.peek(Token![unsafe]) && !input.peek2(token::Brace) 185 || input.peek(Token![async]) 186 && (input.peek2(Token![unsafe]) 187 || input.peek2(Token![extern]) 188 || input.peek2(Token![fn])) 189 || input.peek(Token![fn]) 190 || input.peek(Token![mod]) 191 || input.peek(Token![type]) 192 || input.peek(Token![struct]) 193 || input.peek(Token![enum]) 194 || input.peek(Token![union]) && input.peek2(Ident) 195 || input.peek(Token![auto]) && input.peek2(Token![trait]) 196 || input.peek(Token![trait]) 197 || input.peek(Token![default]) 198 && (input.peek2(Token![unsafe]) || input.peek2(Token![impl])) 199 || input.peek(Token![impl]) 200 || input.peek(Token![macro]) 201 { 202 let mut item: Item = input.parse()?; 203 attrs.extend(item.replace_attrs(Vec::new())); 204 item.replace_attrs(attrs); 205 Ok(Stmt::Item(item)) 206 } else { 207 stmt_expr(input, allow_nosemi, attrs) 208 } 209 } 210 stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<Stmt>211 fn stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<Stmt> { 212 let bang_token: Token![!] = input.parse()?; 213 let ident: Option<Ident> = input.parse()?; 214 let (delimiter, tokens) = mac::parse_delimiter(input)?; 215 let semi_token: Option<Token![;]> = input.parse()?; 216 217 Ok(Stmt::Item(Item::Macro(ItemMacro { 218 attrs, 219 ident, 220 mac: Macro { 221 path, 222 bang_token, 223 delimiter, 224 tokens, 225 }, 226 semi_token, 227 }))) 228 } 229 stmt_local(input: ParseStream, attrs: Vec<Attribute>, begin: ParseBuffer) -> Result<Stmt>230 fn stmt_local(input: ParseStream, attrs: Vec<Attribute>, begin: ParseBuffer) -> Result<Stmt> { 231 let let_token: Token![let] = input.parse()?; 232 233 let mut pat: Pat = pat::parsing::multi_pat_with_leading_vert(input)?; 234 if input.peek(Token![:]) { 235 let colon_token: Token![:] = input.parse()?; 236 let ty: Type = input.parse()?; 237 pat = Pat::Type(PatType { 238 attrs: Vec::new(), 239 pat: Box::new(pat), 240 colon_token, 241 ty: Box::new(ty), 242 }); 243 } 244 245 let init = if input.peek(Token![=]) { 246 let eq_token: Token![=] = input.parse()?; 247 let init: Expr = input.parse()?; 248 249 if input.peek(Token![else]) { 250 input.parse::<Token![else]>()?; 251 let content; 252 braced!(content in input); 253 content.call(Block::parse_within)?; 254 let verbatim = Expr::Verbatim(verbatim::between(begin, input)); 255 let semi_token: Token![;] = input.parse()?; 256 return Ok(Stmt::Semi(verbatim, semi_token)); 257 } 258 259 Some((eq_token, Box::new(init))) 260 } else { 261 None 262 }; 263 264 let semi_token: Token![;] = input.parse()?; 265 266 Ok(Stmt::Local(Local { 267 attrs, 268 let_token, 269 pat, 270 init, 271 semi_token, 272 })) 273 } 274 stmt_expr( input: ParseStream, allow_nosemi: bool, mut attrs: Vec<Attribute>, ) -> Result<Stmt>275 fn stmt_expr( 276 input: ParseStream, 277 allow_nosemi: bool, 278 mut attrs: Vec<Attribute>, 279 ) -> Result<Stmt> { 280 let mut e = expr::parsing::expr_early(input)?; 281 282 let mut attr_target = &mut e; 283 loop { 284 attr_target = match attr_target { 285 Expr::Assign(e) => &mut e.left, 286 Expr::AssignOp(e) => &mut e.left, 287 Expr::Binary(e) => &mut e.left, 288 _ => break, 289 }; 290 } 291 attrs.extend(attr_target.replace_attrs(Vec::new())); 292 attr_target.replace_attrs(attrs); 293 294 if input.peek(Token![;]) { 295 return Ok(Stmt::Semi(e, input.parse()?)); 296 } 297 298 if allow_nosemi || !expr::requires_terminator(&e) { 299 Ok(Stmt::Expr(e)) 300 } else { 301 Err(input.error("expected semicolon")) 302 } 303 } 304 } 305 306 #[cfg(feature = "printing")] 307 mod printing { 308 use super::*; 309 use proc_macro2::TokenStream; 310 use quote::{ToTokens, TokenStreamExt}; 311 312 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 313 impl ToTokens for Block { to_tokens(&self, tokens: &mut TokenStream)314 fn to_tokens(&self, tokens: &mut TokenStream) { 315 self.brace_token.surround(tokens, |tokens| { 316 tokens.append_all(&self.stmts); 317 }); 318 } 319 } 320 321 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 322 impl ToTokens for Stmt { to_tokens(&self, tokens: &mut TokenStream)323 fn to_tokens(&self, tokens: &mut TokenStream) { 324 match self { 325 Stmt::Local(local) => local.to_tokens(tokens), 326 Stmt::Item(item) => item.to_tokens(tokens), 327 Stmt::Expr(expr) => expr.to_tokens(tokens), 328 Stmt::Semi(expr, semi) => { 329 expr.to_tokens(tokens); 330 semi.to_tokens(tokens); 331 } 332 } 333 } 334 } 335 336 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 337 impl ToTokens for Local { to_tokens(&self, tokens: &mut TokenStream)338 fn to_tokens(&self, tokens: &mut TokenStream) { 339 expr::printing::outer_attrs_to_tokens(&self.attrs, tokens); 340 self.let_token.to_tokens(tokens); 341 self.pat.to_tokens(tokens); 342 if let Some((eq_token, init)) = &self.init { 343 eq_token.to_tokens(tokens); 344 init.to_tokens(tokens); 345 } 346 self.semi_token.to_tokens(tokens); 347 } 348 } 349 } 350