|
1 | 1 | //! RSX Parser
|
2 | 2 |
|
3 | 3 | use proc_macro2::{TokenStream, TokenTree};
|
4 |
| -use std::iter; |
5 | 4 | use syn::{
|
| 5 | + braced, |
6 | 6 | ext::IdentExt,
|
7 | 7 | parse::{discouraged::Speculative, Parse, ParseStream, Parser as _, Peek},
|
8 | 8 | punctuated::Punctuated,
|
9 |
| - token::{Brace, Colon}, |
10 |
| - Error, Expr, ExprBlock, ExprLit, ExprPath, Ident, Path, PathSegment, Result, Token, |
| 9 | + token::{Brace, Colon, Colon2}, |
| 10 | + Block, Error, Expr, ExprBlock, ExprLit, ExprPath, Ident, Path, PathSegment, Result, Token, |
11 | 11 | };
|
12 | 12 |
|
13 | 13 | use crate::{node::*, punctuation::*};
|
@@ -133,9 +133,16 @@ impl Parser {
|
133 | 133 |
|
134 | 134 | fn block_expr(&self, input: ParseStream) -> Result<Expr> {
|
135 | 135 | let fork = input.fork();
|
136 |
| - let parser = move |input: ParseStream| input.parse(); |
137 |
| - let group: TokenTree = fork.parse()?; |
138 |
| - let block: ExprBlock = parser.parse2(iter::once(group).collect())?; |
| 136 | + let content; |
| 137 | + let brace_token = braced!(content in fork); |
| 138 | + let block = ExprBlock { |
| 139 | + attrs: vec![], |
| 140 | + label: None, |
| 141 | + block: Block { |
| 142 | + brace_token, |
| 143 | + stmts: Block::parse_within(&content)?, |
| 144 | + }, |
| 145 | + }; |
139 | 146 | input.advance_to(&fork);
|
140 | 147 |
|
141 | 148 | Ok(block.into())
|
@@ -211,8 +218,12 @@ impl Parser {
|
211 | 218 | attributes.extend(Some(next));
|
212 | 219 | };
|
213 | 220 |
|
214 |
| - let parser = move |input: ParseStream| self.attributes(input); |
215 |
| - let attributes = parser.parse2(attributes)?; |
| 221 | + let attributes = if !attributes.is_empty() { |
| 222 | + let parser = move |input: ParseStream| self.attributes(input); |
| 223 | + parser.parse2(attributes)? |
| 224 | + } else { |
| 225 | + vec![] |
| 226 | + }; |
216 | 227 |
|
217 | 228 | Ok((name, attributes, self_closing))
|
218 | 229 | }
|
@@ -289,15 +300,30 @@ impl Parser {
|
289 | 300 | }
|
290 | 301 |
|
291 | 302 | fn node_name(&self, input: ParseStream) -> Result<NodeName> {
|
292 |
| - let node_name = self |
293 |
| - .node_name_punctuated_ident::<Dash, fn(_) -> Dash>(input, Dash) |
294 |
| - .map(|ok| NodeName::Dash(ok)) |
295 |
| - .or_else(|_| { |
296 |
| - self.node_name_punctuated_ident::<Colon, fn(_) -> Colon>(input, Colon) |
297 |
| - .map(|ok| NodeName::Colon(ok)) |
| 303 | + let node_name = if input.peek2(Colon2) { |
| 304 | + self.node_name_mod_style(input)? |
| 305 | + } else if input.peek2(Colon) { |
| 306 | + self.node_name_punctuated_ident::<Colon, fn(_) -> Colon>(input, Colon) |
| 307 | + .map(|ok| NodeName::Colon(ok))? |
| 308 | + } else if input.peek2(Dash) { |
| 309 | + self.node_name_punctuated_ident::<Dash, fn(_) -> Dash>(input, Dash) |
| 310 | + .map(|ok| NodeName::Dash(ok))? |
| 311 | + } else if input.peek(Ident::peek_any) { |
| 312 | + let mut segments = Punctuated::new(); |
| 313 | + let ident = Ident::parse_any(input)?; |
| 314 | + segments.push_value(PathSegment::from(ident)); |
| 315 | + |
| 316 | + NodeName::Path(ExprPath { |
| 317 | + attrs: vec![], |
| 318 | + qself: None, |
| 319 | + path: Path { |
| 320 | + leading_colon: None, |
| 321 | + segments, |
| 322 | + }, |
298 | 323 | })
|
299 |
| - .or_else(|_| self.node_name_mod_style(input)) |
300 |
| - .or(Err(input.error("invalid tag name or attribute key")))?; |
| 324 | + } else { |
| 325 | + return Err(input.error("invalid tag name or attribute key")); |
| 326 | + }; |
301 | 327 |
|
302 | 328 | Ok(node_name)
|
303 | 329 | }
|
|
0 commit comments