Skip to main content

boa_ast/keyword/
mod.rs

1//! The `Keyword` AST node, which represents reserved words of the ECMAScript language.
2//!
3//! The [specification][spec] defines keywords as tokens that match an `IdentifierName`, but also
4//! have special meaning in ECMAScript. In ECMAScript, you cannot use these reserved words as variables,
5//! labels, or function names.
6//!
7//! The [MDN documentation][mdn] contains a more extensive explanation about keywords.
8//!
9//! [spec]: https://tc39.es/ecma262/#sec-keywords-and-reserved-words
10//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords
11
12use crate::expression::operator::binary::{BinaryOp, RelationalOp};
13use boa_interner::Sym;
14use boa_macros::utf16;
15use std::{convert::TryFrom, error, fmt, str::FromStr};
16
17#[cfg(test)]
18mod tests;
19
20/// List of keywords recognized by the JavaScript grammar.
21///
22/// See the [module-level documentation][self] for more details.
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[derive(Clone, Copy, PartialEq, Eq, Debug)]
25pub enum Keyword {
26    /// The `await` keyword.
27    ///
28    /// More information:
29    ///  - [ECMAScript reference][spec]
30    ///  - [MDN documentation][mdn]
31    ///
32    /// [spec]: https://tc39.es/ecma262/#prod-AwaitExpression
33    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
34    Await,
35
36    /// The `async` keyword.
37    ///
38    /// More information:
39    ///  - [ECMAScript reference][spec]
40    ///  - [MDN documentation][mdn]
41    ///
42    /// [spec]: https://tc39.es/ecma262/#prod-AsyncMethod
43    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
44    Async,
45
46    /// The `break` keyword.
47    ///
48    /// More information:
49    ///  - [break `Node` documentation][node]
50    ///  - [ECMAScript reference][spec]
51    ///  - [MDN documentation][mdn]
52    ///
53    /// [spec]: https://tc39.es/ecma262/#prod-BreakStatement
54    /// [node]: ../node/enum.Node.html#variant.Break
55    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break
56    Break,
57
58    /// The `case` keyword.
59    ///
60    /// More information:
61    ///  - [switch `Node` documentation][node]
62    ///  - [ECMAScript reference][spec]
63    ///  - [MDN documentation][mdn]
64    ///
65    /// [spec]: https://tc39.es/ecma262/#prod-CaseClause
66    /// [node]: ../node/enum.Node.html#variant.Switch
67    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch
68    Case,
69
70    /// The `catch` keyword.
71    ///
72    /// More information:
73    ///  - [try `Node` documentation][node]
74    ///  - [ECMAScript reference][spec]
75    ///  - [MDN documentation][mdn]
76    ///
77    /// [spec]: https://tc39.es/ecma262/#prod-Catch
78    /// [node]: ../node/enum.Node.html#variant.Try
79    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
80    Catch,
81
82    /// The `class` keyword.
83    ///
84    /// More information:
85    ///  - [ECMAScript reference][spec]
86    ///  - [MDN documentation][mdn]
87    ///
88    /// [spec]: https://tc39.es/ecma262/#prod-ClassDeclaration
89    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class
90    Class,
91
92    /// The `continue` keyword.
93    ///
94    /// More information:
95    ///  - [continue `Node` documentation][node]
96    ///  - [ECMAScript reference][spec]
97    ///  - [MDN documentation][mdn]
98    ///
99    /// [spec]: https://tc39.es/ecma262/#prod-ContinueStatement
100    /// [node]: ../node/enum.Node.html#variant.Continue
101    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue
102    Continue,
103
104    /// The `const` keyword.
105    ///
106    /// More information:
107    ///  - [const `Node` documentation][node]
108    ///  - [ECMAScript reference][spec]
109    ///  - [MDN documentation][mdn]
110    ///
111    /// [spec]: https://tc39.es/ecma262/#sec-let-and-const-declarations
112    /// [node]: ../node/enum.Node.html#variant.ConstDecl
113    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
114    Const,
115
116    /// The `debugger` keyword.
117    ///
118    /// More information:
119    ///  - [ECMAScript reference][spec]
120    ///  - [MDN documentation][mdn]
121    ///
122    /// [spec]: https://tc39.es/ecma262/#sec-debugger-statement
123    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger
124    Debugger,
125
126    /// The `default` keyword.
127    ///
128    /// More information:
129    ///  - [switch `Node` documentation][node]
130    ///  - [ECMAScript reference default clause][spec-clause]
131    ///  - [ECMAScript reference default export][spec-export]
132    ///  - [MDN documentation][mdn]
133    ///
134    /// [node]: ../node/enum.Node.html#variant.Switch
135    /// [spec-clause]: https://tc39.es/ecma262/#prod-DefaultClause
136    /// [spec-export]: https://tc39.es/ecma262/#prod-ImportedDefaultBinding
137    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/default
138    Default,
139
140    /// The `delete` keyword.
141    ///
142    /// More information:
143    ///  - [delete `UnaryOp` documentation][unary]
144    ///  - [ECMAScript reference][spec]
145    ///  - [MDN documentation][mdn]
146    ///
147    /// [spec]: https://tc39.es/ecma262/#sec-delete-operator
148    /// [unary]: ../op/enum.UnaryOp.html#variant.Delete
149    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
150    Delete,
151
152    /// The `do` keyword.
153    ///
154    /// More information:
155    ///  - [ECMAScript reference][spec]
156    ///  - [MDN documentation][mdn]
157    ///
158    /// [spec]: https://tc39.es/ecma262/#sec-do-while-statement
159    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/do...while
160    Do,
161
162    /// The `else` keyword.
163    ///
164    /// More information:
165    ///  - [if `Node` documentation][node]
166    ///  - [ECMAScript reference][spec]
167    ///  - [MDN documentation][mdn]
168    ///
169    /// [node]: ../node/enum.Node.html#variant.If
170    /// [spec]: https://tc39.es/ecma262/#prod-IfStatement
171    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else
172    Else,
173
174    /// The `enum` keyword.
175    ///
176    /// Future reserved keyword.
177    Enum,
178
179    /// The `export` keyword.
180    ///
181    /// More information:
182    ///  - [ECMAScript reference][spec]
183    ///  - [MDN documentation][mdn]
184    ///
185    /// [spec]: https://tc39.es/ecma262/#sec-exports
186    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
187    Export,
188
189    /// The `extends` keyword.
190    ///
191    /// More information:
192    ///  - [ECMAScript reference][spec]
193    ///  - [MDN documentation][mdn]
194    ///
195    /// [spec]: https://tc39.es/ecma262/#prod-ClassHeritage
196    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
197    Extends,
198
199    /// The `finally` keyword.
200    ///
201    /// More information:
202    ///  - [try `Node` documentation][node]
203    ///  - [ECMAScript reference][spec]
204    ///  - [MDN documentation][mdn]
205    ///
206    /// [node]: ../node/enum.Node.html#variant.Try
207    /// [spec]: https://tc39.es/ecma262/#prod-Finally
208    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
209    Finally,
210
211    /// The `for` keyword.
212    ///
213    /// More information:
214    ///  - [for loop `Node` documentation][node]
215    ///  - [ECMAScript reference][spec]
216    ///  - [MDN documentation][mdn]
217    ///
218    /// [node]: ../node/enum.Node.html#variant.ForLoop
219    /// [spec]: https://tc39.es/ecma262/#prod-ForDeclaration
220    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
221    For,
222
223    /// The `function` keyword.
224    ///
225    /// More information:
226    ///  - [function `Node` documentation][node]
227    ///  - [ECMAScript reference][spec]
228    ///  - [MDN documentation][mdn]
229    ///
230    /// [node]: ../node/enum.Node.html#variant.FunctionDecl
231    /// [spec]: https://tc39.es/ecma262/#sec-terms-and-definitions-function
232    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function
233    Function,
234
235    /// The `if` keyword.
236    ///
237    /// More information:
238    ///  - [if `Node` documentation][node]
239    ///  - [ECMAScript reference][spec]
240    ///  - [MDN documentation][mdn]
241    ///
242    /// [node]: ../node/enum.Node.html#variant.If
243    /// [spec]: https://tc39.es/ecma262/#prod-IfStatement
244    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else
245    If,
246
247    /// The `in` keyword.
248    ///
249    /// More information:
250    ///  - [ECMAScript reference][spec]
251    ///  - [MDN documentation][mdn]
252    ///
253    /// [spec]: https://tc39.es/ecma262/#prod-RelationalExpression
254    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in
255    In,
256
257    /// The `instanceof` keyword.
258    ///
259    /// More information:
260    ///  - [ECMAScript reference][spec]
261    ///  - [MDN documentation][mdn]
262    ///
263    /// [spec]: https://tc39.es/ecma262/#sec-instanceofoperator
264    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
265    InstanceOf,
266
267    /// The `import` keyword.
268    ///
269    /// More information:
270    ///  - [ECMAScript reference][spec]
271    ///  - [MDN documentation][mdn]
272    ///
273    /// [spec]: https://tc39.es/ecma262/#sec-imports
274    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
275    Import,
276
277    /// The `let` keyword.
278    ///
279    /// More information:
280    ///  - [let `Node` documentation][node]
281    ///  - [ECMAScript reference][spec]
282    ///  - [MDN documentation][mdn]
283    ///
284    /// [node]: ../node/enum.Node.html#variant.LetDecl
285    /// [spec]: https://tc39.es/ecma262/#sec-let-and-const-declarations
286    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
287    Let,
288
289    /// The `new` keyword.
290    ///
291    /// More information:
292    ///  - [new `Node` documentation][node]
293    ///  - [ECMAScript reference][spec]
294    ///  - [MDN documentation][mdn]
295    ///
296    /// [node]: ../node/enum.Node.html#variant.New
297    /// [spec]: https://tc39.es/ecma262/#prod-NewExpression
298    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
299    New,
300
301    /// The `of` keyword.
302    ///
303    /// More information:
304    ///  - [ECMAScript reference][spec]
305    ///  - [MDN documentation][mdn]
306    ///
307    /// [spec]: https://tc39.es/ecma262/#sec-for-in-and-for-of-statements
308    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
309    Of,
310
311    /// The `return` keyword
312    ///
313    /// More information:
314    ///  - [return `Node` documentation][node]
315    ///  - [ECMAScript reference][spec]
316    ///  - [MDN documentation][mdn]
317    ///
318    /// [node]: ../node/enum.Node.html#variant.Return
319    /// [spec]: https://tc39.es/ecma262/#prod-ReturnStatement
320    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return
321    Return,
322
323    /// The `super` keyword
324    ///
325    /// More information:
326    ///  - [ECMAScript reference][spec]
327    ///  - [MDN documentation][mdn]
328    ///
329    /// [spec]: https://tc39.es/ecma262/#sec-super-keyword
330    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super
331    Super,
332
333    /// The `switch` keyword.
334    ///
335    /// More information:
336    ///  - [switch `Node` documentation][node]
337    ///  - [ECMAScript reference][spec]
338    ///  - [MDN documentation][mdn]
339    ///
340    /// [node]: ../node/enum.Node.html#variant.Switch
341    /// [spec]: https://tc39.es/ecma262/#prod-SwitchStatement
342    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch
343    Switch,
344
345    /// The `this` keyword.
346    ///
347    /// More information:
348    ///  - [this `Node` documentation][node]
349    ///  - [ECMAScript reference][spec]
350    ///  - [MDN documentation][mdn]
351    ///
352    /// [node]: ../node/enum.Node.html#variant.This
353    /// [spec]: https://tc39.es/ecma262/#sec-this-keyword
354    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
355    This,
356
357    /// The `throw` keyword.
358    ///
359    /// More information:
360    ///  - [throw `Node` documentation][node]
361    ///  - [ECMAScript reference][spec]
362    ///  - [MDN documentation][mdn]
363    ///
364    /// [node]: ../node/enum.Node.html#variant.Throw
365    /// [spec]: https://tc39.es/ecma262/#sec-throw-statement
366    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw
367    Throw,
368
369    /// The `try` keyword.
370    ///
371    /// More information:
372    ///  - [try `Node` documentation][node]
373    ///  - [ECMAScript reference][spec]
374    ///  - [MDN documentation][mdn]
375    ///
376    /// [node]: ../node/enum.Node.html#variant.Try
377    /// [spec]: https://tc39.es/ecma262/#prod-TryStatement
378    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
379    Try,
380
381    /// The `typeof` keyword.
382    ///
383    /// More information:
384    ///  - [typeof `UnaryOp` documentation][unary]
385    ///  - [ECMAScript reference][spec]
386    ///  - [MDN documentation][mdn]
387    ///
388    /// [unary]: ../op/enum.UnaryOp.html#variant.TypeOf
389    /// [spec]: https://tc39.es/ecma262/#sec-typeof-operator
390    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
391    TypeOf,
392
393    /// The `var` keyword.
394    ///
395    /// More information:
396    ///  - [var `Node` documentation][node]
397    ///  - [ECMAScript reference][spec]
398    ///  - [MDN documentation][mdn]
399    ///
400    /// [node]: ../node/enum.Node.html#variant.VarDecl
401    /// [spec]: https://tc39.es/ecma262/#prod-VariableStatement
402    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
403    Var,
404
405    /// The `void` keyword.
406    ///
407    /// More information:
408    ///  - [void `UnaryOp` documentation][unary]
409    ///  - [ECMAScript reference][spec]
410    ///  - [MDN documentation][mdn]
411    ///
412    /// [unary]: ../op/enum.UnaryOp.html#variant.Void
413    /// [spec]: https://tc39.es/ecma262/#sec-void-operator
414    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
415    Void,
416
417    /// The `while` keyword.
418    ///
419    /// More information:
420    ///  - [while `Node` documentation][node]
421    ///  - [ECMAScript reference][spec]
422    ///  - [MDN documentation][mdn]
423    ///
424    /// [node]: ../node/enum.Node.html#variant.While
425    /// [spec]: https://tc39.es/ecma262/#prod-grammar-notation-WhileStatement
426    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while
427    While,
428
429    /// The `with` keyword.
430    ///
431    /// More information:
432    ///  - [ECMAScript reference][spec]
433    ///  - [MDN documentation][mdn]
434    ///
435    /// [spec]: https://tc39.es/ecma262/#prod-WithStatement
436    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with
437    With,
438
439    /// The 'yield' keyword.
440    ///
441    /// More information:
442    ///  - [ECMAScript reference][spec]
443    ///  - [MDN documentation][mdn]
444    ///
445    /// [spec]: https://tc39.es/ecma262/#prod-YieldExpression
446    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield
447    Yield,
448
449    /// The `using` keyword.
450    ///
451    /// More information:
452    ///  - [ECMAScript reference][spec]
453    ///  - [MDN documentation][mdn]
454    ///
455    /// [spec]: https://tc39.es/proposal-explicit-resource-management/
456    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/using
457    Using,
458}
459
460impl Keyword {
461    /// Gets the keyword as a binary operation, if this keyword is the `in` or the `instanceof`
462    /// keywords.
463    #[must_use]
464    pub const fn as_binary_op(self) -> Option<BinaryOp> {
465        match self {
466            Self::In => Some(BinaryOp::Relational(RelationalOp::In)),
467            Self::InstanceOf => Some(BinaryOp::Relational(RelationalOp::InstanceOf)),
468            _ => None,
469        }
470    }
471
472    /// Gets the keyword as a tuple of strings.
473    #[must_use]
474    pub const fn as_str(self) -> (&'static str, &'static [u16]) {
475        match self {
476            Self::Await => ("await", utf16!("await")),
477            Self::Async => ("async", utf16!("async")),
478            Self::Break => ("break", utf16!("break")),
479            Self::Case => ("case", utf16!("case")),
480            Self::Catch => ("catch", utf16!("catch")),
481            Self::Class => ("class", utf16!("class")),
482            Self::Continue => ("continue", utf16!("continue")),
483            Self::Const => ("const", utf16!("const")),
484            Self::Debugger => ("debugger", utf16!("debugger")),
485            Self::Default => ("default", utf16!("default")),
486            Self::Delete => ("delete", utf16!("delete")),
487            Self::Do => ("do", utf16!("do")),
488            Self::Else => ("else", utf16!("else")),
489            Self::Enum => ("enum", utf16!("enum")),
490            Self::Extends => ("extends", utf16!("extends")),
491            Self::Export => ("export", utf16!("export")),
492            Self::Finally => ("finally", utf16!("finally")),
493            Self::For => ("for", utf16!("for")),
494            Self::Function => ("function", utf16!("function")),
495            Self::If => ("if", utf16!("if")),
496            Self::In => ("in", utf16!("in")),
497            Self::InstanceOf => ("instanceof", utf16!("instanceof")),
498            Self::Import => ("import", utf16!("import")),
499            Self::Let => ("let", utf16!("let")),
500            Self::New => ("new", utf16!("new")),
501            Self::Of => ("of", utf16!("of")),
502            Self::Return => ("return", utf16!("return")),
503            Self::Super => ("super", utf16!("super")),
504            Self::Switch => ("switch", utf16!("switch")),
505            Self::This => ("this", utf16!("this")),
506            Self::Throw => ("throw", utf16!("throw")),
507            Self::Try => ("try", utf16!("try")),
508            Self::TypeOf => ("typeof", utf16!("typeof")),
509            Self::Var => ("var", utf16!("var")),
510            Self::Void => ("void", utf16!("void")),
511            Self::While => ("while", utf16!("while")),
512            Self::With => ("with", utf16!("with")),
513            Self::Yield => ("yield", utf16!("yield")),
514            Self::Using => ("using", utf16!("using")),
515        }
516    }
517
518    /// Converts the keyword to a symbol in the given interner.
519    #[must_use]
520    pub const fn to_sym(self) -> Sym {
521        match self {
522            Self::Await => Sym::AWAIT,
523            Self::Async => Sym::ASYNC,
524            Self::Break => Sym::BREAK,
525            Self::Case => Sym::CASE,
526            Self::Catch => Sym::CATCH,
527            Self::Class => Sym::CLASS,
528            Self::Continue => Sym::CONTINUE,
529            Self::Const => Sym::CONST,
530            Self::Debugger => Sym::DEBUGGER,
531            Self::Default => Sym::DEFAULT,
532            Self::Delete => Sym::DELETE,
533            Self::Do => Sym::DO,
534            Self::Else => Sym::ELSE,
535            Self::Enum => Sym::ENUM,
536            Self::Export => Sym::EXPORT,
537            Self::Extends => Sym::EXTENDS,
538            Self::Finally => Sym::FINALLY,
539            Self::For => Sym::FOR,
540            Self::Function => Sym::FUNCTION,
541            Self::If => Sym::IF,
542            Self::In => Sym::IN,
543            Self::InstanceOf => Sym::INSTANCEOF,
544            Self::Import => Sym::IMPORT,
545            Self::Let => Sym::LET,
546            Self::New => Sym::NEW,
547            Self::Of => Sym::OF,
548            Self::Return => Sym::RETURN,
549            Self::Super => Sym::SUPER,
550            Self::Switch => Sym::SWITCH,
551            Self::This => Sym::THIS,
552            Self::Throw => Sym::THROW,
553            Self::Try => Sym::TRY,
554            Self::TypeOf => Sym::TYPEOF,
555            Self::Var => Sym::VAR,
556            Self::Void => Sym::VOID,
557            Self::While => Sym::WHILE,
558            Self::With => Sym::WITH,
559            Self::Yield => Sym::YIELD,
560            Self::Using => Sym::USING,
561        }
562    }
563}
564
565impl TryFrom<Keyword> for BinaryOp {
566    type Error = KeywordToBinaryOpError;
567
568    fn try_from(value: Keyword) -> Result<Self, Self::Error> {
569        value.as_binary_op().ok_or(KeywordToBinaryOpError)
570    }
571}
572
573/// Error returned when a [`Keyword`] cannot be converted into a [`BinaryOp`].
574#[derive(Debug, Clone, Copy)]
575pub struct KeywordToBinaryOpError;
576
577impl fmt::Display for KeywordToBinaryOpError {
578    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579        write!(f, "keyword is not a binary operator")
580    }
581}
582
583impl error::Error for KeywordToBinaryOpError {}
584
585/// The error type which is returned from parsing a [`str`] into a [`Keyword`].
586#[derive(Debug, Clone, Copy)]
587pub struct KeywordError;
588impl fmt::Display for KeywordError {
589    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
590        write!(f, "invalid token")
591    }
592}
593
594// This is important for other errors to wrap this one.
595impl error::Error for KeywordError {}
596
597impl FromStr for Keyword {
598    type Err = KeywordError;
599    fn from_str(s: &str) -> Result<Self, Self::Err> {
600        match s {
601            "await" => Ok(Self::Await),
602            "async" => Ok(Self::Async),
603            "break" => Ok(Self::Break),
604            "case" => Ok(Self::Case),
605            "catch" => Ok(Self::Catch),
606            "class" => Ok(Self::Class),
607            "continue" => Ok(Self::Continue),
608            "const" => Ok(Self::Const),
609            "debugger" => Ok(Self::Debugger),
610            "default" => Ok(Self::Default),
611            "delete" => Ok(Self::Delete),
612            "do" => Ok(Self::Do),
613            "else" => Ok(Self::Else),
614            "enum" => Ok(Self::Enum),
615            "extends" => Ok(Self::Extends),
616            "export" => Ok(Self::Export),
617            "finally" => Ok(Self::Finally),
618            "for" => Ok(Self::For),
619            "function" => Ok(Self::Function),
620            "if" => Ok(Self::If),
621            "in" => Ok(Self::In),
622            "instanceof" => Ok(Self::InstanceOf),
623            "import" => Ok(Self::Import),
624            "let" => Ok(Self::Let),
625            "new" => Ok(Self::New),
626            "of" => Ok(Self::Of),
627            "return" => Ok(Self::Return),
628            "super" => Ok(Self::Super),
629            "switch" => Ok(Self::Switch),
630            "this" => Ok(Self::This),
631            "throw" => Ok(Self::Throw),
632            "try" => Ok(Self::Try),
633            "typeof" => Ok(Self::TypeOf),
634            "var" => Ok(Self::Var),
635            "void" => Ok(Self::Void),
636            "while" => Ok(Self::While),
637            "with" => Ok(Self::With),
638            "yield" => Ok(Self::Yield),
639            "using" => Ok(Self::Using),
640            _ => Err(KeywordError),
641        }
642    }
643}
644
645impl fmt::Display for Keyword {
646    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
647        fmt::Display::fmt(self.as_str().0, f)
648    }
649}