1use crate::lexer;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
4#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
5#[repr(u16)]
6pub enum SyntaxKind {
7    IDENT_KW = 1,
9    DEFINED = 2,
11    DIGITS = 3,
13    PERIOD = 4,
16    PLUS = 5,
18    DASH = 6,
20    SLASH = 7,
22    ASTERISK = 8,
24    PERCENT = 9,
26    LANGLE = 10,
28    RANGLE = 11,
30    LBRACKET = 12,
32    RBRACKET = 13,
34    LPAREN = 14,
36    RPAREN = 15,
38    LBRACE = 16,
40    RBRACE = 17,
42    CARET = 18,
44    BAR = 19,
46    AMPERSAND = 20,
48    TILDE = 21,
50    EQUAL = 22,
52    BANG = 23,
54    COLON = 24,
56    SEMICOLON = 25,
58    COMMA = 26,
60    QUESTION = 27,
62    HASH = 28,
64    QUOTE_STRING = 29,
67    ANGLE_STRING = 30,
69    BACKSLASH = 31,
71    WS = 32,
73    NEWLINE = 33,
75    COMMENT = 34,
77    ERROR = 36,
81    LEFT_OP = 37,
84    RIGHT_OP = 38,
86    INC_OP = 39,
88    DEC_OP = 40,
90    LE_OP = 41,
92    GE_OP = 42,
94    EQ_OP = 43,
96    NE_OP = 44,
98    AND_OP = 45,
100    OR_OP = 46,
102    XOR_OP = 47,
104    MUL_ASSIGN = 48,
106    DIV_ASSIGN = 49,
108    ADD_ASSIGN = 50,
110    MOD_ASSIGN = 51,
112    LEFT_ASSIGN = 52,
114    RIGHT_ASSIGN = 53,
116    AND_ASSIGN = 54,
118    XOR_ASSIGN = 55,
120    OR_ASSIGN = 56,
122    SUB_ASSIGN = 57,
124    PP_CONCAT_OP = 58,
126    PP_CONCAT,
129    PP_EMPTY,
131    PP_INCLUDE,
133    PP_INCLUDE_PATH,
135    PP_DEFINE,
137    PP_DEFINE_ARGS,
138    PP_DEFINE_ARG,
139    PP_DEFINE_BODY,
140    PP_UNDEF,
142    PP_IDENT,
143    PP_IF,
145    PP_IF_EXPR,
146    PP_IFDEF,
148    PP_IFNDEF,
150    PP_ELSE,
152    PP_ELIF,
154    PP_ENDIF,
156    PP_ERROR,
158    PP_ERROR_BODY,
160    PP_PRAGMA,
162    PP_PRAGMA_BODY,
164    PP_EXTENSION,
166    PP_VERSION,
168    PP_VERSION_NUMBER,
169    PP_VERSION_PROFILE,
170    PP_LINE,
172    PP_LINE_BODY,
174    ROOT,
176    _LAST,
177}
178
179impl SyntaxKind {
180    pub fn is_whitespace(&self) -> bool {
181        matches!(self, Self::COMMENT | Self::WS | Self::NEWLINE)
182    }
183
184    pub fn is_trivia(&self) -> bool {
185        matches!(self, Self::COMMENT | Self::WS)
186    }
187
188    pub fn is_newline(&self) -> bool {
189        matches!(self, Self::NEWLINE)
190    }
191
192    pub fn paste(lhs: Self, rhs: Self) -> Self {
193        use SyntaxKind::*;
194
195        match lhs {
196            IDENT_KW => match rhs {
197                DEFINED | IDENT_KW | DIGITS => IDENT_KW,
198                _ => ERROR,
199            },
200            DIGITS => match rhs {
201                IDENT_KW | DIGITS | PERIOD | DASH | PLUS => DIGITS,
202                _ => ERROR,
203            },
204            LEFT_OP => match rhs {
205                EQUAL => LEFT_ASSIGN,
206                _ => ERROR,
207            },
208            RIGHT_OP => match rhs {
209                EQUAL => RIGHT_ASSIGN,
210                _ => ERROR,
211            },
212            PERIOD => match rhs {
213                DIGITS => DIGITS,
214                _ => ERROR,
215            },
216            EQUAL => match rhs {
217                EQUAL => EQ_OP,
218                _ => ERROR,
219            },
220            BANG => match rhs {
221                EQUAL => NE_OP,
222                _ => ERROR,
223            },
224            DASH => match rhs {
225                DASH => DEC_OP,
226                EQUAL => SUB_ASSIGN,
227                _ => ERROR,
228            },
229            PLUS => match rhs {
230                PLUS => INC_OP,
231                EQUAL => ADD_ASSIGN,
232                _ => ERROR,
233            },
234            ASTERISK => match rhs {
235                EQUAL => MUL_ASSIGN,
236                _ => ERROR,
237            },
238            SLASH => match rhs {
239                EQUAL => DIV_ASSIGN,
240                _ => ERROR,
241            },
242            PERCENT => match rhs {
243                EQUAL => MOD_ASSIGN,
244                _ => ERROR,
245            },
246            LANGLE => match rhs {
247                LANGLE => LEFT_OP,
248                EQUAL => LE_OP,
249                _ => ERROR,
250            },
251            RANGLE => match rhs {
252                RANGLE => RIGHT_OP,
253                EQUAL => GE_OP,
254                _ => ERROR,
255            },
256            BAR => match rhs {
257                BAR => OR_OP,
258                EQUAL => OR_ASSIGN,
259                _ => ERROR,
260            },
261            CARET => match rhs {
262                CARET => XOR_OP,
263                EQUAL => XOR_ASSIGN,
264                _ => ERROR,
265            },
266            AMPERSAND => match rhs {
267                AMPERSAND => AND_OP,
268                EQUAL => AND_ASSIGN,
269                _ => ERROR,
270            },
271            HASH => match rhs {
272                HASH => PP_CONCAT_OP,
273                _ => ERROR,
274            },
275            _ => ERROR,
276        }
277    }
278}
279
280impl From<lexer::Token> for SyntaxKind {
281    fn from(s: lexer::Token) -> Self {
282        use SyntaxKind::*;
283
284        if s == lexer::Token::LINECONT {
286            return WS;
287        }
288
289        unsafe { std::mem::transmute(std::mem::transmute::<lexer::Token, u16>(s)) }
291    }
292}
293
294impl From<SyntaxKind> for rowan::SyntaxKind {
295    fn from(kind: SyntaxKind) -> Self {
296        Self(kind as u16)
297    }
298}