macroonz_compiler/token/generation/spelling.rs
1//! Judging the identifier spellings a renderer may write.
2
3use crate::token::bank::rust_keyword;
4
5/// Whether one spelling is a single Rust identifier a rendering is willing to write.
6///
7/// ASCII only, and `_` alone is refused because it is the wildcard pattern rather than a name.
8/// ONE alphabet, seated with the token home, for every spelling any home renders in identifier position — a path segment, an exported address, a stamped item's own name, a declared grammar's word.
9/// A second copy would agree with this one until one of them was edited, and the failure would surface in a consumer's build with no idea where the name came from; the homes that once each carried a copy now all read this seat.
10#[must_use]
11pub fn rendered_identifier(spelling: &str) -> bool {
12 let mut characters = spelling.chars();
13 let Some(head) = characters.next() else {
14 return false;
15 };
16 if !head.is_ascii_alphabetic() && head != '_' {
17 return false;
18 }
19 if spelling == "_" {
20 return false;
21 }
22 characters.all(|character| character.is_ascii_alphanumeric() || character == '_')
23}
24
25/// Whether one spelling can NAME a rendered item: a single identifier the language has not already taken.
26///
27/// The identifier alphabet here and the keyword bank are the two halves of one law: the alphabet says which spellings can be a name, the bank says which of those the language took, and an item name must clear both.
28/// The direct grammars keep reading the two halves separately, because an authored declaration deserves a refusal naming which half disagreed at which token; every constructor that mints a name or a path segment programmatically reads this one.
29#[must_use]
30pub fn rendered_name(spelling: &str) -> bool {
31 rendered_identifier(spelling) && !rust_keyword(spelling)
32}