attr valid: return whether attrs non-empty

This commit is contained in:
Noah Hellman 2023-01-16 17:24:27 +01:00
parent 161dfec96d
commit b512c670e6
3 changed files with 39 additions and 16 deletions

View file

@ -10,13 +10,18 @@ pub(crate) fn parse<'s, S: DiscontinuousString<'s>>(chars: S) -> Attributes<'s>
a a
} }
pub fn valid<I: Iterator<Item = char>>(chars: I) -> usize { pub fn valid<I: Iterator<Item = char>>(chars: I) -> (usize, bool) {
let mut has_attr = false;
let mut p = Parser::new(chars); let mut p = Parser::new(chars);
if p.any(|e| matches!(e, Element::Invalid)) { for e in &mut p {
0 match e {
} else { Element::Class(..) | Element::Identifier(..) | Element::Attribute(..) => {
p.pos has_attr = true
} }
Element::Invalid => return (0, false),
}
}
(p.pos, has_attr)
} }
// Attributes are relatively rare, we choose to pay 8 bytes always and sometimes an extra // Attributes are relatively rare, we choose to pay 8 bytes always and sometimes an extra
@ -357,7 +362,25 @@ mod test {
#[test] #[test]
fn valid_full() { fn valid_full() {
let src = "{.class %comment%}"; let src = "{.class %comment%}";
assert_eq!(super::valid(src.chars()), src.len()); assert_eq!(super::valid(src.chars()), (src.len(), true));
}
#[test]
fn valid_empty() {
let src = "{}";
assert_eq!(super::valid(src.chars()), (src.len(), false));
}
#[test]
fn valid_whitespace() {
let src = "{ \n }";
assert_eq!(super::valid(src.chars()), (src.len(), false));
}
#[test]
fn valid_comment() {
let src = "{%comment%}";
assert_eq!(super::valid(src.chars()), (src.len(), false));
} }
#[test] #[test]
@ -365,15 +388,15 @@ mod test {
let src = "{.class}"; let src = "{.class}";
assert_eq!( assert_eq!(
super::valid(src.chars().chain("{.ignore}".chars())), super::valid(src.chars().chain("{.ignore}".chars())),
src.len() (src.len(), true),
); );
} }
#[test] #[test]
fn valid_invalid() { fn valid_invalid() {
assert_eq!(super::valid(" {.valid}".chars()), 0); assert_eq!(super::valid(" {.valid}".chars()), (0, false));
assert_eq!(super::valid("{.class invalid}".chars()), 0); assert_eq!(super::valid("{.class invalid}".chars()), (0, false));
assert_eq!(super::valid("abc".chars()), 0); assert_eq!(super::valid("abc".chars()), (0, false));
assert_eq!(super::valid("{.abc.}".chars()), 0); assert_eq!(super::valid("{.abc.}".chars()), (0, false));
} }
} }

View file

@ -270,7 +270,7 @@ impl BlockParser {
)) ))
} }
} }
'{' => (attr::valid(line_t.chars()) == line_t.trim_end().len()) '{' => (attr::valid(line_t.chars()).0 == line_t.trim_end().len())
.then(|| (Block::Atom(Attributes), Span::by_len(start, line_t.len()))), .then(|| (Block::Atom(Attributes), Span::by_len(start, line_t.len()))),
'|' => (&line_t[line_t.len() - 1..] == "|" '|' => (&line_t[line_t.len() - 1..] == "|"
&& &line_t[line_t.len() - 2..line_t.len() - 1] != "\\") && &line_t[line_t.len() - 2..line_t.len() - 1] != "\\")

View file

@ -239,12 +239,12 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
.map_or(false, |e| e.kind == EventKind::Str) .map_or(false, |e| e.kind == EventKind::Str)
{ {
let mut ahead = self.lexer.inner().clone(); let mut ahead = self.lexer.inner().clone();
let mut attr_len = attr::valid(std::iter::once('{').chain(&mut ahead)) - 1; let mut attr_len = attr::valid(std::iter::once('{').chain(&mut ahead)).0 - 1;
if attr_len > 0 { if attr_len > 0 {
while attr_len > 0 { while attr_len > 0 {
self.lexer = lex::Lexer::new(ahead.clone()); self.lexer = lex::Lexer::new(ahead.clone());
self.span = self.span.extend(attr_len); self.span = self.span.extend(attr_len);
attr_len = attr::valid(&mut ahead); attr_len = attr::valid(&mut ahead).0;
} }
let i = self let i = self
@ -345,7 +345,7 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
}; };
self.openers.drain(o..); self.openers.drain(o..);
let mut ahead = self.lexer.inner().clone(); let mut ahead = self.lexer.inner().clone();
let mut attr_len = attr::valid(&mut ahead); let mut attr_len = attr::valid(&mut ahead).0;
if attr_len > 0 { if attr_len > 0 {
let span_closer = self.span; let span_closer = self.span;
self.events[e_attr].span = Span::empty_at(self.span.end()); self.events[e_attr].span = Span::empty_at(self.span.end());
@ -354,7 +354,7 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
self.lexer = lex::Lexer::new(ahead.clone()); self.lexer = lex::Lexer::new(ahead.clone());
self.span = self.events[e_attr].span.extend(attr_len); self.span = self.events[e_attr].span.extend(attr_len);
self.events[e_attr].span = self.span; self.events[e_attr].span = self.span;
attr_len = attr::valid(&mut ahead); attr_len = attr::valid(&mut ahead).0;
} }
if event.is_none() { if event.is_none() {