词法约定#
本页面规定 MoonBit 的词法形式。运行时表示、API 和字面量重载见基础。
MoonBit 源文本必须是格式正确的 UTF-8。格式错误的输入会报告词法错误。在每个位置,词法分析器都会取最长的有效词法单元。空白会被丢弃,而换行参与自动分号插入。
在产生式中,{ symbol } 表示重复零次或多次,{ symbol }+ 表示重复一次或多次,[ symbol ] 表示出现零次或一次,x...y 表示包含两端的范围。圆括号用于组合形式。except 子句从其左侧的完整形式中排除所列形式。
通用词法类#
unicode-scalar-value ::= U+0000U+D7FFU+E000U+10FFFF newline-character ::= LFCRU+2028U+2029 newline ::= newline-characterCRLF whitespace ::= U+0009U+000BU+000CU+0020U+00A0U+1680 U+2000U+200AU+202FU+205FU+3000U+FEFF line-character ::= unicode-scalar-valuenewline-character
字符串字面量#
string-literal ::= "string-character" string-character ::= regular-string-character simple-escape-sequence unicode-escape-sequence interpolation regular-string-character ::= unicode-scalar-value "\newline-character simple-escape-sequence ::= \\"'ntbrf/ unicode-escape-sequence ::= \u09AFaf09AFaf 09AFaf09AFaf \u{09AFaf}
简单转义序列的含义如下:
序列 |
字符 |
|---|---|
|
反斜杠(U+005C) |
|
双引号(U+0022) |
|
单引号(U+0027) |
|
正斜杠(U+002F) |
|
换行符(U+000A) |
|
回车符(U+000D) |
|
水平制表符(U+0009) |
|
退格符(U+0008) |
|
换页符(U+000C) |
Unicode 转义必须表示 Unicode 标量值。若在右引号之前遇到换行,则报告未终止的字符串字面量。
插值#
interpolation ::= \{whitespaceexpressionwhitespace}
表达式不能为空,且必须在与之匹配的 } 处结束。嵌套字面量中的大括号不影响匹配。嵌套插值会被递归识别。不允许出现换行、// 注释、属性和多行字符串字面量。
多行字符串字面量#
multiline-string-literal ::= multiline-string-line newlinemultiline-string-line multiline-string-line ::= raw-multiline-string-line interpolated-multiline-string-line raw-multiline-string-line ::= #|multiline-regular-character interpolated-multiline-string-line ::= $|multiline-regular-characterinterpolation multiline-regular-character ::= unicode-scalar-value newline-character
结果中省略各行前缀,并使用 U+000A 连接各行。最后一个带前缀的空行会添加末尾换行符。#| 行是原样文本。在 $| 行中,只有 \{ 会开始插值。插值表达式内不允许多行字符串。
字节序列字面量#
bytes-literal ::= b"bytes-character" bytes-character ::= regular-string-character simple-escape-sequence byte-escape-sequence interpolation byte-escape-sequence ::= \x09AFaf09AFaf \o030707
若在右引号之前遇到换行,则报告未终止的字面量。非 ASCII 源字符写入其 UTF-8 编码。\xHH 和 \oDDD 各写入一个取值为 0 到 255 的字节。插值遵循字符串字面量规则。字节序列字面量没有多行形式。
正则字面量#
regex-literal ::= re"regex-character" regex-character ::= regular-string-character \unicode-scalar-value{newline-character interpolation
反斜杠会原样保留给正则解析器,而 \{ 会开始插值。带插值的正则字面量仅在 lex-pattern 上下文中接受。若在右引号之前遇到换行,则报告未终止的字面量。参见正则字面量表达式。
字符字面量#
character-literal ::= 'regular-character' 'character-escape-sequence' regular-character ::= unicode-scalar-value '\newline-character character-escape-sequence ::= simple-escape-sequence unicode-escape-sequence
字符字面量恰好包含一个 Unicode 标量值或转义序列。
字节字面量#
byte-literal ::= b'regular-byte-character' b'byte-character-escape-sequence' regular-byte-character ::= U+0000U+007F '\newline-character byte-character-escape-sequence ::= simple-escape-sequence byte-escape-sequence
未转义的字节必须是 ASCII。字节字面量中不允许 Unicode 转义。
标识符#
non-ascii ::= U+00A1U+00AC U+00AEU+02AF U+1100U+11FF U+1E00U+1EFF U+2070U+209F U+2150U+218F U+2E80U+2EFF U+2FF0U+2FFF U+3001U+30FF U+31C0U+9FFF U+AC00U+D7FF U+F900U+FAFF U+FE00U+FE0F U+FE30U+FE4F U+1F000U+1FBFF U+20000U+2A6DF U+2A700U+2EBEF U+2F800U+2FA1F U+30000U+323AF U+E0100U+E01EF uident ::= AZAZaz09_non-ascii lident ::= _AZaz09_non-ascii aznon-asciiAZaz09_non-ascii underscore ::= _
以上字符范围按原样使用,不进行 Unicode 规范化。uident 以 ASCII 大写字母开头。其他标识符拼写以 ASCII 小写字母、_ 或 non-ascii 中的字符开头。单独的 _ 是专用词法单元。关键字也使用各自的专用词法单元。以 ASCII 十进制数字开头时会开始一个数字字面量。
关键字#
keyword ::= aselseexternfniflet constmatchusingmuttype structenumextenumtrait derivewhilebreakcontinueimportreturn throwraisetrycatchpubpriv proof_assertproof_letreadonlytruefalse testloopforinimplwith guardasyncissuberrorandletrec enumviewnoraisedeferlexscan wheredeclarenobreakextendtry!guard!
关键字优先于标识符。
以下拼写为保留字。尚未成为关键字的保留字会被词法分析为标识符或标签,并报告保留关键字警告。
reserved-word ::= modulemoverefstaticsuperunsafe useawaitdynabstractdofinal macrooverridetypeofvirtualyield localmethodaliasassertpackage recurisnotdefine downcastinheritmembernamespaceupcast voidlazyincludemixinprotected sealedconstructoratomicvolatile anyframeanytypeasmcomptimeerrdefer exportopaqueorelseresumethreadlocal unreachabledynclassdynobjdynrecvar finallynoasyncassume
标签#
label ::= _AZaz09_non-ascii~ aznon-asciiAZaz09_non-ascii~keyword~
~ 必须紧跟名称。以 ASCII 大写字母开头的标识符和关键字不能构成标签。
包名#
package-part ::= AZaz_AZaz09_- package-name ::= @package-part/package-part
包名仅限 ASCII。连字符不能位于包名部分的开头。前导 @、斜杠和各个部分必须彼此相邻。
属性#
attribute-name ::= AZaz_AZaz09_ attribute ::= #attribute-name.attribute-nameline-character
可选的点号限定名之后,到下一个换行为止的所有内容都是原始载荷。interpolation 中不允许使用属性。载荷文法见属性。
数字字面量#
integer-nums ::= 0909_ 0xX09AFaf09AFaf_ 0oO0707_ 0bB0101_ integer-literal ::= integer-numsULULN double-dec ::= 0909_.09_ eE+-0909_ double-hex ::= 0xX09AFaf 09AFaf_. 09AFaf_ pP+-0909_ double-literal ::= double-decdouble-hex float-dec ::= double-decF float-hex ::= 0xX09AFaf 09AFaf_. 09AFaf_ pP+-0909_F float-literal ::= float-decfloat-hex
数的第一个数字之后,下划线可以重复出现,也可以出现在末尾。大写后缀分别指定 UInt(U)、Int64(L)、UInt64(UL)、BigInt(N)或 Float(F)。不带后缀的浮点字面量为 Double。
浮点字面量始终包含小数点。十六进制 Float 必须在 F 前包含由 p 或 P 引导的指数部分,因此 0x1.F 是 Double。正负号是独立的词法单元。紧接 .. 时,整数词法单元先结束,因此 1..=2 以 1 和 ..= 开始。
1. 和 1.F 也分别是合法的 Double 和 Float 字面量。
点号前缀词法单元#
tuple-accessor ::= .09 dot-identifier ::= .AZaz_non-asciiAZaz09_non-ascii
这些形式中不能包含空白。元组访问器中不能有下划线。点号标识符遵循标识符的大小写规则,但不查询关键字表,因此 .if 合法。单独的 . 会报告词法错误。
运算符与分隔符#
delimiter ::= (),:::; []{}[||] operator ::= =>-> &&&^ */% <<>> =><|<?<+< ==!==~<=>= |||+-?! +=-=*=/=%=|> ....=..<..<=>..>=.....
列出的词法单元中,最长者优先。
自动分号插入#
换行后,如果前一个词法单元可以结束语句,且后一个词法单元可以开始语句,词法分析器可能会插入 ;。文件末尾也可作为有效的后继。词法分析器不会在 } 前插入分号,也不会在多行字符串的相邻行之间插入分号。
.mbti 扩展#
.mbti 的词法文法在 .mbt 的基础上增加以下关键字:
mbti-keyword ::= keywordpackage
在 .mbti 中,package 的匹配优先级高于标识符,且不能构成标签。在 .mbt 中,它遵循上文所述的保留字规则,并可构成 package~。
注释#
当两者都能匹配时,
doc-comment优先于line-comment。MoonBit 不支持块注释。