luau_lexer/token/
impl.rs

1//! All `impl` blocks for [`TokenType`]
2
3use crate::{
4    prelude::{
5        Comment, CompoundOperator, Keyword, Lexable, Lexer, Literal, Operator, Error,
6        PartialKeyword, Symbol, TokenType,
7    },
8    utils::is_identifier_start,
9};
10
11impl Lexable for TokenType {
12    fn try_lex(lexer: &mut Lexer) -> Option<Self> {
13        let character = lexer.current_char()?;
14        let start = lexer.lexer_position;
15
16        match character {
17            '0'..='9' => {
18                if let Some(number) = Literal::parse_number(lexer) {
19                    return Some(Self::Literal(number));
20                }
21            }
22            '.' => {
23                let next_character = lexer.next_char();
24                if matches!(next_character, Some('0'..='9')) {
25                    if let Some(number) = Literal::parse_number(lexer) {
26                        return Some(Self::Literal(number));
27                    }
28                }
29                lexer.consume('.');
30
31                let next_character = lexer.current_char();
32                if next_character == Some('.') {
33                    lexer.consume('.');
34
35                    if lexer.consume('.') {
36                        return Some(Self::Symbol(Symbol::Ellipses));
37                    } else {
38                        let operator = Operator::Concatenation;
39
40                        return CompoundOperator::try_from_operator(operator, lexer)
41                            .map(Self::CompoundOperator)
42                            .or(Some(Self::Operator(operator)));
43                    }
44                } else {
45                    return Some(Self::Symbol(Symbol::Dot));
46                }
47            }
48            '\'' | '"' | '`' => {
49                if let Some(string) = Literal::parse_string(lexer) {
50                    return Some(Self::Literal(string));
51                }
52            }
53            '[' => {
54                if matches!(lexer.next_char(), Some('[' | '=')) {
55                    if let Some(string) = Literal::parse_string(lexer) {
56                        return Some(Self::Literal(string));
57                    }
58                }
59                lexer.consume('[');
60
61                return Some(Self::Symbol(Symbol::OpeningBrackets));
62            }
63            '>' if lexer.consume_with_next('=') => {
64                return Some(Self::CompoundOperator(
65                    CompoundOperator::GreaterThanOrEqualTo,
66                ));
67            }
68            '<' if lexer.consume_with_next('=') => {
69                return Some(Self::CompoundOperator(CompoundOperator::LessThanOrEqualTo));
70            }
71            '-' if lexer.consume_with_next('-') => {
72                return Comment::try_lex(lexer).map(Self::Comment)
73            }
74            '-' if lexer.consume_with_next('>') => {
75                return Some(Self::Symbol(Symbol::Arrow));
76            }
77            '=' => {
78                lexer.consume('=');
79
80                if lexer.consume('=') {
81                    return Some(Self::CompoundOperator(CompoundOperator::EqualEqual));
82                } else {
83                    return Some(Self::Symbol(Symbol::Equal));
84                }
85            }
86            ':' if lexer.consume_with_next(':') => {
87                return Some(Self::Symbol(Symbol::Typecast));
88            }
89            _ if is_identifier_start(character) => {
90                let word = lexer.consume_identifier();
91
92                if let Some(keyword) = Keyword::try_from_str(&word) {
93                    return Some(Self::Keyword(keyword));
94                } else if let Some(partial_keyword) = PartialKeyword::try_from_str(&word) {
95                    return Some(Self::PartialKeyword(partial_keyword));
96                }
97
98                match word.as_str() {
99                    "true" => return Some(Self::Literal(Literal::Boolean(true))),
100                    "false" => return Some(Self::Literal(Literal::Boolean(false))),
101                    "and" => return Some(Self::Operator(Operator::And)),
102                    "or" => return Some(Self::Operator(Operator::Or)),
103                    "not" => return Some(Self::Operator(Operator::Not)),
104                    _ => return Some(Self::Identifier(word)),
105                }
106            }
107            _ => {
108                if let Some(symbol) = Symbol::try_from_char(character, lexer) {
109                    return Some(Self::Symbol(symbol));
110                }
111                if let Some(operator) = Operator::try_from_chars(character, lexer) {
112                    return CompoundOperator::try_from_operator(operator, lexer)
113                        .map(Self::CompoundOperator)
114                        .or(Some(Self::Operator(operator)));
115                }
116            }
117        }
118
119        lexer.increment_position(1);
120
121        Some(Self::Error(Error::new(
122            start,
123            format!("Unexpected character: {}", character),
124            Some(lexer.lexer_position),
125        )))
126    }
127}