1use styx_parse::TokenKind;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14#[repr(u16)]
15#[allow(non_camel_case_types)]
16#[allow(clippy::manual_non_exhaustive)] pub enum SyntaxKind {
18 L_BRACE = 0,
22 R_BRACE,
24 L_PAREN,
26 R_PAREN,
28 COMMA,
30 GT,
32 AT,
34
35 BARE_SCALAR,
38 QUOTED_SCALAR,
40 RAW_SCALAR,
42 HEREDOC_START,
44 HEREDOC_CONTENT,
46 HEREDOC_END,
48
49 LINE_COMMENT,
52 DOC_COMMENT,
54
55 WHITESPACE,
58 NEWLINE,
60
61 EOF,
64 ERROR,
66
67 #[doc(hidden)]
69 __LAST_TOKEN,
70
71 DOCUMENT,
74 ENTRY,
76 OBJECT,
78 SEQUENCE,
80 SCALAR,
82 UNIT,
84 TAG,
86 TAG_NAME,
88 TAG_PAYLOAD,
90 KEY,
92 VALUE,
94 HEREDOC,
96 ATTRIBUTES,
98 ATTRIBUTE,
100}
101
102impl SyntaxKind {
103 pub fn is_token(self) -> bool {
105 (self as u16) < (Self::__LAST_TOKEN as u16)
106 }
107
108 pub fn is_node(self) -> bool {
110 (self as u16) > (Self::__LAST_TOKEN as u16)
111 }
112
113 pub fn is_trivia(self) -> bool {
115 matches!(self, Self::WHITESPACE | Self::NEWLINE | Self::LINE_COMMENT)
116 }
117}
118
119impl From<TokenKind> for SyntaxKind {
120 fn from(kind: TokenKind) -> Self {
121 match kind {
122 TokenKind::LBrace => Self::L_BRACE,
123 TokenKind::RBrace => Self::R_BRACE,
124 TokenKind::LParen => Self::L_PAREN,
125 TokenKind::RParen => Self::R_PAREN,
126 TokenKind::Comma => Self::COMMA,
127 TokenKind::Gt => Self::GT,
128 TokenKind::At => Self::AT,
129 TokenKind::BareScalar => Self::BARE_SCALAR,
130 TokenKind::QuotedScalar => Self::QUOTED_SCALAR,
131 TokenKind::RawScalar => Self::RAW_SCALAR,
132 TokenKind::HeredocStart => Self::HEREDOC_START,
133 TokenKind::HeredocContent => Self::HEREDOC_CONTENT,
134 TokenKind::HeredocEnd => Self::HEREDOC_END,
135 TokenKind::LineComment => Self::LINE_COMMENT,
136 TokenKind::DocComment => Self::DOC_COMMENT,
137 TokenKind::Whitespace => Self::WHITESPACE,
138 TokenKind::Newline => Self::NEWLINE,
139 TokenKind::Eof => Self::EOF,
140 TokenKind::Error => Self::ERROR,
141 }
142 }
143}
144
145impl From<SyntaxKind> for rowan::SyntaxKind {
146 fn from(kind: SyntaxKind) -> Self {
147 rowan::SyntaxKind(kind as u16)
148 }
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub enum StyxLanguage {}
154
155impl rowan::Language for StyxLanguage {
156 type Kind = SyntaxKind;
157
158 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
159 Self::Kind::from_raw(raw.0).expect("invalid SyntaxKind value from rowan")
160 }
161
162 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
163 rowan::SyntaxKind(kind as u16)
164 }
165}
166
167impl SyntaxKind {
168 pub const fn from_raw(raw: u16) -> Option<Self> {
171 match raw {
172 0 => Some(Self::L_BRACE),
173 1 => Some(Self::R_BRACE),
174 2 => Some(Self::L_PAREN),
175 3 => Some(Self::R_PAREN),
176 4 => Some(Self::COMMA),
177 5 => Some(Self::GT),
178 6 => Some(Self::AT),
179 7 => Some(Self::BARE_SCALAR),
180 8 => Some(Self::QUOTED_SCALAR),
181 9 => Some(Self::RAW_SCALAR),
182 10 => Some(Self::HEREDOC_START),
183 11 => Some(Self::HEREDOC_CONTENT),
184 12 => Some(Self::HEREDOC_END),
185 13 => Some(Self::LINE_COMMENT),
186 14 => Some(Self::DOC_COMMENT),
187 15 => Some(Self::WHITESPACE),
188 16 => Some(Self::NEWLINE),
189 17 => Some(Self::EOF),
190 18 => Some(Self::ERROR),
191 20 => Some(Self::DOCUMENT),
193 21 => Some(Self::ENTRY),
194 22 => Some(Self::OBJECT),
195 23 => Some(Self::SEQUENCE),
196 24 => Some(Self::SCALAR),
197 25 => Some(Self::UNIT),
198 26 => Some(Self::TAG),
199 27 => Some(Self::TAG_NAME),
200 28 => Some(Self::TAG_PAYLOAD),
201 29 => Some(Self::KEY),
202 30 => Some(Self::VALUE),
203 31 => Some(Self::HEREDOC),
204 32 => Some(Self::ATTRIBUTES),
205 33 => Some(Self::ATTRIBUTE),
206 _ => None,
207 }
208 }
209}
210
211pub type SyntaxNode = rowan::SyntaxNode<StyxLanguage>;
213
214pub type SyntaxToken = rowan::SyntaxToken<StyxLanguage>;
216
217pub type SyntaxElement = rowan::SyntaxElement<StyxLanguage>;
219
220#[cfg(test)]
221mod tests {
222 use super::*;
223 use rowan::Language;
224
225 #[test]
226 fn token_vs_node() {
227 assert!(SyntaxKind::L_BRACE.is_token());
228 assert!(SyntaxKind::WHITESPACE.is_token());
229 assert!(SyntaxKind::ERROR.is_token());
230
231 assert!(SyntaxKind::DOCUMENT.is_node());
232 assert!(SyntaxKind::ENTRY.is_node());
233 assert!(SyntaxKind::OBJECT.is_node());
234 }
235
236 #[test]
237 fn trivia() {
238 assert!(SyntaxKind::WHITESPACE.is_trivia());
239 assert!(SyntaxKind::NEWLINE.is_trivia());
240 assert!(SyntaxKind::LINE_COMMENT.is_trivia());
241
242 assert!(!SyntaxKind::DOC_COMMENT.is_trivia());
243 assert!(!SyntaxKind::BARE_SCALAR.is_trivia());
244 }
245
246 #[test]
247 fn token_kind_conversion() {
248 assert_eq!(SyntaxKind::from(TokenKind::LBrace), SyntaxKind::L_BRACE);
249 assert_eq!(
250 SyntaxKind::from(TokenKind::BareScalar),
251 SyntaxKind::BARE_SCALAR
252 );
253 assert_eq!(SyntaxKind::from(TokenKind::Newline), SyntaxKind::NEWLINE);
254 }
255
256 #[test]
257 fn rowan_roundtrip() {
258 let kind = SyntaxKind::DOCUMENT;
259 let raw = StyxLanguage::kind_to_raw(kind);
260 let back = StyxLanguage::kind_from_raw(raw);
261 assert_eq!(kind, back);
262 }
263}