emmylua_parser/syntax/node/token/
tokens.rs

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