1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/// Returns whether `chr` is a valid atom character outside a
/// string (i.e. one of `:atomchar:` documented at `TreeNode::Atom`).
#[inline]
pub const fn is_atom_chr(chr: char) -> bool {
matches!(
chr,
'!' | '#'
| '$'
| '%'
| '&'
| '*'
| '+'
| '-'
| '.'
| '/'
| '0'..='9'
| ':'
| '<'
| '='
| '>'
| '?'
| '@'
| 'A'..='Z'
| '_'
| 'a'..='z'
| '~'
)
}
/// Returns whether `chr` is a valid atom character inside a
/// string, excluding `"` and `\` (i.e. one of `:stringchar:`
/// documented at `TreeNode::Atom`).
#[inline]
pub const fn is_atom_string_chr(chr: char) -> bool {
matches!(chr, ' '..='~' if chr != '"' && chr != '\\')
}
/// Checks whether `atom` is a valid atom (i.e. matches the regular
/// expression documented at `TreeNode::Atom`).
pub fn check_atom(atom: &str) -> bool {
if atom.is_empty() {
// Empty atom
return false;
}
let mut iter = atom.chars();
let mut in_string = false;
loop {
if !in_string {
match iter.next() {
None => return true,
Some('"') => in_string = true,
Some(chr) if is_atom_chr(chr) => {}
// Invalid character
Some(_) => return false,
}
} else {
match iter.next() {
// Unfinished string
None => return false,
Some('"') => in_string = false,
Some('\\') => match iter.next() {
Some('"' | '\\') => {}
Some(chr) if is_atom_string_chr(chr) => {}
// Invalid character or unfinished string
Some(_) | None => return false,
},
Some(chr) if is_atom_string_chr(chr) => {}
// Invalid character
Some(_) => return false,
}
}
}
}