use crate::ns::*; /// Represents a lexical token. #[derive(Clone, PartialEq, Debug)] pub enum Token { Eof, Identifier(String), StringLiteral(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()`]. NumericLiteral(String), RegExpLiteral { body: String, flags: String, }, // Punctuator ColonColon, /// The `@` token. Attribute, /// The `..` token. Descendants, /// The `...` token. Ellipsis, LeftParen, RightParen, LeftBracket, RightBracket, LeftBrace, RightBrace, Dot, Semicolon, Comma, Lt, Gt, /// `<=` Le, /// `>=` Ge, Equals, NotEquals, StrictEquals, StrictNotEquals, Plus, Minus, Times, Div, Remainder, Increment, Decrement, LeftShift, RightShift, UnsignedRightShift, BitwiseAnd, BitwiseXor, BitwiseOr, BitwiseNot, 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, 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 word (including surrounding apostrophes) /// * `"'punctuator'"` for punctuator (including surrounding apostrophes) /// * `"XML whitespace"` /// * `"''"` /// * `"XML text"` /// * `"XML name"` /// * `"XML markup"` /// * `"XML attribute value"` fn to_string(&self) -> String { (match self { Token::Eof => "end of program", Token::Identifier(_) => "identifier", Token::StringLiteral(_) => "string", Token::NumericLiteral(_) => "number", Token::RegExpLiteral { .. } => "regular expression", // Punctuators Token::ColonColon => "'::'", Token::Attribute => "'@'", Token::Descendants => "'..'", Token::Ellipsis => "'...'", Token::LeftParen => "'('", Token::RightParen => "')'", Token::LeftBracket => "'['", Token::RightBracket => "']'", Token::LeftBrace => "'{'", Token::RightBrace => "'}'", Token::Dot => "'.'", Token::Semicolon => "';'", Token::Comma => "','", Token::Lt => "'<'", Token::Gt => "'>'", Token::Le => "'<='", Token::Ge => "'>='", Token::Equals => "'=='", Token::NotEquals => "'!='", Token::StrictEquals => "'==='", Token::StrictNotEquals => "'!=='", Token::Plus => "'+'", Token::Minus => "'-'", Token::Times => "'*'", Token::Div => "'/'", Token::Remainder => "'%'", Token::Increment => "'++'", Token::Decrement => "'--'", Token::LeftShift => "'<<'", Token::RightShift => "'>>'", Token::UnsignedRightShift => "'>>>'", Token::BitwiseAnd => "'&'", Token::BitwiseXor => "'^'", Token::BitwiseOr => "'|'", Token::BitwiseNot => "'~'", Token::LogicalAnd => "'&&'", Token::LogicalXor => "'^^'", Token::LogicalOr => "'||'", Token::Question => "'?'", Token::Exclamation => "'!'", Token::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::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() } /// 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::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::Remainder => 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::In => Some(Operator::In), Self::Is => Some(Operator::Is), Self::Equals => Some(Operator::Equals), Self::NotEquals => Some(Operator::NotEquals), Self::StrictEquals => Some(Operator::StrictEquals), Self::StrictNotEquals => Some(Operator::StrictNotEquals), Self::BitwiseAnd => Some(Operator::BitwiseAnd), Self::BitwiseXor => Some(Operator::BitwiseXor), Self::BitwiseOr => 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, } } }