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 => LuaGeneralToken::cast(syntax).map(LuaLiteralToken::Question),
418            _ => None,
419        }
420    }
421}
422
423#[derive(Debug, Clone, PartialEq, Eq, Hash)]
424pub struct LuaSpaceToken {
425    token: LuaSyntaxToken,
426}
427
428impl LuaAstToken for LuaSpaceToken {
429    fn syntax(&self) -> &LuaSyntaxToken {
430        &self.token
431    }
432
433    fn can_cast(kind: LuaTokenKind) -> bool
434    where
435        Self: Sized,
436    {
437        match kind {
438            LuaTokenKind::TkWhitespace | LuaTokenKind::TkEndOfLine => true,
439            _ => false,
440        }
441    }
442
443    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
444    where
445        Self: Sized,
446    {
447        if Self::can_cast(syntax.kind().into()) {
448            Some(LuaSpaceToken { token: syntax })
449        } else {
450            None
451        }
452    }
453}
454
455#[derive(Debug, Clone, PartialEq, Eq, Hash)]
456pub struct LuaIndexToken {
457    token: LuaSyntaxToken,
458}
459
460impl LuaAstToken for LuaIndexToken {
461    fn syntax(&self) -> &LuaSyntaxToken {
462        &self.token
463    }
464
465    fn can_cast(kind: LuaTokenKind) -> bool
466    where
467        Self: Sized,
468    {
469        kind == LuaTokenKind::TkDot.into()
470            || kind == LuaTokenKind::TkColon.into()
471            || kind == LuaTokenKind::TkLeftBracket.into()
472    }
473
474    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
475    where
476        Self: Sized,
477    {
478        if Self::can_cast(syntax.kind().into()) {
479            Some(LuaIndexToken { token: syntax })
480        } else {
481            None
482        }
483    }
484}
485
486impl LuaIndexToken {
487    pub fn is_dot(&self) -> bool {
488        self.token.kind() == LuaTokenKind::TkDot.into()
489    }
490
491    pub fn is_colon(&self) -> bool {
492        self.token.kind() == LuaTokenKind::TkColon.into()
493    }
494
495    pub fn is_left_bracket(&self) -> bool {
496        self.token.kind() == LuaTokenKind::TkLeftBracket.into()
497    }
498}
499
500#[derive(Debug, Clone, PartialEq, Eq, Hash)]
501pub struct LuaDocDetailToken {
502    token: LuaSyntaxToken,
503}
504
505impl LuaAstToken for LuaDocDetailToken {
506    fn syntax(&self) -> &LuaSyntaxToken {
507        &self.token
508    }
509
510    fn can_cast(kind: LuaTokenKind) -> bool
511    where
512        Self: Sized,
513    {
514        kind == LuaTokenKind::TkDocDetail
515    }
516
517    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
518    where
519        Self: Sized,
520    {
521        if Self::can_cast(syntax.kind().into()) {
522            Some(LuaDocDetailToken { token: syntax })
523        } else {
524            None
525        }
526    }
527}
528
529impl LuaDocDetailToken {
530    pub fn get_detail(&self) -> &str {
531        self.token.text()
532    }
533}
534
535#[derive(Debug, Clone, PartialEq, Eq, Hash)]
536pub struct LuaDocVisibilityToken {
537    token: LuaSyntaxToken,
538}
539
540impl LuaAstToken for LuaDocVisibilityToken {
541    fn syntax(&self) -> &LuaSyntaxToken {
542        &self.token
543    }
544
545    fn can_cast(kind: LuaTokenKind) -> bool
546    where
547        Self: Sized,
548    {
549        kind == LuaTokenKind::TkDocVisibility || kind == LuaTokenKind::TkTagVisibility
550    }
551
552    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
553    where
554        Self: Sized,
555    {
556        if Self::can_cast(syntax.kind().into()) {
557            Some(LuaDocVisibilityToken { token: syntax })
558        } else {
559            None
560        }
561    }
562}
563
564impl LuaDocVisibilityToken {
565    pub fn get_visibility(&self) -> VisibilityKind {
566        VisibilityKind::to_visibility_kind(self.token.text())
567    }
568}
569
570#[derive(Debug, Clone, PartialEq, Eq, Hash)]
571pub struct LuaDocVersionNumberToken {
572    token: LuaSyntaxToken,
573}
574
575impl LuaAstToken for LuaDocVersionNumberToken {
576    fn syntax(&self) -> &LuaSyntaxToken {
577        &self.token
578    }
579
580    fn can_cast(kind: LuaTokenKind) -> bool
581    where
582        Self: Sized,
583    {
584        kind == LuaTokenKind::TkDocVersionNumber
585    }
586
587    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
588    where
589        Self: Sized,
590    {
591        if Self::can_cast(syntax.kind().into()) {
592            Some(LuaDocVersionNumberToken { token: syntax })
593        } else {
594            None
595        }
596    }
597}
598
599impl LuaDocVersionNumberToken {
600    pub fn get_version_number(&self) -> Option<LuaVersionNumber> {
601        let text = self.token.text();
602        LuaVersionNumber::from_str(text)
603    }
604}
605
606#[derive(Debug, Clone, PartialEq, Eq, Hash)]
607pub struct LuaDocTypeBinaryToken {
608    token: LuaSyntaxToken,
609}
610
611impl LuaAstToken for LuaDocTypeBinaryToken {
612    fn syntax(&self) -> &LuaSyntaxToken {
613        &self.token
614    }
615
616    fn can_cast(kind: LuaTokenKind) -> bool
617    where
618        Self: Sized,
619    {
620        kind == LuaTokenKind::TkDocOr
621            || kind == LuaTokenKind::TkDocAnd
622            || kind == LuaTokenKind::TkDocExtends
623            || kind == LuaTokenKind::TkDocIn
624            || kind == LuaTokenKind::TkDocContinueOr
625            || kind == LuaTokenKind::TkPlus
626            || kind == LuaTokenKind::TkMinus
627    }
628
629    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
630    where
631        Self: Sized,
632    {
633        if Self::can_cast(syntax.kind().into()) {
634            Some(LuaDocTypeBinaryToken { token: syntax })
635        } else {
636            None
637        }
638    }
639}
640
641impl LuaDocTypeBinaryToken {
642    pub fn get_op(&self) -> LuaTypeBinaryOperator {
643        LuaOpKind::to_type_binary_operator(self.token.kind().into())
644    }
645}
646
647#[derive(Debug, Clone, PartialEq, Eq, Hash)]
648pub struct LuaDocTypeUnaryToken {
649    token: LuaSyntaxToken,
650}
651
652impl LuaAstToken for LuaDocTypeUnaryToken {
653    fn syntax(&self) -> &LuaSyntaxToken {
654        &self.token
655    }
656
657    fn can_cast(kind: LuaTokenKind) -> bool
658    where
659        Self: Sized,
660    {
661        kind == LuaTokenKind::TkDocKeyOf
662    }
663
664    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
665    where
666        Self: Sized,
667    {
668        if Self::can_cast(syntax.kind().into()) {
669            Some(LuaDocTypeUnaryToken { token: syntax })
670        } else {
671            None
672        }
673    }
674}
675
676impl LuaDocTypeUnaryToken {
677    pub fn get_op(&self) -> LuaTypeUnaryOperator {
678        LuaOpKind::to_type_unary_operator(self.token.kind().into())
679    }
680}
681
682#[derive(Debug, Clone, PartialEq, Eq, Hash)]
683pub struct LuaPathToken {
684    token: LuaSyntaxToken,
685}
686
687impl LuaAstToken for LuaPathToken {
688    fn syntax(&self) -> &LuaSyntaxToken {
689        &self.token
690    }
691
692    fn can_cast(kind: LuaTokenKind) -> bool
693    where
694        Self: Sized,
695    {
696        kind == LuaTokenKind::TKDocPath
697    }
698
699    fn cast(syntax: LuaSyntaxToken) -> Option<Self>
700    where
701        Self: Sized,
702    {
703        if Self::can_cast(syntax.kind().into()) {
704            Some(LuaPathToken { token: syntax })
705        } else {
706            None
707        }
708    }
709}
710
711impl LuaPathToken {
712    pub fn get_path(&self) -> &str {
713        let text = self.token.text();
714        if text.starts_with('\"') || text.starts_with('\'') {
715            &text[1..text.len() - 1]
716        } else {
717            text
718        }
719    }
720}