From adc94ffaa5f53cbbc63c038779f157841afb9d57 Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Mon, 6 Jan 2020 00:39:49 -0500 Subject: [PATCH] Lex tokens starting with `!` (`!important` and `!=`) --- src/lexer.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index eba078c..209ff19 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -2,7 +2,7 @@ use std::convert::TryFrom; use std::iter::Peekable; use std::str::Chars; -use crate::common::{Keyword, Pos, Symbol}; +use crate::common::{Keyword, Op, Pos, Symbol}; use crate::selector::{Attribute, AttributeKind, Selector}; use crate::units::Unit; use crate::{Token, TokenKind, Whitespace}; @@ -32,7 +32,7 @@ impl<'a> Iterator for Lexer<'a> { }}; } let kind: TokenKind = match self.buf.peek().unwrap_or(&'\0') { - 'a'..='z' | 'A'..='Z' => self.lex_ident(), + 'a'..='z' | 'A'..='Z' | '-' | '_' => self.lex_ident(), '@' => self.lex_at_rule(), '0'..='9' => self.lex_num(), '$' => self.lex_variable(), @@ -63,6 +63,7 @@ impl<'a> Iterator for Lexer<'a> { self.pos.next_char(); self.lex_attr() } + '!' => self.lex_exclamation(), '<' => symbol!(self, Lt), '>' => symbol!(self, Gt), '\0' => return None, @@ -89,6 +90,30 @@ impl<'a> Lexer<'a> { } } + fn lex_exclamation(&mut self) -> TokenKind { + self.buf.next(); + self.pos.next_char(); + macro_rules! assert_char { + ($self:ident, $($char:literal)*) => { + $( + assert_eq!($char, $self.buf.next().expect("expected char").to_ascii_lowercase(), "expected keyword `important`"); + )* + } + }; + match self.buf.peek() { + Some('i') | Some('I') => { + self.buf.next(); + assert_char!(self, 'm' 'p' 'o' 'r' 't' 'a' 'n' 't'); + } + Some('=') => { + self.buf.next(); + return TokenKind::Op(Op::NotEqual); + } + _ => todo!("expected either `i` or `=` after `!`"), + }; + TokenKind::Keyword(Keyword::Important) + } + fn devour_whitespace(&mut self) { while let Some(c) = self.buf.peek() { if !is_whitespace(*c) {