跳转至

词法

源文件与编码

Lumos 仅接受 Unicode 源码文件,编码必须为 UTF-8、UTF-16 或 UTF-32。
所有内容区分大小写,且不允许 BOM;若检测到 BOM 将直接报错。

标识符

语法规则

标识符由字母、数字和下划线组成:

  • 首字符:必须为字母或下划线 [a-zA-Z_]
  • 后续字符:可为字母、数字或下划线 [a-zA-Z0-9_]*
  • 保留字:大部分情况下 Lumos 关键字不可作为标识符使用(见 关键字列表
  • 下划线前缀只分配给非公开成员:以单个下划线开头的标识符被约定为私有或内部使用,虽然语法上仍然有效,但建议遵循这一约定以提高代码可读性。
  • 同时添加下划线前后缀只分配给私有成员:以单个下划线开头并以单个下划线结尾的标识符被约定为私有成员,虽然语法上仍然有效,但建议遵循这一约定以提高代码可读性。
var i32 count = 0;      // ✓ 有效
val name = "Alice";     // ✓ 有效
i32 _private = 42;      // ✓ 有效(下划线前缀表示私有/内部)
i32 x123 = 1;           // ✓ 有效
i32 123var;             // ✗ 无效(以数字开头)

二进制标识符

默认标识符仅允许上述 ASCII 字符的子集,若需要使用其它内容作为名称,必须使用 $"..." 的形式,并遵循 b"..." 的字节串转义规则:

val $"变量" = 10;            // ✓ Unicode 标识符
val $"π" = 3.14159;          // ✓ 特殊符号
val $"😀" = "emoji";        // ✓ 表情符号
val $"var with spaces" = 42; // ✓ 包含空格
val $"\0\x12\x34\x56" = 0;   // ✓ 二进制内容

此时使用这些变量和函数时也需要使用 $"..." 的形式:

println($"变量"); // 输出 10

命名约定

虽然语法允许多种形式,但建议遵循以下命名约定以提高代码可读性和一致性:

类别 风格 示例
变量/参数 snake_case max_count, user_name, is_valid
函数 snake_case calculate_sum, handle_event, parse_json
类型/结构体 PascalCase Point, Vector, LinkedList
常量(lit/imv UPPER_CASE PI, MAX_SIZE, DEFAULT_TIMEOUT

空白字符

Lumos 认可的空白字符为 \x20(空格)、\x09(制表符)和 \x0A(换行符)。其它任何字符均不被视为空白字符。

行号在遇到换行符(LF)时递增,列号在换行处重置。回车符(CR, \x0D)本身不增加行号,但仅允许作为 CRLF 序列的一部分(即 CR 必须紧跟 LF);在其他位置出现 CR 将引发词法错误。

行首的空白(空格或制表符)被视为缩进。单个行的缩进必须只使用空格或只使用制表符,混用空格和制表符进行缩进会导致词法错误。

运算符

对于运算符,Lumos 采用简单且一致的规则:

  • 下列字符可作为运算符的一部分:! % ^ & * - + = | : < > , . ? / ~
  • 采用永远最长匹配原则进行运算符识别。

也就是说,遇到 a+-b 时会被解析为单个 +- 运算符,而不是 + 运算符后跟 - 运算符;如果未定义 +-,则会报错。

例如,我们可以用带斜线的标识符为运算符提供实现:

// 我们用 `\mul` 来表示 `*` 运算符
// `\mul_mul` 对应 `**` 运算符
def \mul_mul(int a, int b) -> int {
    return pow(a, b);
}

自定义运算符不得超过 4 个字符长度。


相关内容:语法入口见 语法