use crate::syntax::ast::op::{BinOp, CompOp};
use std::{convert::TryInto, error, fmt, str::FromStr};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Keyword {
Await,
Break,
Case,
Catch,
Class,
Continue,
Const,
Debugger,
Default,
Delete,
Do,
Else,
Enum,
Export,
Extends,
Finally,
For,
Function,
If,
In,
InstanceOf,
Import,
Let,
New,
Return,
Super,
Switch,
This,
Throw,
Try,
TypeOf,
Var,
Void,
While,
With,
Yield,
}
impl Keyword {
pub fn as_binop(self) -> Option<BinOp> {
match self {
Keyword::In => Some(BinOp::Comp(CompOp::In)),
Keyword::InstanceOf => Some(BinOp::Comp(CompOp::InstanceOf)),
_ => None,
}
}
pub fn as_str(self) -> &'static str {
match self {
Self::Await => "await",
Self::Break => "break",
Self::Case => "case",
Self::Catch => "catch",
Self::Class => "class",
Self::Continue => "continue",
Self::Const => "const",
Self::Debugger => "debugger",
Self::Default => "default",
Self::Delete => "delete",
Self::Do => "do",
Self::Else => "else",
Self::Enum => "enum",
Self::Extends => "extends",
Self::Export => "export",
Self::Finally => "finally",
Self::For => "for",
Self::Function => "function",
Self::If => "if",
Self::In => "in",
Self::InstanceOf => "instanceof",
Self::Import => "import",
Self::Let => "let",
Self::New => "new",
Self::Return => "return",
Self::Super => "super",
Self::Switch => "switch",
Self::This => "this",
Self::Throw => "throw",
Self::Try => "try",
Self::TypeOf => "typeof",
Self::Var => "var",
Self::Void => "void",
Self::While => "while",
Self::With => "with",
Self::Yield => "yield",
}
}
}
impl TryInto<BinOp> for Keyword {
type Error = String;
fn try_into(self) -> Result<BinOp, Self::Error> {
self.as_binop()
.ok_or_else(|| format!("No binary operation for {}", self))
}
}
#[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 {
fn description(&self) -> &str {
"invalid token"
}
fn cause(&self) -> Option<&dyn error::Error> {
None
}
}
impl FromStr for Keyword {
type Err = KeywordError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"await" => Ok(Self::Await),
"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),
"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(), f)
}
}