4 /// A braced block containing Rust statements.
6 /// *This type is available only if Syn is built with the `"full"` feature.*
7 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
9 pub brace_token
: token
::Brace
,
10 /// Statements in a block
16 /// A statement, usually ending in a semicolon.
18 /// *This type is available only if Syn is built with the `"full"` feature.*
19 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
21 /// A local (let) binding.
24 /// An item definition.
27 /// Expr without trailing semicolon.
30 /// Expression with trailing semicolon.
31 Semi(Expr
, Token
![;]),
36 /// A local `let` binding: `let x: u64 = s.parse()?`.
38 /// *This type is available only if Syn is built with the `"full"` feature.*
39 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
41 pub attrs
: Vec
<Attribute
>,
42 pub let_token
: Token
![let],
44 pub init
: Option
<(Token
![=], Box
<Expr
>)>,
45 pub semi_token
: Token
![;],
49 #[cfg(feature = "parsing")]
52 use crate::parse
::discouraged
::Speculative
;
53 use crate::parse
::{Parse, ParseBuffer, ParseStream, Result}
;
54 use proc_macro2
::TokenStream
;
57 /// Parse the body of a block as zero or more statements, possibly
58 /// including one trailing expression.
60 /// *This function is available only if Syn is built with the `"parsing"`
66 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
67 /// use syn::parse::{Parse, ParseStream};
69 /// // Parse a function with no generics or parameter list.
71 /// // fn playground {
74 /// // println!("{}", x);
76 /// struct MiniFunction {
77 /// attrs: Vec<Attribute>,
78 /// fn_token: Token![fn],
80 /// brace_token: token::Brace,
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()?;
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)?;
97 /// let mut attrs = outer_attrs;
98 /// attrs.extend(inner_attrs);
109 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
110 pub fn parse_within(input
: ParseStream
) -> Result
<Vec
<Stmt
>> {
111 let mut stmts
= Vec
::new();
113 while let Some(semi
) = input
.parse
::<Option
<Token
![;]>>()?
{
114 stmts
.push(Stmt
::Semi(Expr
::Verbatim(TokenStream
::new()), semi
));
116 if input
.is_empty() {
119 let s
= parse_stmt(input
, true)?
;
120 let requires_semicolon
= if let Stmt
::Expr(s
) = &s
{
121 expr
::requires_terminator(s
)
126 if input
.is_empty() {
128 } else if requires_semicolon
{
129 return Err(input
.error("unexpected token"));
136 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
137 impl Parse
for Block
{
138 fn parse(input
: ParseStream
) -> Result
<Self> {
141 brace_token
: braced
!(content
in input
),
142 stmts
: content
.call(Block
::parse_within
)?
,
147 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
148 impl Parse
for Stmt
{
149 fn parse(input
: ParseStream
) -> Result
<Self> {
150 parse_stmt(input
, false)
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
)?
;
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
))
167 input
.advance_to(&ahead
);
168 return stmt_mac(input
, attrs
, path
);
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])
202 let mut item
: Item
= input
.parse()?
;
203 attrs
.extend(item
.replace_attrs(Vec
::new()));
204 item
.replace_attrs(attrs
);
207 stmt_expr(input
, allow_nosemi
, attrs
)
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()?
;
217 Ok(Stmt
::Item(Item
::Macro(ItemMacro
{
230 fn stmt_local(input
: ParseStream
, attrs
: Vec
<Attribute
>, begin
: ParseBuffer
) -> Result
<Stmt
> {
231 let let_token
: Token
![let] = input
.parse()?
;
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
{
245 let init
= if input
.peek(Token
![=]) {
246 let eq_token
: Token
![=] = input
.parse()?
;
247 let init
: Expr
= input
.parse()?
;
249 if input
.peek(Token
![else]) {
250 input
.parse
::<Token
![else]>()?
;
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
));
259 Some((eq_token
, Box
::new(init
)))
264 let semi_token
: Token
![;] = input
.parse()?
;
266 Ok(Stmt
::Local(Local
{
278 mut attrs
: Vec
<Attribute
>,
280 let mut e
= expr
::parsing
::expr_early(input
)?
;
282 let mut attr_target
= &mut e
;
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
,
291 attrs
.extend(attr_target
.replace_attrs(Vec
::new()));
292 attr_target
.replace_attrs(attrs
);
294 if input
.peek(Token
![;]) {
295 return Ok(Stmt
::Semi(e
, input
.parse()?
));
298 if allow_nosemi
|| !expr
::requires_terminator(&e
) {
301 Err(input
.error("expected semicolon"))
306 #[cfg(feature = "printing")]
309 use proc_macro2
::TokenStream
;
310 use quote
::{ToTokens, TokenStreamExt}
;
312 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
313 impl ToTokens
for Block
{
314 fn to_tokens(&self, tokens
: &mut TokenStream
) {
315 self.brace_token
.surround(tokens
, |tokens
| {
316 tokens
.append_all(&self.stmts
);
321 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
322 impl ToTokens
for Stmt
{
323 fn to_tokens(&self, tokens
: &mut TokenStream
) {
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
);
336 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
337 impl ToTokens
for Local
{
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
);
346 self.semi_token
.to_tokens(tokens
);