1use super::regex::RegExpFlags;
9
10use crate::{
11 syntax::ast::{Keyword, Punctuator, Span},
12 syntax::lexer::template::TemplateString,
13 JsBigInt,
14};
15use std::fmt::{self, Debug, Display, Formatter};
16
17#[cfg(feature = "deser")]
18use serde::{Deserialize, Serialize};
19
20#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
27#[derive(Debug, Clone, PartialEq)]
28pub struct Token {
29 kind: TokenKind,
31 span: Span,
33}
34
35impl Token {
36 #[inline]
38 pub fn new(kind: TokenKind, span: Span) -> Self {
39 Self { kind, span }
40 }
41
42 #[inline]
44 pub fn kind(&self) -> &TokenKind {
45 &self.kind
46 }
47
48 #[inline]
50 pub fn span(&self) -> Span {
51 self.span
52 }
53}
54
55impl Display for Token {
56 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
57 write!(f, "{}", self.kind)
58 }
59}
60
61#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
63#[derive(Clone, PartialEq, Debug)]
64pub enum Numeric {
65 Rational(f64),
67
68 Integer(i32),
70
71 BigInt(JsBigInt),
73}
74
75impl From<f64> for Numeric {
76 #[inline]
77 fn from(n: f64) -> Self {
78 Self::Rational(n)
79 }
80}
81
82impl From<i32> for Numeric {
83 #[inline]
84 fn from(n: i32) -> Self {
85 Self::Integer(n)
86 }
87}
88
89impl From<JsBigInt> for Numeric {
90 #[inline]
91 fn from(n: JsBigInt) -> Self {
92 Self::BigInt(n)
93 }
94}
95
96#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
98#[derive(Clone, PartialEq, Debug)]
99pub enum TokenKind {
100 BooleanLiteral(bool),
102
103 EOF,
105
106 Identifier(Box<str>),
108
109 Keyword(Keyword),
113
114 NullLiteral,
116
117 NumericLiteral(Numeric),
119
120 Punctuator(Punctuator),
124
125 StringLiteral(Box<str>),
127
128 TemplateNoSubstitution(TemplateString),
130
131 TemplateMiddle(TemplateString),
133
134 RegularExpressionLiteral(Box<str>, RegExpFlags),
136
137 LineTerminator,
139
140 Comment,
142}
143
144impl From<bool> for TokenKind {
145 fn from(oth: bool) -> Self {
146 Self::BooleanLiteral(oth)
147 }
148}
149
150impl From<Keyword> for TokenKind {
151 fn from(kw: Keyword) -> Self {
152 Self::Keyword(kw)
153 }
154}
155
156impl From<Punctuator> for TokenKind {
157 fn from(punc: Punctuator) -> Self {
158 Self::Punctuator(punc)
159 }
160}
161
162impl From<Numeric> for TokenKind {
163 fn from(num: Numeric) -> Self {
164 Self::NumericLiteral(num)
165 }
166}
167
168impl TokenKind {
169 pub fn boolean_literal(lit: bool) -> Self {
171 Self::BooleanLiteral(lit)
172 }
173
174 pub fn eof() -> Self {
176 Self::EOF
177 }
178
179 pub fn identifier<I>(ident: I) -> Self
181 where
182 I: Into<Box<str>>,
183 {
184 Self::Identifier(ident.into())
185 }
186
187 pub fn keyword(keyword: Keyword) -> Self {
189 Self::Keyword(keyword)
190 }
191
192 pub fn numeric_literal<L>(lit: L) -> Self
194 where
195 L: Into<Numeric>,
196 {
197 Self::NumericLiteral(lit.into())
198 }
199
200 pub fn punctuator(punc: Punctuator) -> Self {
202 Self::Punctuator(punc)
203 }
204
205 pub fn string_literal<S>(lit: S) -> Self
207 where
208 S: Into<Box<str>>,
209 {
210 Self::StringLiteral(lit.into())
211 }
212
213 pub fn template_middle(template_string: TemplateString) -> Self {
214 Self::TemplateMiddle(template_string)
215 }
216
217 pub fn template_no_substitution(template_string: TemplateString) -> Self {
218 Self::TemplateNoSubstitution(template_string)
219 }
220
221 pub fn regular_expression_literal<B, R>(body: B, flags: R) -> Self
223 where
224 B: Into<Box<str>>,
225 R: Into<RegExpFlags>,
226 {
227 Self::RegularExpressionLiteral(body.into(), flags.into())
228 }
229
230 pub fn line_terminator() -> Self {
232 Self::LineTerminator
233 }
234
235 pub fn comment() -> Self {
237 Self::Comment
238 }
239}
240
241impl Display for TokenKind {
242 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
243 match *self {
244 Self::BooleanLiteral(ref val) => write!(f, "{}", val),
245 Self::EOF => write!(f, "end of file"),
246 Self::Identifier(ref ident) => write!(f, "{}", ident),
247 Self::Keyword(ref word) => write!(f, "{}", word),
248 Self::NullLiteral => write!(f, "null"),
249 Self::NumericLiteral(Numeric::Rational(num)) => write!(f, "{}", num),
250 Self::NumericLiteral(Numeric::Integer(num)) => write!(f, "{}", num),
251 Self::NumericLiteral(Numeric::BigInt(ref num)) => write!(f, "{}n", num),
252 Self::Punctuator(ref punc) => write!(f, "{}", punc),
253 Self::StringLiteral(ref lit) => write!(f, "{}", lit),
254 Self::TemplateNoSubstitution(ref ts) => write!(f, "{}", ts.as_raw()),
255 Self::TemplateMiddle(ref ts) => write!(f, "{}", ts.as_raw()),
256 Self::RegularExpressionLiteral(ref body, ref flags) => write!(f, "/{}/{}", body, flags),
257 Self::LineTerminator => write!(f, "line terminator"),
258 Self::Comment => write!(f, "comment"),
259 }
260 }
261}