1use unicode_xid::UnicodeXID;
2
3const KEYWORDS: [&str; 38] = [
5 "and",
6 "or",
7 "if",
8 "then",
9 "else",
10 "is_some",
11 "is_none",
12 "some",
13 "int",
14 "float",
15 "dec",
16 "true",
17 "false",
18 "none",
19 "contains",
20 "in",
21 "to_upper",
22 "to_lower",
23 "uppercase",
24 "lowercase",
25 "starts",
26 "ends",
27 "trim",
28 "round",
29 "floor",
30 "fract",
31 "date_time",
32 "datetime",
33 "duration",
34 "year",
35 "month",
36 "week",
37 "day",
38 "hour",
39 "minute",
40 "second",
41 "key",
42 "val",
43];
44
45pub(crate) fn is_reserved_keyword(name: &str) -> bool {
46 KEYWORDS.contains(&name)
47}
48
49pub(crate) fn is_valid_identifier(name: &str) -> bool {
50 let mut chars = name.chars();
51 match chars.next() {
52 Some(start) => {
53 start == '_' || start.is_xid_start() && chars.all(UnicodeXID::is_xid_continue)
54 }
55 None => false,
56 }
57}
58
59#[cfg(test)]
60mod when_testing_identifier {
61 use crate::expr::keywords::is_valid_identifier;
62
63 #[test]
64 fn should_allow_leading_underscore() {
65 assert!(is_valid_identifier("_id"));
66 }
67
68 #[test]
69 fn should_allow_leading_letter() {
70 assert!(is_valid_identifier("id"));
71 }
72
73 #[test]
74 fn should_disallow_leading_number() {
75 assert!(!is_valid_identifier("1id"));
76 }
77
78 #[test]
79 fn should_allow_trailing_number() {
80 assert!(is_valid_identifier("id1"));
81 }
82}