1use crate::ns::*;
2
3#[derive(Clone, PartialEq, Debug)]
5pub enum Token {
6 Eof,
7 Identifier(String),
8 String(String),
9 Number(String, NumberSuffix),
13 RegExp {
14 body: String,
15 flags: String,
16 },
17
18 CssNumber {
19 value: f64,
20 unit: Option<String>,
21 },
22 CssHashWord(String),
23 CssBeginsWith,
24 CssEndsWith,
25 CssContains,
26 CssListMatch,
27 CssHreflangMatch,
28 CssAtNamespace,
29 CssAtMedia,
30 CssAtFontFace,
31 CssAtImport,
32 CssImportant,
33 CssSemicolons,
34
35 ColonColon,
37 Attribute,
39 Descendants,
41 Ellipsis,
43 ParenOpen,
44 ParenClose,
45 SquareOpen,
46 SquareClose,
47 BlockOpen,
48 BlockClose,
49 Dot,
50 Semicolon,
51 Comma,
52 Lt,
53 Gt,
54 Le,
56 Ge,
58 Equals,
59 NotEquals,
60 StrictEquals,
61 StrictNotEquals,
62 Plus,
63 Minus,
64 Times,
65 Div,
66 Percent,
67 Increment,
68 Decrement,
69 LeftShift,
70 RightShift,
71 UnsignedRightShift,
72 Ampersand,
73 Hat,
74 Pipe,
75 Tilde,
76 LogicalAnd,
77 LogicalXor,
78 LogicalOr,
79 Question,
80 Exclamation,
81 Colon,
82 Assign,
83 AddAssign,
84 SubtractAssign,
85 MultiplyAssign,
86 DivideAssign,
87 RemainderAssign,
88 LeftShiftAssign,
89 RightShiftAssign,
90 UnsignedRightShiftAssign,
91 BitwiseAndAssign,
92 BitwiseXorAssign,
93 BitwiseOrAssign,
94 LogicalAndAssign,
95 LogicalXorAssign,
96 LogicalOrAssign,
97 Power,
99 PowerAssign,
101 NullCoalescing,
103 NullCoalescingAssign,
105 OptionalChaining,
107
108 As,
110 Await,
111 Break,
112 Case,
113 Catch,
114 Class,
115 Const,
116 Continue,
117 Default,
118 Delete,
119 Do,
120 Else,
121 Extends,
122 False,
123 Finally,
124 For,
125 Function,
126 If,
127 Implements,
128 Import,
129 In,
130 Instanceof,
131 Interface,
132 Internal,
133 Is,
134 New,
135 Not,
136 Null,
137 Package,
138 Private,
139 Protected,
140 Public,
141 Return,
142 Super,
143 Switch,
144 This,
145 Throw,
146 True,
147 Try,
148 Typeof,
149 Use,
150 Var,
151 Void,
152 While,
153 With,
154 Yield,
155
156 XmlWhitespace,
157 XmlLtSlash,
158 XmlSlashGt,
159 XmlText(String),
160 XmlName(String),
161 XmlMarkup(String),
162 XmlAttributeValue(String),
163}
164
165impl ToString for Token {
166 fn to_string(&self) -> String {
186 (match self {
187 Token::Eof => "end-of-file",
188 Token::Identifier(_) => "identifier",
189 Token::String(_) => "string",
190 Token::Number(_, _) => "number",
191 Token::RegExp { .. } => "regular expression",
192
193 Token::CssNumber { .. } => "number",
194 Token::CssHashWord(_) => "hash-word",
195 Token::CssBeginsWith => "'^='",
196 Token::CssEndsWith => "'$='",
197 Token::CssContains => "'*='",
198 Token::CssListMatch => "'~='",
199 Token::CssHreflangMatch => "'|='",
200 Token::CssAtNamespace => "at-namespace",
201 Token::CssAtMedia => "at-media",
202 Token::CssAtFontFace => "at-font-face",
203 Token::CssAtImport => "at-import",
204 Token::CssImportant => "'!important'",
205 Token::CssSemicolons => "semicolon",
206
207 Token::ColonColon => "colon-colon",
209 Token::Attribute => "'@'",
210 Token::Descendants => "'..'",
211 Token::Ellipsis => "'...'",
212 Token::ParenOpen => "paren-open",
213 Token::ParenClose => "paren-close",
214 Token::SquareOpen => "square-open",
215 Token::SquareClose => "square-close",
216 Token::BlockOpen => "block-open",
217 Token::BlockClose => "block-close",
218 Token::Dot => "dot",
219 Token::Semicolon => "semicolon",
220 Token::Comma => "comma",
221 Token::Lt => "less-than",
222 Token::Gt => "greater-than",
223 Token::Le => "'<='",
224 Token::Ge => "'>='",
225 Token::Equals => "'=='",
226 Token::NotEquals => "'!='",
227 Token::StrictEquals => "'==='",
228 Token::StrictNotEquals => "'!=='",
229 Token::Plus => "plus",
230 Token::Minus => "minus",
231 Token::Times => "times",
232 Token::Div => "slash",
233 Token::Percent => "percent",
234 Token::Increment => "'++'",
235 Token::Decrement => "'--'",
236 Token::LeftShift => "'<<'",
237 Token::RightShift => "'>>'",
238 Token::UnsignedRightShift => "'>>>'",
239 Token::Ampersand => "ampersand",
240 Token::Hat => "hat",
241 Token::Pipe => "pipe",
242 Token::Tilde => "tilde",
243 Token::LogicalAnd => "'&&'",
244 Token::LogicalXor => "'^^'",
245 Token::LogicalOr => "'||'",
246 Token::Question => "question-mark",
247 Token::Exclamation => "exclamation-mark",
248 Token::Colon => "colon",
249 Token::Assign => "'='",
250 Token::AddAssign => "'+='",
251 Token::SubtractAssign => "'-='",
252 Token::MultiplyAssign => "'*='",
253 Token::DivideAssign => "'/='",
254 Token::RemainderAssign => "'%='",
255 Token::LeftShiftAssign => "'<<='",
256 Token::RightShiftAssign => "'>>='",
257 Token::UnsignedRightShiftAssign => "'>>>='",
258 Token::BitwiseAndAssign => "'&='",
259 Token::BitwiseXorAssign => "'^='",
260 Token::BitwiseOrAssign => "'|='",
261 Token::LogicalAndAssign => "'&&='",
262 Token::LogicalXorAssign => "'^^='",
263 Token::LogicalOrAssign => "'||='",
264 Token::Power => "'**'",
265 Token::PowerAssign => "'**='",
266 Token::NullCoalescing => "'??'",
267 Token::NullCoalescingAssign => "'??='",
268 Token::OptionalChaining => "'?.'",
269
270 Token::As => "'as'",
272 Token::Await => "'await'",
273 Token::Break => "'break'",
274 Token::Case => "'case'",
275 Token::Catch => "'catch'",
276 Token::Class => "'class'",
277 Token::Const => "'const'",
278 Token::Continue => "'continue'",
279 Token::Default => "'default'",
280 Token::Delete => "'delete'",
281 Token::Do => "'do'",
282 Token::Else => "'else'",
283 Token::Extends => "'extends'",
284 Token::False => "'false'",
285 Token::Finally => "'finally'",
286 Token::For => "'for'",
287 Token::Function => "'function'",
288 Token::If => "'if'",
289 Token::Implements => "'implements'",
290 Token::Import => "'import'",
291 Token::In => "'in'",
292 Token::Instanceof => "'instanceof'",
293 Token::Interface => "'interface'",
294 Token::Internal => "'internal'",
295 Token::Is => "'is'",
296 Token::New => "'new'",
297 Token::Not => "'not'",
298 Token::Null => "'null'",
299 Token::Package => "'package'",
300 Token::Private => "'private'",
301 Token::Protected => "'protected'",
302 Token::Public => "'public'",
303 Token::Return => "'return'",
304 Token::Super => "'super'",
305 Token::Switch => "'switch'",
306 Token::This => "'this'",
307 Token::Throw => "'throw'",
308 Token::True => "'true'",
309 Token::Try => "'try'",
310 Token::Typeof => "'typeof'",
311 Token::Use => "'use'",
312 Token::Var => "'var'",
313 Token::Void => "'void'",
314 Token::While => "'while'",
315 Token::With => "'with'",
316 Token::Yield => "'yield'",
317
318 Token::XmlWhitespace => "XML whitespace",
319 Token::XmlLtSlash => "'</'",
320 Token::XmlSlashGt => "'/>'",
321 Token::XmlText(_) => "XML text",
322 Token::XmlName(_) => "XML name",
323 Token::XmlMarkup(_) => "XML markup",
324 Token::XmlAttributeValue(_) => "XML attribute value",
325 }).into()
326 }
327}
328
329impl Token {
330 pub fn is_context_keyword(token: &(Token, Location), keyword: &str) -> bool {
331 if let Token::Identifier(name) = &token.0 {
332 name == keyword && token.1.character_count() == name.len()
333 } else {
334 false
335 }
336 }
337
338 pub fn is_reserved_word(&self) -> bool {
340 self.reserved_word_name().is_some()
341 }
342
343 pub fn is_identifier_name(&self) -> bool {
344 matches!(self, Token::Identifier(_)) || self.is_reserved_word()
345 }
346
347 pub fn reserved_word_name(&self) -> Option<String> {
350 match *self {
351 Token::As => Some("as".into()),
352 Token::Await => Some("await".into()),
353 Token::Break => Some("break".into()),
354 Token::Case => Some("case".into()),
355 Token::Catch => Some("catch".into()),
356 Token::Class => Some("class".into()),
357 Token::Const => Some("const".into()),
358 Token::Continue => Some("continue".into()),
359 Token::Default => Some("default".into()),
360 Token::Delete => Some("delete".into()),
361 Token::Do => Some("do".into()),
362 Token::Else => Some("else".into()),
363 Token::Extends => Some("extends".into()),
364 Token::False => Some("false".into()),
365 Token::Finally => Some("finally".into()),
366 Token::For => Some("for".into()),
367 Token::Function => Some("function".into()),
368 Token::If => Some("if".into()),
369 Token::Implements => Some("implements".into()),
370 Token::Import => Some("import".into()),
371 Token::In => Some("in".into()),
372 Token::Instanceof => Some("instanceof".into()),
373 Token::Interface => Some("interface".into()),
374 Token::Internal => Some("internal".into()),
375 Token::Is => Some("is".into()),
376 Token::New => Some("new".into()),
377 Token::Not => Some("not".into()),
378 Token::Null => Some("null".into()),
379 Token::Package => Some("package".into()),
380 Token::Private => Some("private".into()),
381 Token::Protected => Some("protected".into()),
382 Token::Public => Some("public".into()),
383 Token::Return => Some("return".into()),
384 Token::Super => Some("super".into()),
385 Token::Switch => Some("switch".into()),
386 Token::This => Some("this".into()),
387 Token::Throw => Some("throw".into()),
388 Token::True => Some("true".into()),
389 Token::Try => Some("try".into()),
390 Token::Typeof => Some("typeof".into()),
391 Token::Use => Some("use".into()),
392 Token::Var => Some("var".into()),
393 Token::Void => Some("void".into()),
394 Token::While => Some("while".into()),
395 Token::With => Some("with".into()),
396 Token::Yield => Some("yield".into()),
397 _ => None,
398 }
399 }
400
401 pub fn compound_assignment(&self) -> Option<Operator> {
403 match self {
404 Self::AddAssign => Some(Operator::Add),
405 Self::SubtractAssign => Some(Operator::Subtract),
406 Self::MultiplyAssign => Some(Operator::Multiply),
407 Self::DivideAssign => Some(Operator::Divide),
408 Self::RemainderAssign => Some(Operator::Remainder),
409 Self::PowerAssign => Some(Operator::Power),
410 Self::LeftShiftAssign => Some(Operator::ShiftLeft),
411 Self::RightShiftAssign => Some(Operator::ShiftRight),
412 Self::UnsignedRightShiftAssign => Some(Operator::ShiftRightUnsigned),
413 Self::BitwiseAndAssign => Some(Operator::BitwiseAnd),
414 Self::BitwiseXorAssign => Some(Operator::BitwiseXor),
415 Self::BitwiseOrAssign => Some(Operator::BitwiseOr),
416 Self::LogicalAndAssign => Some(Operator::LogicalAnd),
417 Self::LogicalXorAssign => Some(Operator::LogicalXor),
418 Self::LogicalOrAssign => Some(Operator::LogicalOr),
419 Self::NullCoalescingAssign => Some(Operator::NullCoalescing),
420 _ => None,
421 }
422 }
423
424 pub fn to_binary_operator(&self) -> Option<Operator> {
427 match self {
428 Self::Times => Some(Operator::Multiply),
429 Self::Div => Some(Operator::Divide),
430 Self::Percent => Some(Operator::Remainder),
431 Self::Plus => Some(Operator::Add),
432 Self::Minus => Some(Operator::Subtract),
433 Self::LeftShift => Some(Operator::ShiftLeft),
434 Self::RightShift => Some(Operator::ShiftRight),
435 Self::UnsignedRightShift => Some(Operator::ShiftRightUnsigned),
436 Self::Lt => Some(Operator::Lt),
437 Self::Gt => Some(Operator::Gt),
438 Self::Le => Some(Operator::Le),
439 Self::Ge => Some(Operator::Ge),
440 Self::As => Some(Operator::As),
441 Self::In => Some(Operator::In),
442 Self::Is => Some(Operator::Is),
443 Self::Instanceof => Some(Operator::Instanceof),
444 Self::Equals => Some(Operator::Equals),
445 Self::NotEquals => Some(Operator::NotEquals),
446 Self::StrictEquals => Some(Operator::StrictEquals),
447 Self::StrictNotEquals => Some(Operator::StrictNotEquals),
448 Self::Ampersand => Some(Operator::BitwiseAnd),
449 Self::Hat => Some(Operator::BitwiseXor),
450 Self::Pipe => Some(Operator::BitwiseOr),
451 Self::LogicalAnd => Some(Operator::LogicalAnd),
452 Self::LogicalXor => Some(Operator::LogicalXor),
453 Self::LogicalOr => Some(Operator::LogicalOr),
454 Self::NullCoalescing => Some(Operator::NullCoalescing),
455 Self::Power => Some(Operator::Power),
456 _ => None,
457 }
458 }
459
460 pub(crate) fn to_attribute(&self, location: &Location) -> Option<Attribute> {
461 match self {
462 Self::Public => Some(Attribute::Public(location.clone())),
463 Self::Private => Some(Attribute::Private(location.clone())),
464 Self::Protected => Some(Attribute::Protected(location.clone())),
465 Self::Internal => Some(Attribute::Internal(location.clone())),
466 Self::Identifier(ref name) => {
467 Attribute::from_identifier_name(name, &location)
468 },
469 _ => None,
470 }
471 }
472}