use super::regex::RegExpFlags;
use crate::{
builtins::BigInt,
syntax::ast::{Keyword, Punctuator, Span},
};
use std::fmt::{self, Debug, Display, Formatter};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Token {
kind: TokenKind,
span: Span,
}
impl Token {
#[inline]
pub fn new(kind: TokenKind, span: Span) -> Self {
Self { kind, span }
}
#[inline]
pub fn kind(&self) -> &TokenKind {
&self.kind
}
#[inline]
pub fn span(&self) -> Span {
self.span
}
}
impl Display for Token {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Debug)]
pub enum Numeric {
Rational(f64),
Integer(i32),
BigInt(BigInt),
}
impl From<f64> for Numeric {
#[inline]
fn from(n: f64) -> Self {
Self::Rational(n)
}
}
impl From<i32> for Numeric {
#[inline]
fn from(n: i32) -> Self {
Self::Integer(n)
}
}
impl From<BigInt> for Numeric {
#[inline]
fn from(n: BigInt) -> Self {
Self::BigInt(n)
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Debug)]
pub enum TokenKind {
BooleanLiteral(bool),
EOF,
Identifier(Box<str>),
Keyword(Keyword),
NullLiteral,
NumericLiteral(Numeric),
Punctuator(Punctuator),
StringLiteral(Box<str>),
TemplateLiteral(Box<str>),
RegularExpressionLiteral(Box<str>, RegExpFlags),
LineTerminator,
Comment,
}
impl From<bool> for TokenKind {
fn from(oth: bool) -> Self {
Self::BooleanLiteral(oth)
}
}
impl From<Keyword> for TokenKind {
fn from(kw: Keyword) -> Self {
Self::Keyword(kw)
}
}
impl From<Punctuator> for TokenKind {
fn from(punc: Punctuator) -> Self {
Self::Punctuator(punc)
}
}
impl From<Numeric> for TokenKind {
fn from(num: Numeric) -> Self {
Self::NumericLiteral(num)
}
}
impl TokenKind {
pub fn boolean_literal(lit: bool) -> Self {
Self::BooleanLiteral(lit)
}
pub fn eof() -> Self {
Self::EOF
}
pub fn identifier<I>(ident: I) -> Self
where
I: Into<Box<str>>,
{
Self::Identifier(ident.into())
}
pub fn keyword(keyword: Keyword) -> Self {
Self::Keyword(keyword)
}
pub fn numeric_literal<L>(lit: L) -> Self
where
L: Into<Numeric>,
{
Self::NumericLiteral(lit.into())
}
pub fn punctuator(punc: Punctuator) -> Self {
Self::Punctuator(punc)
}
pub fn string_literal<S>(lit: S) -> Self
where
S: Into<Box<str>>,
{
Self::StringLiteral(lit.into())
}
pub fn template_literal<S>(lit: S) -> Self
where
S: Into<Box<str>>,
{
Self::TemplateLiteral(lit.into())
}
pub fn regular_expression_literal<B, R>(body: B, flags: R) -> Self
where
B: Into<Box<str>>,
R: Into<RegExpFlags>,
{
Self::RegularExpressionLiteral(body.into(), flags.into())
}
pub fn line_terminator() -> Self {
Self::LineTerminator
}
pub fn comment() -> Self {
Self::Comment
}
}
impl Display for TokenKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
Self::BooleanLiteral(ref val) => write!(f, "{}", val),
Self::EOF => write!(f, "end of file"),
Self::Identifier(ref ident) => write!(f, "{}", ident),
Self::Keyword(ref word) => write!(f, "{}", word),
Self::NullLiteral => write!(f, "null"),
Self::NumericLiteral(Numeric::Rational(num)) => write!(f, "{}", num),
Self::NumericLiteral(Numeric::Integer(num)) => write!(f, "{}", num),
Self::NumericLiteral(Numeric::BigInt(ref num)) => write!(f, "{}n", num),
Self::Punctuator(ref punc) => write!(f, "{}", punc),
Self::StringLiteral(ref lit) => write!(f, "{}", lit),
Self::TemplateLiteral(ref lit) => write!(f, "{}", lit),
Self::RegularExpressionLiteral(ref body, ref flags) => write!(f, "/{}/{}", body, flags),
Self::LineTerminator => write!(f, "line terminator"),
Self::Comment => write!(f, "comment"),
}
}
}