use crate::ns::*; /// Represents a lexical token. #[derive(Clone, PartialEq, Debug)] pub enum Token { Eof, Identifier(String), String(String), /// Numeric literal token. /// The numeric value is in character representation, which may be parsed /// through data type specific methods such as [`NumericLiteral::parse_double()`]. Number(String, NumberSuffix), RegExp { body: String, flags: String, }, CssNumber { value: f64, unit: Option, }, CssHashWord(String), CssBeginsWith, CssEndsWith, CssContains, CssListMatch, CssHreflangMatch, CssAtNamespace, CssAtMedia, CssAtFontFace, CssImportant, CssSemicolons, // Punctuator ColonColon, /// The `@` token. Attribute, /// The `..` token. Descendants, /// The `...` token. Ellipsis, ParenOpen, ParenClose, SquareOpen, SquareClose, BlockOpen, BlockClose, Dot, Semicolon, Comma, Lt, Gt, /// `<=` Le, /// `>=` Ge, Equals, NotEquals, StrictEquals, StrictNotEquals, Plus, Minus, Times, Div, Percent, Increment, Decrement, LeftShift, RightShift, UnsignedRightShift, Ampersand, Hat, Pipe, Tilde, LogicalAnd, LogicalXor, LogicalOr, Question, Exclamation, Colon, Assign, AddAssign, SubtractAssign, MultiplyAssign, DivideAssign, RemainderAssign, LeftShiftAssign, RightShiftAssign, UnsignedRightShiftAssign, BitwiseAndAssign, BitwiseXorAssign, BitwiseOrAssign, LogicalAndAssign, LogicalXorAssign, LogicalOrAssign, /// `**` Power, /// `**=` PowerAssign, /// `??` NullCoalescing, /// `??=` NullCoalescingAssign, /// `?.` OptionalChaining, // Reserved words As, Await, Break, Case, Catch, Class, Const, Continue, Default, Delete, Do, Else, Extends, False, Finally, For, Function, If, Implements, Import, In, Instanceof, Interface, Internal, Is, New, Not, Null, Package, Private, Protected, Public, Return, Super, Switch, This, Throw, True, Try, Typeof, Use, Var, Void, While, With, Yield, XmlWhitespace, XmlLtSlash, XmlSlashGt, XmlText(String), XmlName(String), XmlMarkup(String), XmlAttributeValue(String), } impl ToString for Token { /// Converts the token into a readable string. /// /// The method `Token::to_string` returns the following possible values: /// /// * `"end of program"` /// * `"identifier"` /// * `"string"` for string literal /// * `"number"` for numeric literal /// * `"regular expression"` for regular expression literal /// * `"'keyword'"` for reserved words /// * `"'punctuator'"` for various punctuators /// * `"punctuator"` for various punctuators /// * `"XML whitespace"` /// * `"''"` /// * `"XML text"` /// * `"XML name"` /// * `"XML markup"` /// * `"XML attribute value"` fn to_string(&self) -> String { (match self { Token::Eof => "end-of-file", Token::Identifier(_) => "identifier", Token::String(_) => "string", Token::Number(_, _) => "number", Token::RegExp { .. } => "regular expression", Token::CssNumber { .. } => "number", Token::CssHashWord(_) => "hash-word", Token::CssBeginsWith => "'^='", Token::CssEndsWith => "'$='", Token::CssContains => "'*='", Token::CssListMatch => "'~='", Token::CssHreflangMatch => "'|='", Token::CssAtNamespace => "at-namespace", Token::CssAtMedia => "at-media", Token::CssAtFontFace => "at-font-face", Token::CssImportant => "'!important'", Token::CssSemicolons => "semicolon", // Punctuators Token::ColonColon => "colon-colon", Token::Attribute => "'@'", Token::Descendants => "'..'", Token::Ellipsis => "'...'", Token::ParenOpen => "paren-open", Token::ParenClose => "paren-close", Token::SquareOpen => "square-open", Token::SquareClose => "square-close", Token::BlockOpen => "block-open", Token::BlockClose => "block-close", Token::Dot => "dot", Token::Semicolon => "semicolon", Token::Comma => "comma", Token::Lt => "less-than", Token::Gt => "greater-than", Token::Le => "'<='", Token::Ge => "'>='", Token::Equals => "'=='", Token::NotEquals => "'!='", Token::StrictEquals => "'==='", Token::StrictNotEquals => "'!=='", Token::Plus => "plus", Token::Minus => "minus", Token::Times => "times", Token::Div => "slash", Token::Percent => "percent", Token::Increment => "'++'", Token::Decrement => "'--'", Token::LeftShift => "'<<'", Token::RightShift => "'>>'", Token::UnsignedRightShift => "'>>>'", Token::Ampersand => "ampersand", Token::Hat => "hat", Token::Pipe => "pipe", Token::Tilde => "tilde", Token::LogicalAnd => "'&&'", Token::LogicalXor => "'^^'", Token::LogicalOr => "'||'", Token::Question => "question-mark", Token::Exclamation => "exclamation-mark", Token::Colon => "colon", Token::Assign => "'='", Token::AddAssign => "'+='", Token::SubtractAssign => "'-='", Token::MultiplyAssign => "'*='", Token::DivideAssign => "'/='", Token::RemainderAssign => "'%='", Token::LeftShiftAssign => "'<<='", Token::RightShiftAssign => "'>>='", Token::UnsignedRightShiftAssign => "'>>>='", Token::BitwiseAndAssign => "'&='", Token::BitwiseXorAssign => "'^='", Token::BitwiseOrAssign => "'|='", Token::LogicalAndAssign => "'&&='", Token::LogicalXorAssign => "'^^='", Token::LogicalOrAssign => "'||='", Token::Power => "'**'", Token::PowerAssign => "'**='", Token::NullCoalescing => "'??'", Token::NullCoalescingAssign => "'??='", Token::OptionalChaining => "'?.'", // Reserved words Token::As => "'as'", Token::Await => "'await'", Token::Break => "'break'", Token::Case => "'case'", Token::Catch => "'catch'", Token::Class => "'class'", Token::Const => "'const'", Token::Continue => "'continue'", Token::Default => "'default'", Token::Delete => "'delete'", Token::Do => "'do'", Token::Else => "'else'", Token::Extends => "'extends'", Token::False => "'false'", Token::Finally => "'finally'", Token::For => "'for'", Token::Function => "'function'", Token::If => "'if'", Token::Implements => "'implements'", Token::Import => "'import'", Token::In => "'in'", Token::Instanceof => "'instanceof'", Token::Interface => "'interface'", Token::Internal => "'internal'", Token::Is => "'is'", Token::New => "'new'", Token::Not => "'not'", Token::Null => "'null'", Token::Package => "'package'", Token::Private => "'private'", Token::Protected => "'protected'", Token::Public => "'public'", Token::Return => "'return'", Token::Super => "'super'", Token::Switch => "'switch'", Token::This => "'this'", Token::Throw => "'throw'", Token::True => "'true'", Token::Try => "'try'", Token::Typeof => "'typeof'", Token::Use => "'use'", Token::Var => "'var'", Token::Void => "'void'", Token::While => "'while'", Token::With => "'with'", Token::Yield => "'yield'", Token::XmlWhitespace => "XML whitespace", Token::XmlLtSlash => "' "'/>'", Token::XmlText(_) => "XML text", Token::XmlName(_) => "XML name", Token::XmlMarkup(_) => "XML markup", Token::XmlAttributeValue(_) => "XML attribute value", }).into() } } impl Token { pub fn is_context_keyword(token: &(Token, Location), keyword: &str) -> bool { if let Token::Identifier(name) = &token.0 { name == keyword && token.1.character_count() == name.len() } else { false } } /// Indicates whether the token is a reserved word. pub fn is_reserved_word(&self) -> bool { self.reserved_word_name().is_some() } pub fn is_identifier_name(&self) -> bool { matches!(self, Token::Identifier(_)) || self.is_reserved_word() } /// Tests whether the token is a reserved word and returns /// its *IdentifierName* string. pub fn reserved_word_name(&self) -> Option { match *self { Token::As => Some("as".into()), Token::Await => Some("await".into()), Token::Break => Some("break".into()), Token::Case => Some("case".into()), Token::Catch => Some("catch".into()), Token::Class => Some("class".into()), Token::Const => Some("const".into()), Token::Continue => Some("continue".into()), Token::Default => Some("default".into()), Token::Delete => Some("delete".into()), Token::Do => Some("do".into()), Token::Else => Some("else".into()), Token::Extends => Some("extends".into()), Token::False => Some("false".into()), Token::Finally => Some("finally".into()), Token::For => Some("for".into()), Token::Function => Some("function".into()), Token::If => Some("if".into()), Token::Implements => Some("implements".into()), Token::Import => Some("import".into()), Token::In => Some("in".into()), Token::Instanceof => Some("instanceof".into()), Token::Interface => Some("interface".into()), Token::Internal => Some("internal".into()), Token::Is => Some("is".into()), Token::New => Some("new".into()), Token::Not => Some("not".into()), Token::Null => Some("null".into()), Token::Package => Some("package".into()), Token::Private => Some("private".into()), Token::Protected => Some("protected".into()), Token::Public => Some("public".into()), Token::Return => Some("return".into()), Token::Super => Some("super".into()), Token::Switch => Some("switch".into()), Token::This => Some("this".into()), Token::Throw => Some("throw".into()), Token::True => Some("true".into()), Token::Try => Some("try".into()), Token::Typeof => Some("typeof".into()), Token::Use => Some("use".into()), Token::Var => Some("var".into()), Token::Void => Some("void".into()), Token::While => Some("while".into()), Token::With => Some("with".into()), Token::Yield => Some("yield".into()), _ => None, } } /// Converts a compound assignment, a logical assignment, or a nullish coalescing assignment to an *Operator* value. pub fn compound_assignment(&self) -> Option { match self { Self::AddAssign => Some(Operator::Add), Self::SubtractAssign => Some(Operator::Subtract), Self::MultiplyAssign => Some(Operator::Multiply), Self::DivideAssign => Some(Operator::Divide), Self::RemainderAssign => Some(Operator::Remainder), Self::PowerAssign => Some(Operator::Power), Self::LeftShiftAssign => Some(Operator::ShiftLeft), Self::RightShiftAssign => Some(Operator::ShiftRight), Self::UnsignedRightShiftAssign => Some(Operator::ShiftRightUnsigned), Self::BitwiseAndAssign => Some(Operator::BitwiseAnd), Self::BitwiseXorAssign => Some(Operator::BitwiseXor), Self::BitwiseOrAssign => Some(Operator::BitwiseOr), Self::LogicalAndAssign => Some(Operator::LogicalAnd), Self::LogicalXorAssign => Some(Operator::LogicalXor), Self::LogicalOrAssign => Some(Operator::LogicalOr), Self::NullCoalescingAssign => Some(Operator::NullCoalescing), _ => None, } } /// Converts this token into a binary operator, excluding /// `not in`, and `is not`. pub fn to_binary_operator(&self) -> Option { match self { Self::Times => Some(Operator::Multiply), Self::Div => Some(Operator::Divide), Self::Percent => Some(Operator::Remainder), Self::Plus => Some(Operator::Add), Self::Minus => Some(Operator::Subtract), Self::LeftShift => Some(Operator::ShiftLeft), Self::RightShift => Some(Operator::ShiftRight), Self::UnsignedRightShift => Some(Operator::ShiftRightUnsigned), Self::Lt => Some(Operator::Lt), Self::Gt => Some(Operator::Gt), Self::Le => Some(Operator::Le), Self::Ge => Some(Operator::Ge), Self::As => Some(Operator::As), Self::In => Some(Operator::In), Self::Is => Some(Operator::Is), Self::Instanceof => Some(Operator::Instanceof), Self::Equals => Some(Operator::Equals), Self::NotEquals => Some(Operator::NotEquals), Self::StrictEquals => Some(Operator::StrictEquals), Self::StrictNotEquals => Some(Operator::StrictNotEquals), Self::Ampersand => Some(Operator::BitwiseAnd), Self::Hat => Some(Operator::BitwiseXor), Self::Pipe => Some(Operator::BitwiseOr), Self::LogicalAnd => Some(Operator::LogicalAnd), Self::LogicalXor => Some(Operator::LogicalXor), Self::LogicalOr => Some(Operator::LogicalOr), Self::NullCoalescing => Some(Operator::NullCoalescing), Self::Power => Some(Operator::Power), _ => None, } } pub(crate) fn to_attribute(&self, location: &Location) -> Option { match self { Self::Public => Some(Attribute::Public(location.clone())), Self::Private => Some(Attribute::Private(location.clone())), Self::Protected => Some(Attribute::Protected(location.clone())), Self::Internal => Some(Attribute::Internal(location.clone())), Self::Identifier(ref name) => { Attribute::from_identifier_name(name, &location) }, _ => None, } } }