emmylua_parser/syntax/node/token/
tokens.rs

1use crate::{
2    LuaOpKind, LuaSyntaxToken, LuaTypeBinaryOperator, LuaTypeUnaryOperator, LuaVersionNumber,
3    VisibilityKind,
4    kind::{BinaryOperator, LuaTokenKind, UnaryOperator},
5    syntax::traits::LuaAstToken,
6};
7
8use super::{float_token_value, int_token_value, string_token_value};
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct LuaGeneralToken {
12    token: LuaSyntaxToken,
13}
14
15impl LuaAstToken for LuaGeneralToken {
16    fn syntax(&self) -> &LuaSyntaxToken {
17        &self.token
18    }
19
20    fn can_cast(_: LuaTokenKind) -> bool
21    where
22        Self: Sized,
23    {
24        true
25    }
26
27    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
28    where
29        Self: Sized,
30    {
31        Some(LuaGeneralToken { token: syntax })
32    }
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Hash)]
36pub struct LuaNameToken {
37    token: LuaSyntaxToken,
38}
39
40impl LuaAstToken for LuaNameToken {
41    fn syntax(&self) -> &LuaSyntaxToken {
42        &self.token
43    }
44
45    fn can_cast(kind: LuaTokenKind) -> bool
46    where
47        Self: Sized,
48    {
49        kind == LuaTokenKind::TkName
50    }
51
52    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
53    where
54        Self: Sized,
55    {
56        if Self::can_cast(syntax.kind().into()) {
57            Some(LuaNameToken { token: syntax })
58        } else {
59            None
60        }
61    }
62}
63
64impl LuaNameToken {
65    pub fn get_name_text(&self) -> &str {
66        self.token.text()
67    }
68}
69
70#[derive(Debug, Clone, PartialEq, Eq, Hash)]
71pub struct LuaStringToken {
72    token: LuaSyntaxToken,
73}
74
75impl LuaAstToken for LuaStringToken {
76    fn syntax(&self) -> &LuaSyntaxToken {
77        &self.token
78    }
79
80    fn can_cast(kind: LuaTokenKind) -> bool
81    where
82        Self: Sized,
83    {
84        kind == LuaTokenKind::TkString || kind == LuaTokenKind::TkLongString
85    }
86
87    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
88    where
89        Self: Sized,
90    {
91        if Self::can_cast(syntax.kind().into()) {
92            Some(LuaStringToken { token: syntax })
93        } else {
94            None
95        }
96    }
97}
98
99impl LuaStringToken {
100    pub fn get_value(&self) -> String {
101        string_token_value(&self.token).unwrap_or_default()
102    }
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Hash)]
106pub struct LuaNumberToken {
107    token: LuaSyntaxToken,
108}
109
110impl LuaAstToken for LuaNumberToken {
111    fn syntax(&self) -> &LuaSyntaxToken {
112        &self.token
113    }
114
115    fn can_cast(kind: LuaTokenKind) -> bool
116    where
117        Self: Sized,
118    {
119        kind == LuaTokenKind::TkFloat || kind == LuaTokenKind::TkInt
120    }
121
122    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
123    where
124        Self: Sized,
125    {
126        if Self::can_cast(syntax.kind().into()) {
127            Some(LuaNumberToken { token: syntax })
128        } else {
129            None
130        }
131    }
132}
133
134impl LuaNumberToken {
135    pub fn is_float(&self) -> bool {
136        self.token.kind() == LuaTokenKind::TkFloat.into()
137    }
138
139    pub fn is_int(&self) -> bool {
140        self.token.kind() == LuaTokenKind::TkInt.into()
141    }
142
143    pub fn get_float_value(&self) -> f64 {
144        if !self.is_float() {
145            return 0.0;
146        }
147        float_token_value(&self.token).unwrap_or(0.0)
148    }
149
150    pub fn get_int_value(&self) -> i64 {
151        if !self.is_int() {
152            return 0;
153        }
154        match int_token_value(&self.token) {
155            Ok(value) => value.as_integer().unwrap_or(0),
156            Err(_) => 0,
157        }
158    }
159}
160
161#[derive(Debug, Clone, PartialEq, Eq, Hash)]
162pub struct LuaBinaryOpToken {
163    token: LuaSyntaxToken,
164}
165
166impl LuaAstToken for LuaBinaryOpToken {
167    fn syntax(&self) -> &LuaSyntaxToken {
168        &self.token
169    }
170
171    fn can_cast(kind: LuaTokenKind) -> bool
172    where
173        Self: Sized,
174    {
175        LuaOpKind::to_binary_operator(kind) != BinaryOperator::OpNop
176    }
177
178    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
179    where
180        Self: Sized,
181    {
182        if Self::can_cast(syntax.kind().into()) {
183            Some(LuaBinaryOpToken { token: syntax })
184        } else {
185            None
186        }
187    }
188}
189
190impl LuaBinaryOpToken {
191    pub fn get_op(&self) -> BinaryOperator {
192        LuaOpKind::to_binary_operator(self.token.kind().into())
193    }
194}
195
196#[derive(Debug, Clone, PartialEq, Eq, Hash)]
197pub struct LuaUnaryOpToken {
198    token: LuaSyntaxToken,
199}
200
201impl LuaAstToken for LuaUnaryOpToken {
202    fn syntax(&self) -> &LuaSyntaxToken {
203        &self.token
204    }
205
206    fn can_cast(kind: LuaTokenKind) -> bool
207    where
208        Self: Sized,
209    {
210        LuaOpKind::to_unary_operator(kind) != UnaryOperator::OpNop
211    }
212
213    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
214    where
215        Self: Sized,
216    {
217        if Self::can_cast(syntax.kind().into()) {
218            Some(LuaUnaryOpToken { token: syntax })
219        } else {
220            None
221        }
222    }
223}
224
225impl LuaUnaryOpToken {
226    pub fn get_op(&self) -> UnaryOperator {
227        LuaOpKind::to_unary_operator(self.token.kind().into())
228    }
229}
230
231#[derive(Debug, Clone, PartialEq, Eq, Hash)]
232pub struct LuaKeywordToken {
233    token: LuaSyntaxToken,
234}
235
236impl LuaAstToken for LuaKeywordToken {
237    fn syntax(&self) -> &LuaSyntaxToken {
238        &self.token
239    }
240
241    fn can_cast(kind: LuaTokenKind) -> bool
242    where
243        Self: Sized,
244    {
245        matches!(
246            kind,
247            LuaTokenKind::TkAnd
248                | LuaTokenKind::TkBreak
249                | LuaTokenKind::TkDo
250                | LuaTokenKind::TkElse
251                | LuaTokenKind::TkElseIf
252                | LuaTokenKind::TkEnd
253                | LuaTokenKind::TkFalse
254                | LuaTokenKind::TkFor
255                | LuaTokenKind::TkFunction
256                | LuaTokenKind::TkGoto
257                | LuaTokenKind::TkIf
258                | LuaTokenKind::TkIn
259                | LuaTokenKind::TkLocal
260                | LuaTokenKind::TkNil
261                | LuaTokenKind::TkNot
262                | LuaTokenKind::TkOr
263                | LuaTokenKind::TkRepeat
264                | LuaTokenKind::TkReturn
265                | LuaTokenKind::TkThen
266                | LuaTokenKind::TkTrue
267                | LuaTokenKind::TkUntil
268                | LuaTokenKind::TkWhile
269        )
270    }
271
272    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
273    where
274        Self: Sized,
275    {
276        if Self::can_cast(syntax.kind().into()) {
277            Some(LuaKeywordToken { token: syntax })
278        } else {
279            None
280        }
281    }
282}
283
284impl LuaKeywordToken {
285    pub fn get_keyword(&self) -> LuaTokenKind {
286        self.token.kind().into()
287    }
288}
289
290#[derive(Debug, Clone, PartialEq, Eq, Hash)]
291pub struct LuaBoolToken {
292    token: LuaSyntaxToken,
293}
294
295impl LuaAstToken for LuaBoolToken {
296    fn syntax(&self) -> &LuaSyntaxToken {
297        &self.token
298    }
299
300    fn can_cast(kind: LuaTokenKind) -> bool
301    where
302        Self: Sized,
303    {
304        kind == LuaTokenKind::TkTrue || kind == LuaTokenKind::TkFalse
305    }
306
307    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
308    where
309        Self: Sized,
310    {
311        if Self::can_cast(syntax.kind().into()) {
312            Some(LuaBoolToken { token: syntax })
313        } else {
314            None
315        }
316    }
317}
318
319impl LuaBoolToken {
320    pub fn is_true(&self) -> bool {
321        self.token.kind() == LuaTokenKind::TkTrue.into()
322    }
323}
324
325#[derive(Debug, Clone, PartialEq, Eq, Hash)]
326pub struct LuaNilToken {
327    token: LuaSyntaxToken,
328}
329
330impl LuaAstToken for LuaNilToken {
331    fn syntax(&self) -> &LuaSyntaxToken {
332        &self.token
333    }
334
335    fn can_cast(kind: LuaTokenKind) -> bool
336    where
337        Self: Sized,
338    {
339        kind == LuaTokenKind::TkNil
340    }
341
342    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
343    where
344        Self: Sized,
345    {
346        if Self::can_cast(syntax.kind().into()) {
347            Some(LuaNilToken { token: syntax })
348        } else {
349            None
350        }
351    }
352}
353
354#[derive(Debug, Clone, PartialEq, Eq, Hash)]
355pub enum LuaLiteralToken {
356    String(LuaStringToken),
357    Number(LuaNumberToken),
358    Bool(LuaBoolToken),
359    Nil(LuaNilToken),
360    Dots(LuaGeneralToken),
361    Question(LuaGeneralToken),
362}
363
364impl LuaAstToken for LuaLiteralToken {
365    fn syntax(&self) -> &LuaSyntaxToken {
366        match self {
367            LuaLiteralToken::String(token) => token.syntax(),
368            LuaLiteralToken::Number(token) => token.syntax(),
369            LuaLiteralToken::Bool(token) => token.syntax(),
370            LuaLiteralToken::Nil(token) => token.syntax(),
371            LuaLiteralToken::Dots(token) => token.syntax(),
372            LuaLiteralToken::Question(token) => token.syntax(),
373        }
374    }
375
376    fn can_cast(kind: LuaTokenKind) -> bool
377    where
378        Self: Sized,
379    {
380        matches!(
381            kind,
382            LuaTokenKind::TkInt
383                | LuaTokenKind::TkFloat
384                | LuaTokenKind::TkComplex
385                | LuaTokenKind::TkNil
386                | LuaTokenKind::TkTrue
387                | LuaTokenKind::TkFalse
388                | LuaTokenKind::TkDots
389                | LuaTokenKind::TkString
390                | LuaTokenKind::TkLongString
391                | LuaTokenKind::TkDocQuestion
392        )
393    }
394
395    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
396    where
397        Self: Sized,
398    {
399        match syntax.kind().into() {
400            LuaTokenKind::TkString | LuaTokenKind::TkLongString => {
401                LuaStringToken::cast(syntax).map(LuaLiteralToken::String)
402            }
403            LuaTokenKind::TkFloat | LuaTokenKind::TkInt | LuaTokenKind::TkComplex => {
404                LuaNumberToken::cast(syntax).map(LuaLiteralToken::Number)
405            }
406            LuaTokenKind::TkTrue | LuaTokenKind::TkFalse => {
407                LuaBoolToken::cast(syntax).map(LuaLiteralToken::Bool)
408            }
409            LuaTokenKind::TkNil => LuaNilToken::cast(syntax).map(LuaLiteralToken::Nil),
410            LuaTokenKind::TkDots => LuaGeneralToken::cast(syntax).map(LuaLiteralToken::Dots),
411            LuaTokenKind::TkDocQuestion => {
412                LuaGeneralToken::cast(syntax).map(LuaLiteralToken::Question)
413            }
414            _ => None,
415        }
416    }
417}
418
419#[derive(Debug, Clone, PartialEq, Eq, Hash)]
420pub struct LuaSpaceToken {
421    token: LuaSyntaxToken,
422}
423
424impl LuaAstToken for LuaSpaceToken {
425    fn syntax(&self) -> &LuaSyntaxToken {
426        &self.token
427    }
428
429    fn can_cast(kind: LuaTokenKind) -> bool
430    where
431        Self: Sized,
432    {
433        matches!(kind, LuaTokenKind::TkWhitespace | LuaTokenKind::TkEndOfLine)
434    }
435
436    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
437    where
438        Self: Sized,
439    {
440        if Self::can_cast(syntax.kind().into()) {
441            Some(LuaSpaceToken { token: syntax })
442        } else {
443            None
444        }
445    }
446}
447
448#[derive(Debug, Clone, PartialEq, Eq, Hash)]
449pub struct LuaIndexToken {
450    token: LuaSyntaxToken,
451}
452
453impl LuaAstToken for LuaIndexToken {
454    fn syntax(&self) -> &LuaSyntaxToken {
455        &self.token
456    }
457
458    fn can_cast(kind: LuaTokenKind) -> bool
459    where
460        Self: Sized,
461    {
462        kind == LuaTokenKind::TkDot
463            || kind == LuaTokenKind::TkColon
464            || kind == LuaTokenKind::TkLeftBracket
465    }
466
467    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
468    where
469        Self: Sized,
470    {
471        if Self::can_cast(syntax.kind().into()) {
472            Some(LuaIndexToken { token: syntax })
473        } else {
474            None
475        }
476    }
477}
478
479impl LuaIndexToken {
480    pub fn is_dot(&self) -> bool {
481        self.token.kind() == LuaTokenKind::TkDot.into()
482    }
483
484    pub fn is_colon(&self) -> bool {
485        self.token.kind() == LuaTokenKind::TkColon.into()
486    }
487
488    pub fn is_left_bracket(&self) -> bool {
489        self.token.kind() == LuaTokenKind::TkLeftBracket.into()
490    }
491}
492
493#[derive(Debug, Clone, PartialEq, Eq, Hash)]
494pub struct LuaDocDetailToken {
495    token: LuaSyntaxToken,
496}
497
498impl LuaAstToken for LuaDocDetailToken {
499    fn syntax(&self) -> &LuaSyntaxToken {
500        &self.token
501    }
502
503    fn can_cast(kind: LuaTokenKind) -> bool
504    where
505        Self: Sized,
506    {
507        kind == LuaTokenKind::TkDocDetail
508    }
509
510    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
511    where
512        Self: Sized,
513    {
514        if Self::can_cast(syntax.kind().into()) {
515            Some(LuaDocDetailToken { token: syntax })
516        } else {
517            None
518        }
519    }
520}
521
522impl LuaDocDetailToken {
523    pub fn get_detail(&self) -> &str {
524        self.token.text()
525    }
526}
527
528#[derive(Debug, Clone, PartialEq, Eq, Hash)]
529pub struct LuaDocVisibilityToken {
530    token: LuaSyntaxToken,
531}
532
533impl LuaAstToken for LuaDocVisibilityToken {
534    fn syntax(&self) -> &LuaSyntaxToken {
535        &self.token
536    }
537
538    fn can_cast(kind: LuaTokenKind) -> bool
539    where
540        Self: Sized,
541    {
542        kind == LuaTokenKind::TkDocVisibility || kind == LuaTokenKind::TkTagVisibility
543    }
544
545    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
546    where
547        Self: Sized,
548    {
549        if Self::can_cast(syntax.kind().into()) {
550            Some(LuaDocVisibilityToken { token: syntax })
551        } else {
552            None
553        }
554    }
555}
556
557impl LuaDocVisibilityToken {
558    pub fn get_visibility(&self) -> Option<VisibilityKind> {
559        VisibilityKind::to_visibility_kind(self.token.text())
560    }
561}
562
563#[derive(Debug, Clone, PartialEq, Eq, Hash)]
564pub struct LuaDocVersionNumberToken {
565    token: LuaSyntaxToken,
566}
567
568impl LuaAstToken for LuaDocVersionNumberToken {
569    fn syntax(&self) -> &LuaSyntaxToken {
570        &self.token
571    }
572
573    fn can_cast(kind: LuaTokenKind) -> bool
574    where
575        Self: Sized,
576    {
577        kind == LuaTokenKind::TkDocVersionNumber
578    }
579
580    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
581    where
582        Self: Sized,
583    {
584        if Self::can_cast(syntax.kind().into()) {
585            Some(LuaDocVersionNumberToken { token: syntax })
586        } else {
587            None
588        }
589    }
590}
591
592impl LuaDocVersionNumberToken {
593    pub fn get_version_number(&self) -> Option<LuaVersionNumber> {
594        let text = self.token.text();
595        LuaVersionNumber::from_str(text)
596    }
597}
598
599#[derive(Debug, Clone, PartialEq, Eq, Hash)]
600pub struct LuaDocTypeBinaryToken {
601    token: LuaSyntaxToken,
602}
603
604impl LuaAstToken for LuaDocTypeBinaryToken {
605    fn syntax(&self) -> &LuaSyntaxToken {
606        &self.token
607    }
608
609    fn can_cast(kind: LuaTokenKind) -> bool
610    where
611        Self: Sized,
612    {
613        kind == LuaTokenKind::TkDocOr
614            || kind == LuaTokenKind::TkDocAnd
615            || kind == LuaTokenKind::TkDocExtends
616            || kind == LuaTokenKind::TkDocIn
617            || kind == LuaTokenKind::TkDocContinueOr
618            || kind == LuaTokenKind::TkPlus
619            || kind == LuaTokenKind::TkMinus
620    }
621
622    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
623    where
624        Self: Sized,
625    {
626        if Self::can_cast(syntax.kind().into()) {
627            Some(LuaDocTypeBinaryToken { token: syntax })
628        } else {
629            None
630        }
631    }
632}
633
634impl LuaDocTypeBinaryToken {
635    pub fn get_op(&self) -> LuaTypeBinaryOperator {
636        LuaOpKind::to_type_binary_operator(self.token.kind().into())
637    }
638}
639
640#[derive(Debug, Clone, PartialEq, Eq, Hash)]
641pub struct LuaDocTypeUnaryToken {
642    token: LuaSyntaxToken,
643}
644
645impl LuaAstToken for LuaDocTypeUnaryToken {
646    fn syntax(&self) -> &LuaSyntaxToken {
647        &self.token
648    }
649
650    fn can_cast(kind: LuaTokenKind) -> bool
651    where
652        Self: Sized,
653    {
654        kind == LuaTokenKind::TkDocKeyOf || kind == LuaTokenKind::TkMinus
655    }
656
657    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
658    where
659        Self: Sized,
660    {
661        if Self::can_cast(syntax.kind().into()) {
662            Some(LuaDocTypeUnaryToken { token: syntax })
663        } else {
664            None
665        }
666    }
667}
668
669impl LuaDocTypeUnaryToken {
670    pub fn get_op(&self) -> LuaTypeUnaryOperator {
671        LuaOpKind::to_type_unary_operator(self.token.kind().into())
672    }
673}
674
675#[derive(Debug, Clone, PartialEq, Eq, Hash)]
676pub struct LuaPathToken {
677    token: LuaSyntaxToken,
678}
679
680impl LuaAstToken for LuaPathToken {
681    fn syntax(&self) -> &LuaSyntaxToken {
682        &self.token
683    }
684
685    fn can_cast(kind: LuaTokenKind) -> bool
686    where
687        Self: Sized,
688    {
689        kind == LuaTokenKind::TKDocPath
690    }
691
692    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
693    where
694        Self: Sized,
695    {
696        if Self::can_cast(syntax.kind().into()) {
697            Some(LuaPathToken { token: syntax })
698        } else {
699            None
700        }
701    }
702}
703
704impl LuaPathToken {
705    pub fn get_path(&self) -> &str {
706        let text = self.token.text();
707        if text.starts_with('\"') || text.starts_with('\'') {
708            &text[1..text.len() - 1]
709        } else {
710            text
711        }
712    }
713}