Skip to main content

sml_pattern/
i18n.rs

1//! 关键字国际化:把「书写形式」与「内部语义」解耦。
2//!
3//! # 为什么不是硬编码别名
4//!
5//! 若在解析器里写死 `if k == "字面" || k == "lit"`,每加一种语言都要改核心代码,
6//! 且第三方无法自带方言。这里抽象为 [`KeywordTable`] trait:
7//!
8//! - 内置三张表:[`CHINESE`] / [`ENGLISH`] / [`BILINGUAL`](默认,两种写法等价)
9//! - 用户可实现 trait 自带任何语言,或构造 [`StaticTable`]
10//!
11//! 注意「机翻等价」的界定:**只替换关键字本身,不动结构标记**
12//! (`@` `:` `{}` `[]` `&` 原样保留),因此语法结构在所有语言下一致。
13
14/// 与语言无关的**内部语义**。任何书写形式都先映射到它,再由它驱动编译。
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum Concept {
17    // —— 模式元素 ——
18    /// 字面量:`字面` / `lit`
19    Lit,
20    /// 字符类:`类` / `class`
21    Class,
22    /// 选择:`任一` / `alt`
23    Alt,
24    /// 内联组:`组` / `group`
25    Group,
26    /// 序列:`序列` / `seq`
27    Seq,
28    /// 引用另一规则:`用` / `use`
29    Use,
30    /// 推进直到:`直到` / `until`
31    Until,
32    /// 量词:`次` / `times`
33    Times,
34    /// 可选:`可选` / `optional`
35    Optional,
36    /// 命名捕获:`名` / `name`
37    Name,
38    /// regex 逃生舱:`正则` / `regex`
39    Regex,
40
41    // —— 量词写成对象时的字段 ——
42    /// `最小` / `min`
43    Min,
44    /// `最大` / `max`
45    Max,
46
47    // —— 字符类的取值 ——
48    /// `数字` / `digit`
49    Digit,
50    /// `字母` / `alpha`(含汉字)
51    Alpha,
52    /// `空白` / `space`
53    Space,
54    /// `字` / `word`
55    Word,
56    /// `任意` / `any`
57    Any,
58
59    // —— 特殊终止符 ——
60    /// `行尾` / `eol`
61    Eol,
62}
63
64/// 关键字表:书写形式 → 内部语义。
65///
66/// 实现此 trait 即可接入任意语言,无需改动编译逻辑。
67pub trait KeywordTable {
68    fn lookup(&self, word: &str) -> Option<Concept>;
69}
70
71/// 静态表:由「书写形式 → 语义」的常量切片构造。
72pub struct StaticTable {
73    entries: &'static [(&'static str, Concept)],
74}
75
76impl StaticTable {
77    pub const fn new(entries: &'static [(&'static str, Concept)]) -> Self {
78        Self { entries }
79    }
80}
81
82impl KeywordTable for StaticTable {
83    fn lookup(&self, word: &str) -> Option<Concept> {
84        self.entries
85            .iter()
86            .find(|(w, _)| *w == word)
87            .map(|(_, c)| *c)
88    }
89}
90
91use Concept::*;
92
93/// 中文表
94pub const CHINESE: StaticTable = StaticTable::new(&[
95    ("字面", Lit),
96    ("类", Class),
97    ("任一", Alt),
98    ("组", Group),
99    ("序列", Seq),
100    ("用", Use),
101    ("直到", Until),
102    ("次", Times),
103    ("可选", Optional),
104    ("名", Name),
105    ("正则", Regex),
106    ("最小", Min),
107    ("最大", Max),
108    ("数字", Digit),
109    ("字母", Alpha),
110    ("空白", Space),
111    ("字", Word),
112    ("任意", Any),
113    ("行尾", Eol),
114    ("末尾", Eol),
115]);
116
117/// 英文表
118pub const ENGLISH: StaticTable = StaticTable::new(&[
119    ("lit", Lit),
120    ("literal", Lit),
121    ("class", Class),
122    ("alt", Alt),
123    ("any-of", Alt),
124    ("group", Group),
125    ("seq", Seq),
126    ("use", Use),
127    ("until", Until),
128    ("times", Times),
129    ("repeat", Times),
130    ("optional", Optional),
131    ("name", Name),
132    ("regex", Regex),
133    ("re", Regex),
134    ("min", Min),
135    ("max", Max),
136    ("digit", Digit),
137    ("alpha", Alpha),
138    ("space", Space),
139    ("word", Word),
140    ("any", Any),
141    ("eol", Eol),
142    ("end", Eol),
143]);
144
145/// 双语表(默认):同一份文档里中英写法等价,可混用。
146///
147/// 这是 SML「中文关键字 = 机翻等价」的直接体现:不发明新语法,
148/// 只是同一个语义有两种书写形式。
149pub const BILINGUAL: StaticTable = StaticTable::new(&[
150    // 中文
151    ("字面", Lit),
152    ("类", Class),
153    ("任一", Alt),
154    ("组", Group),
155    ("序列", Seq),
156    ("用", Use),
157    ("直到", Until),
158    ("次", Times),
159    ("可选", Optional),
160    ("名", Name),
161    ("正则", Regex),
162    ("最小", Min),
163    ("最大", Max),
164    ("数字", Digit),
165    ("字母", Alpha),
166    ("空白", Space),
167    ("字", Word),
168    ("任意", Any),
169    ("行尾", Eol),
170    ("末尾", Eol),
171    // 英文
172    ("lit", Lit),
173    ("literal", Lit),
174    ("class", Class),
175    ("alt", Alt),
176    ("any-of", Alt),
177    ("group", Group),
178    ("seq", Seq),
179    ("use", Use),
180    ("until", Until),
181    ("times", Times),
182    ("repeat", Times),
183    ("optional", Optional),
184    ("name", Name),
185    ("regex", Regex),
186    ("re", Regex),
187    ("min", Min),
188    ("max", Max),
189    ("digit", Digit),
190    ("alpha", Alpha),
191    ("space", Space),
192    ("word", Word),
193    ("any", Any),
194    ("eol", Eol),
195    ("end", Eol),
196]);