## 语法范式
注：用全角空格达成对齐效果
```
模块 : 注水声明列表

注水声明列表 : // 空
　　　　　　 | 声明列表
　　　　　　 | 声明列表 换行
　　　　　　 | 声明列表 分号

声明列表 : 声明
　　　　 | 声明列表 换行 声明
　　　　 | 声明列表 分号 声明

声明 : 类型定义
　　 | 函数
　　 | 条件声明
　　 | 每当声明
　　 | 对于声明
　　 | 外部声明
　　 | 引用声明
　　 | 表达式声明
　　 | 赋值
　　 | 运算赋值
　　 | 类型赋值
　　 | 终止声明
　　 | 跳过声明
　　 | 试试声明
　　 | 抛出声明
　　 | 返回声明
　　 | 块

抛出声明 : 动词_抛出 表达式

顺便处理 : 各表达式前缀 符号_赋值 表达式
　　　　 | 表达式前缀 符号_赋值 表达式
　　　　 | 表达式

试试声明 : 动词_试试 顺便处理 块
　　　　 | 动词_试试 顺便处理 块 各接手声明
　　　　 | 动词_试试 顺便处理 块 善后声明
　　　　 | 动词_试试 顺便处理 块 各接手声明 善后声明
　　　　 | 动词_试试 块 善后声明
　　　　 | 动词_试试 块 各接手声明
　　　　 | 动词_试试 块 各接手声明 善后声明

善后声明 : 动词_善后 块

各接手声明 : 各接手声明 接手声明
　　　　　 | 接手声明

接手声明 : 动词_接手 名称 冒号 表达式 块
　　　　 | 动词_接手 名称 块
　　　　 | 动词_接手 块

类型定义 : 名词_类型 名称 各基准类 类型主体

各基准类 : // 空
　　　　 | 冒号 表达式前缀    // TODO: 已测: 名称, 调用. 还有很多其他的不知是否允许.
　　　　 | 冒号 各表达式前缀  // TODO: 多项

类型主体 : 前大括号 各类型内声明 后大括号

各类型内声明 : // TODO: 空, 貌似 python 不允许, 报错: empty body on ClassDef
　　　　　　 | 各类型内声明 类型内声明

类型内声明 : 块
　　　　　 | 类型定义
　　　　　 | 操作符
　　　　　 | 函数  // $打头或者 self 为第一参数, 则为非静态方法
　　　　　 | 应变属性

应变属性 : 名词_应变属性 标识符 块
　　　　 | 名词_应变属性 标识符 前小括号 后小括号 块
　　　　 | 名词_应变属性 标识符 符号_赋值 前小括号 形参 后小括号 块

操作符 : 名词_操作符 二元操作符 操作数 块
　　　 | 名词_操作符 二元操作符 前小括号 形参 逗号 形参 后小括号 块  // 设置项时使用
　　　 | 名词_操作符 一元操作符 无操作数 块
　　　 | 名词_操作符 减 无操作数 块 

无操作数 : // 空
　　　　 | 前小括号 后小括号

操作数 : 形参
　　　 | 前小括号 形参 后小括号

二元操作符 : 前中括号 后中括号
　　　　　 | 位_左移
　　　　　 | 左移赋值
　　　　　 | 位_右移
　　　　　 | 右移赋值
　　　　　 | 加
　　　　　 | 增量赋值
　　　　　 | 减
　　　　　 | 减量赋值
　　　　　 | 星号
　　　　　 | 乘法赋值
　　　　　 | 除
　　　　　 | 除法赋值
　　　　　 | 求余
　　　　　 | 求余赋值
　　　　　 | 乘方
　　　　　 | 乘方赋值
　　　　　 | 大于
　　　　　 | 大于等于
　　　　　 | 小于
　　　　　 | 小于等于
　　　　　 | 等于
　　　　　 | 不等于

一元操作符 : 非
　　　　　 | 取反
　　　　　 | 井号

块 : 分号
　 | 前大括号 注水声明列表 后大括号

引用声明 : 动词_引用 各模块名 连词_于 模块位置
　　　　 | 动词_引用 星号 连词_于 模块位置
　　　　 | 动词_引用 各模块名

模块位置 : 模块名
　　　　 | 点点
　　　　 | 点

各模块名 : 模块名
　　　　 | 各模块名 逗号 模块名

模块名 : 模块名 点 名称
　　　 | 名称

表达式声明 : 表达式前缀
　　　　　 | 生成表达式

外部声明 : 形容词_外部 各名称

各表达式前缀 : 各表达式前缀 逗号 表达式前缀 // TODO
　　　　　　 | 表达式前缀 逗号 表达式前缀

赋值 : 表达式前缀 符号_赋值 表达式
　　 | 各表达式前缀 符号_赋值 各表达式

运算赋值 : 表达式前缀 增量赋值 表达式
　　　　 | 表达式前缀 减量赋值 表达式
　　　　 | 表达式前缀 乘法赋值 表达式
　　　　 | 表达式前缀 除法赋值 表达式
　　　　 | 表达式前缀 求余赋值 表达式
　　　　 | 表达式前缀 左移赋值 表达式
　　　　 | 表达式前缀 右移赋值 表达式
　　　　 | 表达式前缀 与赋值 表达式
　　　　 | 表达式前缀 或赋值 表达式
　　　　 | 表达式前缀 乘方赋值 表达式

类型赋值 : 名称 冒号 类型名称 符号_赋值 表达式

返回声明 : 动词_返回
　　　　 | 动词_返回 各表达式

终止声明 : 动词_终止

跳过声明 : 动词_跳过

表达式 : 多项式乘法
　　　 | 二元表达式
　　　 | 一元表达式
　　　 | 表达式前缀
　　　 | 首要表达式
　　　 | lambda表达式
　　　 | 三元表达式
　　　 | 数
　　　 | 常量
　　　 | 范围表达式
　　　 | 生成表达式
　　　 | 若干形参表达式

多项式乘法 : 数 表达式前缀
　　　　　 | 数 首要表达式

若干形参表达式 : 点点点

表达式前缀 : 变量
　　　　　 | 调用
　　　　　 | 匿名函数
　　　　　 | 字符串
　　　　　 | 列表表达式
　　　　　 | 字典表达式

片 : 表达式
　 | 表达式 冒号 表达式
　 | 表达式 冒号
　 | 冒号
　 | 冒号 表达式

数 : 十六进制数 
　 | 整数
　 | 小数

字符串 : 单引号字符串
　　　 | 双引号字符串

列表表达式 : 前中括号 后中括号
　　　　　 | 前中括号 各表达式 后中括号

字典表达式 : 前大括号 冒号 后大括号
　　　　　 | 前大括号 各键值对 后大括号

各键值对 : 键值对
　　　　 | 各键值对 逗号 键值对

键值对 : 表达式 冒号 表达式

常量 : 名词_真
　　 | 名词_假
　　 | 名词_空
　　 | 名词_自身

二元表达式 : 表达式 加 表达式
　　　　　 | 表达式 减 表达式
　　　　　 | 表达式 星号 表达式
　　　　　 | 表达式 除 表达式
　　　　　 | 表达式 位_左移 表达式
　　　　　 | 表达式 位_右移 表达式
　　　　　 | 表达式 位_与 表达式
　　　　　 | 表达式 位_或 表达式
　　　　　 | 表达式 求余 表达式
　　　　　 | 表达式 乘方 表达式
　　　　　 | 表达式 大于 表达式
　　　　　 | 表达式 小于 表达式
　　　　　 | 表达式 大于等于 表达式
　　　　　 | 表达式 小于等于 表达式
　　　　　 | 表达式 等于 表达式
　　　　　 | 表达式 不等于 表达式
　　　　　 | 表达式 严格等于 表达式
　　　　　 | 表达式 严格不等于 表达式
　　　　　 | 表达式 连词_且 表达式
　　　　　 | 表达式 连词_或 表达式

一元表达式 : 减 表达式
　　　　　 | 非 表达式
　　　　　 | 取反 表达式
　　　　　 | 井号 表达式

三元表达式 : 表达式 问号 表达式 冒号 表达式

首要表达式 : 前小括号 表达式 后小括号
　　　　　 | 前小括号 名称 冒号 类型名称 后小括号
　　　　　 | 前小括号 名称 冒号 类型名称 逗号 非空形参列表 后小括号
　　　　　 | 前小括号 名称 逗号 非空形参列表 后小括号

范围表达式 : 表达式 点点 表达式
　　　　　 | 表达式 点点小于 表达式
　　　　　 | 范围表达式 连词_每隔 表达式

生成表达式 : 动词_生成
　　　　　 | 动词_生成 表达式

调用 : 表达式前缀 实参部分
　　 | 超类
　　 | 表达式前缀 点 超类

超类 : 名词_超类
　　 | 名词_超类 实参部分

lambda表达式 : lambda形参 lambda主体

lambda形参 : 名称
      　　 | 若干形参表达式
      　　 | 首要表达式
      　　 | 前小括号 后小括号

lambda主体 : 箭头 表达式
      　　 | 箭头 块

匿名函数 : 名词_函数 前小括号 形参列表 后小括号 块
　　　　 | 名词_函数 块 // 待修: 不知如何使用，`lambda_无参.ul`报错
　　　　 | 名词_函数 前小括号 形参列表 后小括号 冒号 类型名称 块

类型名称 : 名称
　　　　 | 类型名称 前中括号 类型列表 后中括号
         
类型列表 : 类型名称
　　　　 | 类型列表 逗号 类型名称

实参部分 : 前小括号 各实参 后小括号
　　　　 | 前小括号 后小括号

各名称 : 名称
　　　 | 各名称 逗号 名称

各实参 : 实参
　　　 | 各实参 逗号 实参

各表达式 : 表达式
　　　　 | 各表达式 逗号 表达式

变量 : 表达式前缀 前中括号 片 后中括号
　　 | 表达式前缀 点 名称
　　 | 名称

名称 : 标识符

实参 : 表达式
　　 | 标识符 符号_赋值 表达式

形参列表 : // 空
　　　　 | 非空形参列表

非空形参列表 : 形参
　　　　　　 | 非空形参列表 逗号 形参
　　　　　　 | 点点点
　　　　　　 | 非空形参列表 逗号 点点点

形参 : 名称
　　 | 名称 符号_赋值 表达式
　　 | 名称 冒号 类型名称

函数 : 名词_函数 标识符 前小括号 形参列表 后小括号 块
　　 | 名词_函数 标识符 块
　　 | 名词_函数 标识符 前小括号 形参列表 后小括号 冒号 类型名称 块
　　 | 名词_函数 标识符 冒号 类型名称 块

条件声明 : 连词_如果 表达式 块 否则如果声明
　　　　 | 连词_如果 表达式 块 连词_否则 块
　　　　 | 声明 连词_如果 表达式

否则如果声明 : // 空
　　　　　　 | 连词_否则如果 表达式 块 否则如果声明
　　　　　　 | 连词_否则如果 表达式 块 连词_否则 块

每当声明 : 连词_每当 表达式 块
　　　　 | 动词_循环 块

迭代器 : 表达式前缀
　　　 | 各表达式前缀

遍历范围 : 表达式

对于声明 : 连词_对 迭代器 连词_于 遍历范围 块
　　　　 | 连词_对 迭代器 冒号 遍历范围 块
　　　　 | 声明 连词_对 迭代器 连词_于 遍历范围
　　　　 | 声明 连词_对 迭代器 冒号 遍历范围
```

## 内置函数

见 [环境.py](../木兰/环境.py) 末尾。

## 特性随笔

### 无条件循环

loop {} 等价于 while true {}，而未采用 do {} while 。感觉前者相对更容易使用。

### 字典包含某键

可用`字典.get(某键) != nil`判断。
注意不能用`字典.get(某键)`, 因为值为 0 时也会返回假。
检查 python 的`键值 in 字典`的对应 ast，为 ast.In，未看到木兰对应操作。
参考[ulgen](https://github.com/MulanRevive/mulan/blob/bc0ee27fc0dda93b5956999ec7f1aaf1061dd43a/ulang/codegen/ulgen.py#L456)，
用了 `__contains__` 。
