标识符中的有效字符是什么?

What is a valid character in an identifier called?

标识符通常由下划线、数字组成;以及第一个字符不是数字的大写和小写字符。在编写词法分析器时,通常会有 is_digitis_alnum 等辅助函数。如果要实现这样一个函数来扫描标识符中使用的字符,它会被称为什么?显然,is_identifier 是错误的,因为那将是词法分析器扫描的整个标记,而不是单个字符。我想 is_alnum_or_underscore 虽然很冗长,但还是准确的。这么普通的东西,我觉得应该用一个词来形容。

Unicode Annex 31 (Unicode Identifier and Pattern Syntax, UAX31) 定义了标识符词法语法定义的框架,可能与我们将使用标准术语。 UAX31 被 Python 和 Rust 使用(通过引用),并已被批准用于 C++23。所以我想这是相当主流的。

UAX31 定义了三组标识符字符,它称为 StartContinueMedial.所有 Start 字符也是 Continue 字符;没有 中间 字符是 继续 字符。

这导致了简单的正则表达式(UAX31-D1 默认标识符语法):

<Identifier> := <Start> <Continue>* (<Medial> <Continue>+)*

声称符合 UAX31 的编程语言不需要接受每个集合的确切成员资格,但它必须明确说明所谓的“配置文件”中的偏差。 (还有其他七项要求,与本题无关,想掉进很深的兔子洞,看文档)

这可以进一步简化,因为 UAX31 和(据我所知)任何主要语言的配置文件都没有在 Medial 中放置任何字符。所以你可以顺其自然,只定义两个类别:identifier-startidentifier-continue,其中第一个是第二个的子集。

您会在许多语法文档中看到:

Python
identifier   ::=  xid_start xid_continue*
Rust
IDENTIFIER_OR_KEYWORD : XID_Start XID_Continue*
                      | _ XID_Continue+
C++
identifier:
        identifier-start
        identifier identifier-continue
这就是我的建议。但是还有很多其他的可能性:
Swift
调用集 identifier-headidentifier-characters
Java
调用它们 JavaLetterJavaLetterOrDigit
C
定义了identifier-nondigitidentifier-digit;继续将是两个集合的并集。