use crate::expression::operator::binary::{BinaryOp, RelationalOp};
use boa_interner::Sym;
use boa_macros::utf16;
use std::{convert::TryFrom, error, fmt, str::FromStr};
#[cfg(test)]
mod tests;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Keyword {
Await,
Async,
Break,
Case,
Catch,
Class,
Continue,
Const,
Debugger,
Default,
Delete,
Do,
Else,
Enum,
Export,
Extends,
Finally,
For,
Function,
If,
In,
InstanceOf,
Import,
Let,
New,
Of,
Return,
Super,
Switch,
This,
Throw,
Try,
TypeOf,
Var,
Void,
While,
With,
Yield,
}
impl Keyword {
#[must_use]
pub const fn as_binary_op(self) -> Option<BinaryOp> {
match self {
Self::In => Some(BinaryOp::Relational(RelationalOp::In)),
Self::InstanceOf => Some(BinaryOp::Relational(RelationalOp::InstanceOf)),
_ => None,
}
}
#[must_use]
pub const fn as_str(self) -> (&'static str, &'static [u16]) {
match self {
Self::Await => ("await", utf16!("await")),
Self::Async => ("async", utf16!("async")),
Self::Break => ("break", utf16!("break")),
Self::Case => ("case", utf16!("case")),
Self::Catch => ("catch", utf16!("catch")),
Self::Class => ("class", utf16!("class")),
Self::Continue => ("continue", utf16!("continue")),
Self::Const => ("const", utf16!("const")),
Self::Debugger => ("debugger", utf16!("debugger")),
Self::Default => ("default", utf16!("default")),
Self::Delete => ("delete", utf16!("delete")),
Self::Do => ("do", utf16!("do")),
Self::Else => ("else", utf16!("else")),
Self::Enum => ("enum", utf16!("enum")),
Self::Extends => ("extends", utf16!("extends")),
Self::Export => ("export", utf16!("export")),
Self::Finally => ("finally", utf16!("finally")),
Self::For => ("for", utf16!("for")),
Self::Function => ("function", utf16!("function")),
Self::If => ("if", utf16!("if")),
Self::In => ("in", utf16!("in")),
Self::InstanceOf => ("instanceof", utf16!("instanceof")),
Self::Import => ("import", utf16!("import")),
Self::Let => ("let", utf16!("let")),
Self::New => ("new", utf16!("new")),
Self::Of => ("of", utf16!("of")),
Self::Return => ("return", utf16!("return")),
Self::Super => ("super", utf16!("super")),
Self::Switch => ("switch", utf16!("switch")),
Self::This => ("this", utf16!("this")),
Self::Throw => ("throw", utf16!("throw")),
Self::Try => ("try", utf16!("try")),
Self::TypeOf => ("typeof", utf16!("typeof")),
Self::Var => ("var", utf16!("var")),
Self::Void => ("void", utf16!("void")),
Self::While => ("while", utf16!("while")),
Self::With => ("with", utf16!("with")),
Self::Yield => ("yield", utf16!("yield")),
}
}
#[must_use]
pub const fn to_sym(self) -> Sym {
match self {
Self::Await => Sym::AWAIT,
Self::Async => Sym::ASYNC,
Self::Break => Sym::BREAK,
Self::Case => Sym::CASE,
Self::Catch => Sym::CATCH,
Self::Class => Sym::CLASS,
Self::Continue => Sym::CONTINUE,
Self::Const => Sym::CONST,
Self::Debugger => Sym::DEBUGGER,
Self::Default => Sym::DEFAULT,
Self::Delete => Sym::DELETE,
Self::Do => Sym::DO,
Self::Else => Sym::ELSE,
Self::Enum => Sym::ENUM,
Self::Export => Sym::EXPORT,
Self::Extends => Sym::EXTENDS,
Self::Finally => Sym::FINALLY,
Self::For => Sym::FOR,
Self::Function => Sym::FUNCTION,
Self::If => Sym::IF,
Self::In => Sym::IN,
Self::InstanceOf => Sym::INSTANCEOF,
Self::Import => Sym::IMPORT,
Self::Let => Sym::LET,
Self::New => Sym::NEW,
Self::Of => Sym::OF,
Self::Return => Sym::RETURN,
Self::Super => Sym::SUPER,
Self::Switch => Sym::SWITCH,
Self::This => Sym::THIS,
Self::Throw => Sym::THROW,
Self::Try => Sym::TRY,
Self::TypeOf => Sym::TYPEOF,
Self::Var => Sym::VAR,
Self::Void => Sym::VOID,
Self::While => Sym::WHILE,
Self::With => Sym::WITH,
Self::Yield => Sym::YIELD,
}
}
}
impl TryFrom<Keyword> for BinaryOp {
type Error = String;
fn try_from(value: Keyword) -> Result<Self, Self::Error> {
value
.as_binary_op()
.ok_or_else(|| format!("No binary operation for {value}"))
}
}
#[derive(Debug, Clone, Copy)]
pub struct KeywordError;
impl fmt::Display for KeywordError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "invalid token")
}
}
impl error::Error for KeywordError {}
impl FromStr for Keyword {
type Err = KeywordError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"await" => Ok(Self::Await),
"async" => Ok(Self::Async),
"break" => Ok(Self::Break),
"case" => Ok(Self::Case),
"catch" => Ok(Self::Catch),
"class" => Ok(Self::Class),
"continue" => Ok(Self::Continue),
"const" => Ok(Self::Const),
"debugger" => Ok(Self::Debugger),
"default" => Ok(Self::Default),
"delete" => Ok(Self::Delete),
"do" => Ok(Self::Do),
"else" => Ok(Self::Else),
"enum" => Ok(Self::Enum),
"extends" => Ok(Self::Extends),
"export" => Ok(Self::Export),
"finally" => Ok(Self::Finally),
"for" => Ok(Self::For),
"function" => Ok(Self::Function),
"if" => Ok(Self::If),
"in" => Ok(Self::In),
"instanceof" => Ok(Self::InstanceOf),
"import" => Ok(Self::Import),
"let" => Ok(Self::Let),
"new" => Ok(Self::New),
"of" => Ok(Self::Of),
"return" => Ok(Self::Return),
"super" => Ok(Self::Super),
"switch" => Ok(Self::Switch),
"this" => Ok(Self::This),
"throw" => Ok(Self::Throw),
"try" => Ok(Self::Try),
"typeof" => Ok(Self::TypeOf),
"var" => Ok(Self::Var),
"void" => Ok(Self::Void),
"while" => Ok(Self::While),
"with" => Ok(Self::With),
"yield" => Ok(Self::Yield),
_ => Err(KeywordError),
}
}
}
impl fmt::Display for Keyword {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.as_str().0, f)
}
}