Skip to content

Commit 3011d58

Browse files
authored
perf: more peeking and better block parsing (#5)
1 parent a75300e commit 3011d58

File tree

1 file changed

+42
-16
lines changed

1 file changed

+42
-16
lines changed

src/parser.rs

+42-16
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
//! RSX Parser
22
33
use proc_macro2::{TokenStream, TokenTree};
4-
use std::iter;
54
use syn::{
5+
braced,
66
ext::IdentExt,
77
parse::{discouraged::Speculative, Parse, ParseStream, Parser as _, Peek},
88
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,
1111
};
1212

1313
use crate::{node::*, punctuation::*};
@@ -133,9 +133,16 @@ impl Parser {
133133

134134
fn block_expr(&self, input: ParseStream) -> Result<Expr> {
135135
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+
};
139146
input.advance_to(&fork);
140147

141148
Ok(block.into())
@@ -211,8 +218,12 @@ impl Parser {
211218
attributes.extend(Some(next));
212219
};
213220

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+
};
216227

217228
Ok((name, attributes, self_closing))
218229
}
@@ -289,15 +300,30 @@ impl Parser {
289300
}
290301

291302
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+
},
298323
})
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+
};
301327

302328
Ok(node_name)
303329
}

0 commit comments

Comments
 (0)