token: use many0 combinator for StartTag parsing

This commit is contained in:
Astro 2022-03-23 19:30:53 +01:00
parent 5c5e32e7ff
commit ce1d95710b

View file

@ -81,6 +81,7 @@ impl Token {
fn parse_tag(s: &[u8]) -> IResult<&[u8], Token> { fn parse_tag(s: &[u8]) -> IResult<&[u8], Token> {
let (s, _) = tag("<")(s)?; let (s, _) = tag("<")(s)?;
alt((|s| -> IResult<&[u8], Token> { alt((|s| -> IResult<&[u8], Token> {
// CDATA
let (s, _) = tag("![CDATA[")(s)?; let (s, _) = tag("![CDATA[")(s)?;
let mut end = None; let mut end = None;
for i in 0..s.len() - 2 { for i in 0..s.len() - 2 {
@ -96,6 +97,7 @@ impl Token {
Err(nom::Err::Incomplete(nom::Needed::Unknown)) Err(nom::Err::Incomplete(nom::Needed::Unknown))
} }
}, |s| { }, |s| {
// EndTag
let (s, _) = tag("/")(s)?; let (s, _) = tag("/")(s)?;
let (s, _) = space0(s)?; let (s, _) = space0(s)?;
let (s, name) = take_while1(|b| !(is_space(b) || b == b'>'))(s)?; let (s, name) = take_while1(|b| !(is_space(b) || b == b'>'))(s)?;
@ -104,34 +106,27 @@ impl Token {
let name = Self::str_from_utf8(name)?; let name = Self::str_from_utf8(name)?;
Ok((s, Token::EndTag { name: name.into() })) Ok((s, Token::EndTag { name: name.into() }))
}, |s| { }, |s| {
// StartTag
let (s, _) = space0(s)?; let (s, _) = space0(s)?;
let (s, name) = take_while1(|b| !(is_space(b) || b == b'>' || b == b'/'))(s)?; let (s, name) = take_while1(|b| !(is_space(b) || b == b'>' || b == b'/'))(s)?;
let mut attrs = vec![]; let (s, _) = space0(s)?;
let mut self_closing = false; let (s, attrs) = many0(|s| {
let mut s_ = s; let (s, (name, value)) = Self::parse_attr(s)?;
loop { let (s, _) = space0(s)?;
let (s, _) = space0(s_)?; Ok((s, (name, value)))
let (s, attr) = alt((|s| { })(s)?;
let (s, _) = tag("/")(s)?;
let (s, _) = space0(s)?; let (s, self_closing) = alt((|s| {
let (s, _) = tag(">")(s)?; let (s, _) = tag("/")(s)?;
self_closing = true; let (s, _) = space0(s)?;
Ok((s, None)) let (s, _) = tag(">")(s)?;
}, |s| { Ok((s, true))
let (s, _) = tag(">")(s)?; }, |s| {
Ok((s, None)) let (s, _) = tag(">")(s)?;
}, |s| { Ok((s, false))
let (s, (name, value)) = Self::parse_attr(s)?; }))(s)?;
Ok((s, Some((name, value))))
}))(s)?; Ok((s, Token::StartTag {
s_ = s;
if let Some(attr) = attr {
attrs.push(attr);
} else {
break;
}
}
Ok((s_, Token::StartTag {
name: Self::str_from_utf8(name)? name: Self::str_from_utf8(name)?
.into(), .into(),
attrs: attrs.into_iter() attrs: attrs.into_iter()
@ -143,7 +138,7 @@ impl Token {
} }
fn parse_attr(s: &[u8]) -> IResult<&[u8], (&str, String)> { fn parse_attr(s: &[u8]) -> IResult<&[u8], (&str, String)> {
let (s, name) = take_while1(|b| !(is_space(b) || b == b'='))(s)?; let (s, name) = take_while1(|b| !(is_space(b) || b == b'=' || b == b'/' || b == b'>'))(s)?;
let name = Self::str_from_utf8(name)?; let name = Self::str_from_utf8(name)?;
let (s, _) = space0(s)?; let (s, _) = space0(s)?;
let (s, _) = tag("=")(s)?; let (s, _) = tag("=")(s)?;