Lex attributes in a much more robust way :)

This commit is contained in:
ConnorSkees 2020-01-26 19:07:24 -05:00
parent c7efbc7e05
commit 15edae53d6
3 changed files with 60 additions and 43 deletions

View File

@ -127,14 +127,17 @@ impl<'a> Lexer<'a> {
TokenKind::Keyword(Keyword::Important)
}
fn devour_whitespace(&mut self) {
fn devour_whitespace(&mut self) -> bool {
let mut found_whitespace = false;
while let Some(c) = self.buf.peek() {
if !is_whitespace(*c) {
break;
return found_whitespace;
}
found_whitespace = true;
self.buf.next();
self.pos.next_char();
}
found_whitespace
}
fn lex_at_rule(&mut self) -> TokenKind {
@ -300,21 +303,28 @@ impl<'a> Lexer<'a> {
let mut case_sensitive = CaseKind::Sensitive;
while let Some(c) = self.buf.peek() {
if c == &']' && !c.is_whitespace() {
if c == &']' || c.is_whitespace() {
break;
}
if c == &'i' || c == &'I' {
if c == &'i' {
case_sensitive = CaseKind::InsensitiveLowercase;
} else if c == &'I' {
case_sensitive = CaseKind::InsensitiveCapital;
}
let tok = self
.buf
.next()
.expect("this is impossible because we have already peeked");
self.pos.next_char();
value.push(tok);
}
if self.devour_whitespace() {
let n = self.buf.next();
match n {
Some('i') | Some('I') => {
let case_sensitive = match n {
Some('i') => CaseKind::InsensitiveLowercase,
Some('I') => CaseKind::InsensitiveCapital,
_ => unsafe { std::hint::unreachable_unchecked() },
};
self.pos.next_char();
self.devour_whitespace();
match self.buf.next() {
Some(']') => {
@ -325,27 +335,29 @@ impl<'a> Lexer<'a> {
case_sensitive,
})
}
Some(val) => {
self.pos.next_char();
value.push(tok);
value.push(val);
Some(_) => todo!("modifier must be 1 character"),
None => todo!("unexpected EOF"),
}
None => todo!("expected something to come after "),
}
continue;
Some(']') => {
return TokenKind::Attribute(Attribute {
kind,
attr,
value,
case_sensitive,
})
}
let tok = self
.buf
.next()
.expect("this is impossible because we have already peeked");
self.pos.next_char();
value.push(tok);
}
Some(c) => {
value.push(' ');
value.push(c.clone());
self.devour_whitespace();
assert!(self.buf.next() == Some(']'));
}
None => todo!(),
}
} else {
assert!(self.buf.next() == Some(']'));
}
TokenKind::Attribute(Attribute {
kind,

View File

@ -143,10 +143,15 @@ mod test_selectors {
selector_attribute_i_in_attr,
"[atitr=val] {\n color: red;\n}\n"
);
// test!(
// selector_attribute_i_in_val,
// "[attr=vail] {\n color: red;\n}\n"
// );
test!(
selector_attribute_i_in_val,
"[attr=vail] {\n color: red;\n}\n"
);
test!(
selector_attribute_whitespace,
"[attr *= val ] {\n color: red;\n}\n",
"[attr*=val] {\n color: red;\n}\n"
);
test!(
selector_attribute_equals,
"[attr=val] {\n color: red;\n}\n"