No Semicolons Needed
背景
作者正在设计一门叫 Roto 的脚本语言,研究如何让分号可选。通过分析 11 种编程语言的实现方式,总结出以下几种模式。
核心问题:如何在没有显式分号的情况下,确定语句在哪里结束?
各语言方案对比
| 语言 | 策略 | 严格程度 |
|---|---|---|
| Python | 一行一语句 + 严格缩进 | 高 |
| Go | Lexer 自动插入分号 | 中 |
| Kotlin | 语法级别显式处理 | 高 |
| Swift | 尽可能解析,忽略新行 | 低 |
| Gleam | 智能续行分析 | 中 |
| JavaScript | 自动分号插入 (ASI) | 中 |
详细分析
Python: 简单但严格
一行一语句是核心规则。通过显式(\)或隐式(括号内)连接行。缩进是捕捉错误的唯一机制。
Go: Lexer 自动处理
Go 的 lexer 在特定 token 后自动插入分号(标识符、基本字面量、break/continue/return 等)。有趣的是,Go 会报错"未使用的值",提供了一些保护。
Kotlin: 最复杂但最灵活
将新行作为语法的一部分显式处理。不同运算符有不同的规则(如 && 允许两边换行,但 + 只允许在运算符后换行)。
Swift: 最宽松
尽可能向前解析,忽略新行。这意味着 2 * x - 3 和 2 * x\n- 3 结果相同。
对语言设计者的启示
- 没有完美方案,每种都有取舍
- 简单规则(Python/Go)更容易理解
- 复杂规则(Kotlin)更灵活但难维护
- Tree-sitter 语法维护者会更喜欢简单规则