Skip to content

Commit

Permalink
feat(parser)!: fragments (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
stoically committed Jan 3, 2021
1 parent 5f8e7f6 commit da7d25b
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 3 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ assert_eq!(nodes[0].children[0].value_as_string().unwrap(), "hi");
<div key=some::value() />
```

- **Doctypes and Comments**
- **Doctypes, Comments and Fragments**

```html
<!DOCTYPE html>
<!-- "comment" -->
<></>
```

- **Braced blocks are parsed as arbitrary Rust code**
Expand Down
4 changes: 2 additions & 2 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use quote::quote;
fn criterion_benchmark(c: &mut Criterion) {
let tokens = quote! {
<!DOCTYPE html>
<div>
<>
<!-- "comment" -->
<hello world />
<div>"String literal"</div>
Expand All @@ -16,7 +16,7 @@ fn criterion_benchmark(c: &mut Criterion) {
<div>{ let block = "in node position"; }</div>
<div { let block = "in attribute position"; } />
<div key={ let block = "in attribute value position"; } />
</div>
</>
};

c.bench_function("syn_rsx::parse2", |b| {
Expand Down
4 changes: 4 additions & 0 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ pub enum NodeType {
/// node value in this case
Doctype,

/// Fragment: `<></>`
Fragment,

/// Arbitrary rust code in braced `{}` blocks
Block,
}
Expand All @@ -117,6 +120,7 @@ impl fmt::Display for NodeType {
Self::Text => "NodeType::Text",
Self::Comment => "NodeType::Comment",
Self::Doctype => "NodeType::Doctype",
Self::Fragment => "NodeType::Fragment",
Self::Block => "NodeType::Block",
}
)
Expand Down
43 changes: 43 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ impl Parser {
} else {
self.comment(input)
}
} else if input.peek2(Token![>]) {
self.fragment(input)
} else {
self.element(input)
}
Expand Down Expand Up @@ -446,6 +448,47 @@ impl Parser {
})
}

fn fragment(&self, input: ParseStream) -> Result<Node> {
self.fragment_open(input)?;

let mut children = vec![];
loop {
if input.is_empty() {
return Err(input.error("unexpected end of input"));
}

if let Ok(_) = self.fragment_close(&input.fork()) {
self.fragment_close(input)?;
break;
}

children.append(&mut self.node(input)?);
}

Ok(Node {
name: None,
value: None,
node_type: NodeType::Fragment,
attributes: vec![],
children,
})
}

fn fragment_open(&self, input: ParseStream) -> Result<()> {
input.parse::<Token![<]>()?;
input.parse::<Token![>]>()?;

Ok(())
}

fn fragment_close(&self, input: ParseStream) -> Result<()> {
input.parse::<Token![<]>()?;
input.parse::<Token![/]>()?;
input.parse::<Token![>]>()?;

Ok(())
}

fn node_name(&self, input: ParseStream) -> Result<NodeName> {
if input.peek2(Colon2) {
self.node_name_punctuated_ident::<Colon2, fn(_) -> Colon2, PathSegment>(input, Colon2)
Expand Down
13 changes: 13 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,16 @@ fn test_comment() {
Some("comment2".to_owned())
);
}

#[test]
fn test_fragment() {
let tokens = quote! {
<>
<div />
</>
};

let nodes = parse2(tokens);

assert!(nodes.is_ok());
}

0 comments on commit da7d25b

Please sign in to comment.