use crate::ns::*;
#[derive(Clone, PartialEq, Debug)]
pub enum Token {
Eof,
Identifier(String),
String(String),
Number(String, NumberSuffix),
RegExp {
body: String,
flags: String,
},
CssNumber {
value: f64,
unit: Option<String>,
},
CssHashWord(String),
CssBeginsWith,
CssEndsWith,
CssContains,
CssListMatch,
CssHreflangMatch,
CssAtNamespace,
CssAtMedia,
CssAtFontFace,
CssImportant,
CssSemicolons,
ColonColon,
Attribute,
Descendants,
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,
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 {
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",
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 => "'?.'",
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::XmlSlashGt => "'/>'",
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
}
}
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()
}
pub fn reserved_word_name(&self) -> Option<String> {
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,
}
}
pub fn compound_assignment(&self) -> Option<Operator> {
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,
}
}
pub fn to_binary_operator(&self) -> Option<Operator> {
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<Attribute> {
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,
}
}
}