Lex attributes in a much more robust way :)
This commit is contained in:
parent
c7efbc7e05
commit
15edae53d6
62
src/lexer.rs
62
src/lexer.rs
@ -127,14 +127,17 @@ impl<'a> Lexer<'a> {
|
|||||||
TokenKind::Keyword(Keyword::Important)
|
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() {
|
while let Some(c) = self.buf.peek() {
|
||||||
if !is_whitespace(*c) {
|
if !is_whitespace(*c) {
|
||||||
break;
|
return found_whitespace;
|
||||||
}
|
}
|
||||||
|
found_whitespace = true;
|
||||||
self.buf.next();
|
self.buf.next();
|
||||||
self.pos.next_char();
|
self.pos.next_char();
|
||||||
}
|
}
|
||||||
|
found_whitespace
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lex_at_rule(&mut self) -> TokenKind {
|
fn lex_at_rule(&mut self) -> TokenKind {
|
||||||
@ -300,21 +303,28 @@ impl<'a> Lexer<'a> {
|
|||||||
let mut case_sensitive = CaseKind::Sensitive;
|
let mut case_sensitive = CaseKind::Sensitive;
|
||||||
|
|
||||||
while let Some(c) = self.buf.peek() {
|
while let Some(c) = self.buf.peek() {
|
||||||
if c == &']' && !c.is_whitespace() {
|
if c == &']' || c.is_whitespace() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == &'i' || c == &'I' {
|
|
||||||
if c == &'i' {
|
|
||||||
case_sensitive = CaseKind::InsensitiveLowercase;
|
|
||||||
} else if c == &'I' {
|
|
||||||
case_sensitive = CaseKind::InsensitiveCapital;
|
|
||||||
}
|
|
||||||
let tok = self
|
let tok = self
|
||||||
.buf
|
.buf
|
||||||
.next()
|
.next()
|
||||||
.expect("this is impossible because we have already peeked");
|
.expect("this is impossible because we have already peeked");
|
||||||
self.pos.next_char();
|
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();
|
self.devour_whitespace();
|
||||||
match self.buf.next() {
|
match self.buf.next() {
|
||||||
Some(']') => {
|
Some(']') => {
|
||||||
@ -325,27 +335,29 @@ impl<'a> Lexer<'a> {
|
|||||||
case_sensitive,
|
case_sensitive,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some(val) => {
|
Some(_) => todo!("modifier must be 1 character"),
|
||||||
self.pos.next_char();
|
None => todo!("unexpected EOF"),
|
||||||
value.push(tok);
|
|
||||||
value.push(val);
|
|
||||||
}
|
}
|
||||||
None => todo!("expected something to come after "),
|
|
||||||
}
|
}
|
||||||
continue;
|
Some(']') => {
|
||||||
|
return TokenKind::Attribute(Attribute {
|
||||||
|
kind,
|
||||||
|
attr,
|
||||||
|
value,
|
||||||
|
case_sensitive,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
Some(c) => {
|
||||||
let tok = self
|
value.push(' ');
|
||||||
.buf
|
value.push(c.clone());
|
||||||
.next()
|
|
||||||
.expect("this is impossible because we have already peeked");
|
|
||||||
self.pos.next_char();
|
|
||||||
value.push(tok);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.devour_whitespace();
|
self.devour_whitespace();
|
||||||
|
|
||||||
assert!(self.buf.next() == Some(']'));
|
assert!(self.buf.next() == Some(']'));
|
||||||
|
}
|
||||||
|
None => todo!(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert!(self.buf.next() == Some(']'));
|
||||||
|
}
|
||||||
|
|
||||||
TokenKind::Attribute(Attribute {
|
TokenKind::Attribute(Attribute {
|
||||||
kind,
|
kind,
|
||||||
|
@ -348,8 +348,8 @@ pub(crate) enum CaseKind {
|
|||||||
impl Display for CaseKind {
|
impl Display for CaseKind {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::InsensitiveCapital => write!(f, "I"),
|
Self::InsensitiveCapital => write!(f, " I"),
|
||||||
Self::InsensitiveLowercase => write!(f, "i"),
|
Self::InsensitiveLowercase => write!(f, " i"),
|
||||||
Self::Sensitive => write!(f, ""),
|
Self::Sensitive => write!(f, ""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,10 +143,15 @@ mod test_selectors {
|
|||||||
selector_attribute_i_in_attr,
|
selector_attribute_i_in_attr,
|
||||||
"[atitr=val] {\n color: red;\n}\n"
|
"[atitr=val] {\n color: red;\n}\n"
|
||||||
);
|
);
|
||||||
// test!(
|
test!(
|
||||||
// selector_attribute_i_in_val,
|
selector_attribute_i_in_val,
|
||||||
// "[attr=vail] {\n color: red;\n}\n"
|
"[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!(
|
test!(
|
||||||
selector_attribute_equals,
|
selector_attribute_equals,
|
||||||
"[attr=val] {\n color: red;\n}\n"
|
"[attr=val] {\n color: red;\n}\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user