glsl_lang_pp/parser/
syntax_kind.rs

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    /// Identifier or keyword
8    IDENT_KW = 1,
9    /// defined preprocessor keyword
10    DEFINED = 2,
11    /// Digit sequence
12    DIGITS = 3,
13    // Single-char tokens
14    /// .
15    PERIOD = 4,
16    /// +
17    PLUS = 5,
18    /// -
19    DASH = 6,
20    /// /
21    SLASH = 7,
22    /// *
23    ASTERISK = 8,
24    /// %
25    PERCENT = 9,
26    /// <
27    LANGLE = 10,
28    /// >
29    RANGLE = 11,
30    /// [
31    LBRACKET = 12,
32    /// ]
33    RBRACKET = 13,
34    /// (
35    LPAREN = 14,
36    /// )
37    RPAREN = 15,
38    /// {
39    LBRACE = 16,
40    /// }
41    RBRACE = 17,
42    /// ^
43    CARET = 18,
44    /// |
45    BAR = 19,
46    /// &
47    AMPERSAND = 20,
48    /// ~
49    TILDE = 21,
50    /// =
51    EQUAL = 22,
52    /// !
53    BANG = 23,
54    /// :
55    COLON = 24,
56    /// ;
57    SEMICOLON = 25,
58    /// ,
59    COMMA = 26,
60    /// ?
61    QUESTION = 27,
62    /// #
63    HASH = 28,
64    // Other
65    /// "string"
66    QUOTE_STRING = 29,
67    /// <string>
68    ANGLE_STRING = 30,
69    /// \
70    BACKSLASH = 31,
71    /// Whitespace
72    WS = 32,
73    /// Newline
74    NEWLINE = 33,
75    /// Comment (single-line or multi-line)
76    COMMENT = 34,
77    // Replaced by WS in this step
78    // LINECONT = 35,
79    /// Invalid token
80    ERROR = 36,
81    // Multi-char tokens
82    /// <<
83    LEFT_OP = 37,
84    /// >>
85    RIGHT_OP = 38,
86    /// ++
87    INC_OP = 39,
88    /// --
89    DEC_OP = 40,
90    /// <=
91    LE_OP = 41,
92    /// >=
93    GE_OP = 42,
94    /// ==
95    EQ_OP = 43,
96    /// !=
97    NE_OP = 44,
98    /// &&
99    AND_OP = 45,
100    /// ||
101    OR_OP = 46,
102    /// ^^
103    XOR_OP = 47,
104    /// *=
105    MUL_ASSIGN = 48,
106    /// /=
107    DIV_ASSIGN = 49,
108    /// +=
109    ADD_ASSIGN = 50,
110    /// %=
111    MOD_ASSIGN = 51,
112    /// <<=
113    LEFT_ASSIGN = 52,
114    /// >>=
115    RIGHT_ASSIGN = 53,
116    /// &=
117    AND_ASSIGN = 54,
118    /// ^=
119    XOR_ASSIGN = 55,
120    /// |=
121    OR_ASSIGN = 56,
122    /// -=
123    SUB_ASSIGN = 57,
124    /// ##
125    PP_CONCAT_OP = 58,
126    // Extra types
127    /// Concatenation expression
128    PP_CONCAT,
129    /// #
130    PP_EMPTY,
131    /// #include
132    PP_INCLUDE,
133    /// #include path
134    PP_INCLUDE_PATH,
135    /// #define
136    PP_DEFINE,
137    PP_DEFINE_ARGS,
138    PP_DEFINE_ARG,
139    PP_DEFINE_BODY,
140    /// #undef
141    PP_UNDEF,
142    PP_IDENT,
143    /// #if
144    PP_IF,
145    PP_IF_EXPR,
146    /// #ifdef
147    PP_IFDEF,
148    /// #ifndef
149    PP_IFNDEF,
150    /// #else
151    PP_ELSE,
152    /// #elif
153    PP_ELIF,
154    /// #endif
155    PP_ENDIF,
156    /// #error
157    PP_ERROR,
158    /// #error body
159    PP_ERROR_BODY,
160    /// #pragma
161    PP_PRAGMA,
162    /// #pragma body
163    PP_PRAGMA_BODY,
164    /// #extension
165    PP_EXTENSION,
166    /// #version
167    PP_VERSION,
168    PP_VERSION_NUMBER,
169    PP_VERSION_PROFILE,
170    /// #line
171    PP_LINE,
172    /// #line body
173    PP_LINE_BODY,
174    /// AST root
175    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        // A stray line continuation should just be part of whitespace
285        if s == lexer::Token::LINECONT {
286            return WS;
287        }
288
289        // SAFETY: Aside from LINECONT, SyntaxKind is a superset of lexer::Token
290        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}