use std::collections::HashMap; use std::convert::TryFrom; use std::default::Default; use std::fmt::{self, Display}; use crate::mixin::Mixin; use crate::Token; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Symbol { /// . Period, /// # Hash, /// @ At, /// $ Dollar, /// ( OpenParen, /// ) CloseParen, /// { OpenCurlyBrace, /// } CloseCurlyBrace, /// [ OpenSquareBrace, /// ] CloseSquareBrace, /// , Comma, /// + Plus, /// - Minus, /// * Mul, /// / Div, /// : Colon, /// ; SemiColon, /// ~ Tilde, /// > Gt, /// < Lt, /// ^ Xor, /// = Equal, /// | BitOr, /// & BitAnd, /// % Percent, /// " DoubleQuote, /// ' SingleQuote, /// ? QuestionMark, /// \ BackSlash, } impl Display for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Period => write!(f, "."), Self::Hash => write!(f, "#"), Self::At => write!(f, "@"), Self::Dollar => write!(f, "$"), Self::OpenParen => write!(f, "("), Self::CloseParen => write!(f, "),"), Self::OpenCurlyBrace => write!(f, "{{"), Self::CloseCurlyBrace => write!(f, "}}"), Self::OpenSquareBrace => write!(f, "["), Self::CloseSquareBrace => write!(f, "]"), Self::Comma => write!(f, ","), Self::Plus => write!(f, "+"), Self::Minus => write!(f, "-"), Self::Mul => write!(f, "*"), Self::Div => write!(f, "/"), Self::Colon => write!(f, ":"), Self::SemiColon => write!(f, ";"), Self::Tilde => write!(f, "~"), Self::Gt => write!(f, ">"), Self::Lt => write!(f, "<"), Self::Xor => write!(f, "^"), Self::Equal => write!(f, "="), Self::BitOr => write!(f, "|"), Self::BitAnd => write!(f, "&"), Self::Percent => write!(f, "%"), Self::DoubleQuote => write!(f, "\""), Self::SingleQuote => write!(f, "'"), Self::QuestionMark => write!(f, "?"), Self::BackSlash => write!(f, "\\"), } } } impl TryFrom for Symbol { type Error = &'static str; fn try_from(c: char) -> Result { match c { '.' => Ok(Self::Period), '#' => Ok(Self::Hash), '@' => Ok(Self::At), '$' => Ok(Self::Dollar), '(' => Ok(Self::OpenParen), ')' => Ok(Self::CloseParen), '{' => Ok(Self::OpenCurlyBrace), '}' => Ok(Self::CloseCurlyBrace), '[' => Ok(Self::OpenSquareBrace), ']' => Ok(Self::CloseSquareBrace), ',' => Ok(Self::Comma), '+' => Ok(Self::Plus), '-' => Ok(Self::Minus), '*' => Ok(Self::Mul), '/' => Ok(Self::Div), ':' => Ok(Self::Colon), ';' => Ok(Self::SemiColon), '~' => Ok(Self::Tilde), '>' => Ok(Self::Gt), '<' => Ok(Self::Lt), '^' => Ok(Self::Xor), '=' => Ok(Self::Equal), '|' => Ok(Self::BitOr), '&' => Ok(Self::BitAnd), '%' => Ok(Self::Percent), '"' => Ok(Self::DoubleQuote), '\'' => Ok(Self::SingleQuote), '?' => Ok(Self::QuestionMark), '\\' => Ok(Self::BackSlash), _ => Err("invalid symbol"), } } } #[derive(Clone, Debug, Eq, PartialEq)] pub struct MediaQuery {} #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Whitespace { Space, Tab, Newline, CarriageReturn, } impl Display for Whitespace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Space => write!(f, " "), Self::Tab => write!(f, "\t"), Self::Newline => writeln!(f), Self::CarriageReturn => write!(f, "\r"), } } } impl TryFrom for Whitespace { type Error = &'static str; fn try_from(c: char) -> Result { match c { ' ' => Ok(Self::Space), '\t' => Ok(Self::Tab), '\n' => Ok(Self::Newline), '\r' => Ok(Self::CarriageReturn), _ => Err("invalid whitespace"), } } } #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Op { Equal, NotEqual, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, Plus, Minus, Mul, Div, Rem, } impl Display for Op { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Equal => write!(f, "=="), Self::NotEqual => write!(f, "!="), Self::GreaterThanEqual => write!(f, ">="), Self::LessThanEqual => write!(f, "<="), Self::GreaterThan => write!(f, ">"), Self::LessThan => write!(f, "<"), Self::Plus => write!(f, "+"), Self::Minus => write!(f, "-"), Self::Mul => write!(f, "*"), Self::Div => write!(f, "/"), Self::Rem => write!(f, "%"), } } } #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Keyword { Important, Infinity, NaN, Auto, Inherit, Initial, Unset, True, False, Not, And, Or, Null, In, } impl Display for Keyword { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Important => write!(f, "!important"), Self::Infinity => write!(f, "Infinity"), Self::NaN => write!(f, "NaN"), Self::Auto => write!(f, "auto"), Self::Inherit => write!(f, "inherit"), Self::Initial => write!(f, "initial"), Self::Unset => write!(f, "unset"), Self::True => write!(f, "true"), Self::False => write!(f, "false"), Self::Not => write!(f, "not"), Self::And => write!(f, "and"), Self::Or => write!(f, "or"), Self::Null => write!(f, "null"), Self::In => write!(f, "in"), } } } impl Into<&'static str> for Keyword { fn into(self) -> &'static str { match self { Self::Important => "!important", Self::Infinity => "Infinity", Self::NaN => "NaN", Self::Auto => "auto", Self::Inherit => "inherit", Self::Initial => "initial", Self::Unset => "unset", Self::True => "true", Self::False => "false", Self::Not => "not", Self::And => "and", Self::Or => "or", Self::Null => "null", Self::In => "in", } } } impl TryFrom<&str> for Keyword { type Error = &'static str; fn try_from(kw: &str) -> Result { // todo: case insensitive? match kw { "important" => Ok(Self::Important), "infinity" => Ok(Self::Infinity), "nan" => Ok(Self::NaN), "auto" => Ok(Self::Auto), "inherit" => Ok(Self::Inherit), "initial" => Ok(Self::Initial), "unset" => Ok(Self::Unset), "true" => Ok(Self::True), "false" => Ok(Self::False), "not" => Ok(Self::Not), "and" => Ok(Self::And), "or" => Ok(Self::Or), "null" => Ok(Self::Null), "in" => Ok(Self::In), _ => Err("invalid keyword"), } } } #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Pos { line: u32, column: u32, } impl Pos { pub const fn new() -> Self { Pos { line: 1, column: 1 } } pub const fn line(self) -> u32 { self.line } pub const fn column(self) -> u32 { self.column } pub fn newline(&mut self) { self.line += 1; self.column = 0; } pub fn next_char(&mut self) { self.column += 1; } pub fn chars(&mut self, num: u32) { self.column += num; } } impl Display for Pos { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "line:{} col:{}", self.line, self.column) } } #[derive(Debug, Clone, Default)] pub(crate) struct Scope { pub vars: HashMap>, pub mixins: HashMap, } impl Scope { #[must_use] pub fn new() -> Self { Self { vars: HashMap::new(), mixins: HashMap::new(), } } pub fn merge(&mut self, other: Scope) { self.vars.extend(other.vars); self.mixins.extend(other.mixins); } } #[derive(Debug)] pub enum Printer { Error(Pos, String), Warn(Pos, String), Debug(Pos, String), }