1use sipha::types::FromSyntaxKind;
6use sipha::SyntaxKinds;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, SyntaxKinds)]
9#[repr(u16)]
10pub enum Kind {
11 TriviaWs,
13 TriviaLineComment,
14 TriviaBlockComment,
15 TokNumber,
17 TokString,
18 TokIdent,
19 KwAbstract,
21 KwAnd,
22 KwAs,
23 KwBreak,
24 KwClass,
25 KwConst,
26 KwContinue,
27 KwDo,
28 KwElse,
29 KwFalse,
30 KwFor,
31 KwFunction,
32 KwGlobal,
33 KwIf,
34 KwIn,
35 KwInclude,
36 KwLet,
37 KwNew,
38 KwNot,
39 KwNull,
40 KwOr,
41 KwReturn,
42 KwTrue,
43 KwVar,
44 KwWhile,
45 KwXor,
46 KwFinal,
47 KwConstructor,
48 KwExtends,
49 KwStatic,
50 KwPublic,
51 KwPrivate,
52 KwProtected,
53 KwThis,
54 KwSuper,
55 KwInstanceof,
56 KwTry,
57 KwCatch,
58 KwSwitch,
59 KwCase,
60 KwDefault,
61 KwThrow,
62 KwReserved,
63 TokOp,
65 TokArrow,
66 TokDotDot,
67 TokDot,
68 TokColon,
69 TokComma,
70 TokSemi,
71 TokParenL,
72 TokParenR,
73 TokBracketL,
74 TokBracketR,
75 TokBraceL,
76 TokBraceR,
77 TokLemnisate,
78 TokPi,
79 TokEof,
81 NodeRoot,
83 NodeTokenStream,
84 NodeExpr,
85 NodePrimaryExpr,
86 NodeBinaryExpr,
87 NodeBinaryLevel, NodeUnaryExpr,
89 NodeCallExpr,
90 NodeMemberExpr,
91 NodeIndexExpr,
92 NodeArray,
93 NodeMap,
94 NodeMapPair,
95 NodeObject,
96 NodeObjectPair,
97 NodeSet,
98 NodeStmt,
99 NodeBlock,
100 NodeVarDecl,
101 NodeIfStmt,
102 NodeWhileStmt,
103 NodeForStmt,
104 NodeForInStmt,
105 NodeDoWhileStmt,
106 NodeReturnStmt,
107 NodeBreakStmt,
108 NodeContinueStmt,
109 NodeExprStmt,
110 NodeFunctionDecl,
111 NodeClassDecl,
112 NodeInclude,
113 NodeConstructorDecl,
114 NodeInterval,
115 NodeClassField,
116 NodeAsCast,
117 NodeAnonFn,
118 NodeTypeAnnot,
119 NodeParam,
120 NodeTypeExpr,
121 NodeTypeParams,
122 NodeSigFile,
124 NodeSigFunction,
125 NodeSigClass,
126 NodeSigMethod,
127 NodeSigConstructor,
128 NodeSigField,
129 NodeSigGlobal,
130 NodeSigParam,
131 NodeSigDocBlock,
133 TokSigDocLine,
135 TokSigDocBlock,
137}
138
139pub const SYNTHETIC_ROOT: sipha::types::SyntaxKind = u16::MAX;
141
142pub const KEYWORDS: &[&str] = &[
144 "abstract",
145 "and",
146 "as",
147 "break",
148 "case",
149 "catch",
150 "class",
151 "const",
152 "constructor",
153 "continue",
154 "default",
155 "do",
156 "else",
157 "extends",
158 "false",
159 "final",
160 "for",
161 "function",
162 "global",
163 "if",
164 "in",
165 "include",
166 "instanceof",
167 "let",
168 "new",
169 "not",
170 "null",
171 "or",
172 "private",
173 "protected",
174 "public",
175 "reserved",
176 "return",
177 "static",
178 "super",
179 "switch",
180 "this",
181 "throw",
182 "true",
183 "try",
184 "var",
185 "while",
186 "xor",
187];
188
189#[must_use]
192pub fn is_valid_identifier(name: &str) -> bool {
193 let mut chars = name.chars();
194 match chars.next() {
195 Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
196 _ => return false,
197 }
198 chars.all(|c| c.is_ascii_alphanumeric() || c == '_')
199}
200
201#[cfg(test)]
202mod tests {
203 use super::is_valid_identifier;
204
205 #[test]
206 fn valid_identifiers() {
207 assert!(is_valid_identifier("x"));
208 assert!(is_valid_identifier("_private"));
209 assert!(is_valid_identifier("foo_bar"));
210 assert!(is_valid_identifier("Cell"));
211 }
212
213 #[test]
214 fn invalid_identifiers() {
215 assert!(!is_valid_identifier(""));
216 assert!(!is_valid_identifier("123"));
217 assert!(!is_valid_identifier("bad name"));
218 assert!(!is_valid_identifier("x-y"));
219 }
220}
221
222pub const FIELD_RHS: sipha::types::FieldId = 0;
225
226pub fn kind_name(kind: sipha::types::SyntaxKind) -> &'static str {
228 if kind == SYNTHETIC_ROOT {
229 return "ROOT";
230 }
231 Kind::from_syntax_kind(kind).map_or("?", kind_name_enum)
232}
233
234fn kind_name_enum(k: Kind) -> &'static str {
235 match k {
236 Kind::TokNumber => "NUMBER",
237 Kind::TokString => "STRING",
238 Kind::TokIdent => "IDENT",
239 Kind::TokOp => "OP",
240 Kind::TokParenL => "(",
241 Kind::TokParenR => ")",
242 Kind::TokDotDot => "..",
243 Kind::NodeTokenStream => "TOKEN_STREAM",
244 Kind::NodeRoot => "ROOT",
245 Kind::NodeExpr => "EXPR",
246 Kind::NodeExprStmt => "EXPR_STMT",
247 Kind::NodeVarDecl => "VAR_DECL",
248 Kind::NodeIfStmt => "IF_STMT",
249 Kind::NodeWhileStmt => "WHILE_STMT",
250 Kind::NodeBlock => "BLOCK",
251 Kind::NodeReturnStmt => "RETURN_STMT",
252 Kind::NodeForStmt => "FOR_STMT",
253 Kind::NodeForInStmt => "FOR_IN_STMT",
254 Kind::NodeDoWhileStmt => "DO_WHILE_STMT",
255 Kind::NodeFunctionDecl => "FUNCTION_DECL",
256 Kind::NodeClassDecl => "CLASS_DECL",
257 Kind::NodeConstructorDecl => "CONSTRUCTOR_DECL",
258 Kind::NodeClassField => "CLASS_FIELD",
259 Kind::NodeInterval => "INTERVAL",
260 Kind::NodeInclude => "INCLUDE",
261 Kind::NodeArray => "ARRAY",
262 Kind::NodeMap => "MAP",
263 Kind::NodeMapPair => "MAP_PAIR",
264 Kind::NodeObject => "OBJECT",
265 Kind::NodeObjectPair => "OBJECT_PAIR",
266 Kind::NodeSet => "SET",
267 Kind::NodeTypeExpr => "TYPE_EXPR",
268 Kind::NodeTypeParams => "TYPE_PARAMS",
269 Kind::NodeAsCast => "AS_CAST",
270 Kind::NodeSigFile => "SIG_FILE",
271 Kind::NodeSigFunction => "SIG_FUNCTION",
272 Kind::NodeSigClass => "SIG_CLASS",
273 Kind::NodeSigMethod => "SIG_METHOD",
274 Kind::NodeSigConstructor => "SIG_CONSTRUCTOR",
275 Kind::NodeSigField => "SIG_FIELD",
276 Kind::NodeSigGlobal => "SIG_GLOBAL",
277 Kind::NodeSigParam => "SIG_PARAM",
278 Kind::NodeSigDocBlock => "SIG_DOC_BLOCK",
279 Kind::TokSigDocLine => "SIG_DOC_LINE",
280 Kind::TokSigDocBlock => "SIG_DOC_BLOCK_TOKEN",
281 _ => "?",
282 }
283}