英文原文:https://www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html#integer-literals
词法语法
Scala程序使用Unicode Basic Multilingual Plane(BMP)字符集编写; 目前不支持Unicode补充字符。本章定义了Scala的词法语法的两种模式,即Scala模式和XML模式。如果没有另外提及,Scala令牌的以下描述引用Scala模式,文字字符'c'引用ASCII片段 \u0000
- \u007F
。
在Scala模式下,Unicode转义符由具有给定十六进制代码的相应Unicode字符替换。
要构造标记,根据以下类别区分字符(括号中给出的Unicode常规类别):
- 空白字符。
\u0020 | \u0009 | \u000D | \u000A
。 - 信,包括小写字母(
Ll
),大写字母(Lu
),首字母大写字母(Lt
),其他字母(Lo
),字母数字(Nl
)和两个字符\u0024 ‘$’
和\u005F ‘_’
,这既算作大写字母。 - 数字
‘0’ | … | ‘9’
。 - 括号
‘(’ | ‘)’ | ‘[’ | ‘]’ | ‘{’ | ‘}’
。 - 分隔符字符
‘`’ | ‘'’ | ‘"’ | ‘.’ | ‘;’ | ‘,’
。 - 操作员角色。它们由所有可打印的ASCII字符组成
\u0020
- \u007F
它们不在上面的集合中,数学符号(Sm
)和其他符号(So
)。
身份标识
有三种方法可以形成标识符。首先,标识符可以以字母开头,后面可以是任意字母和数字序列。其后可以是下划线‘_‘
字符和由字母和数字或运算符字符组成的另一个字符串。其次,标识符可以以操作符字符开头,后跟任意操作符字符序列。前两种形式称为普通标识符。最后,标识符也可以由后引号之间的任意字符串形成(主机系统可以对哪些字符串对于标识符合法施加一些限制)。然后,标识符由除反引号本身之外的所有字符组成。
像往常一样,适用最长匹配规则。例如,字符串
分解为三个标识符big_bob
,++=
和 def
。模式匹配的规则进一步区分 变量标识符和常量标识符,变量标识符以小写字母开头,而 常量标识符则不是。
' $ '字符保留用于编译器合成的标识符。用户程序不应定义包含' $ '字符的标识符。
以下名称是保留字,而不是id
词法标识符的语法类的成员。
Unicode的运营商\u21D2
“ ⇒⇒'和\u2190
' ←←”,其中具有ASCII当量=>
和<-
,也是保留。
以下是标识符的示例:
x Object maxIndex p2p empty_? + `yield` αρετη _y dot_product_* __system _MAX_LEN_
当需要访问Scala中保留字的Java标识符时,请使用反引号括起的字符串。例如,该语句
Thread.yield()
是非法的,因为它yield
是Scala中的保留字。但是,这是一个解决方法:Thread.`yield`()
换行符
Scala是一种面向行的语言,语句可以用分号或换行符终止。如果满足以下三个条件,则Scala源文本中的换行符将被视为特殊标记“nl”:
- 紧接在换行符之前的令牌可以终止语句。
- 紧接在换行符之后的令牌可以开始声明。
- 令牌显示在启用换行符的区域中。
可以终止语句的标记是:文字,标识符和以下分隔符和保留字:
可以开始声明的标记都是Scala标记,但 以下分隔符和保留字除外:
一个case
令牌可以开始只有当后跟一个声明 class
或object
标记。
在以下位置启用换行符:
- 所有Scala源文件,除了禁用换行的嵌套区域,以及
- 匹配
{
和}
大括号标记之间的间隔,但禁用换行符的嵌套区域除外。
新线被禁用:
- 匹配
(
和)
括号标记之间的间隔,除了启用换行的嵌套区域,和 - 匹配
[
和]
括号标记之间的间隔,但启用了换行符的嵌套区域除外。 -
case
令牌与其匹配 =>
令牌之间的间隔,但启用了换行符的嵌套区域除外。 - 在XML模式下分析的任何区域。
请注意,{...}
XML和字符串文字中转义的大括号字符不是标记,因此不会包含启用换行符的区域。
通常,nl
即使两个令牌之间存在多条线,也只在一个位于不同线路上的两个连续非换行令牌之间插入一个令牌。但是,如果两个令牌被至少一个完全空行(即不包含可打印字符的行)分开,则nl
插入两个令牌。
Scala语法(在这里完整给出)包含可选nl
令牌但不接受分号的产品。这导致其中一个位置的换行不终止表达式或语句。这些职位可归纳如下:
在以下位置接受多个换行符令(请注意,在每种情况下,用分号代替换行符都是非法的):
- 在条件表达式 或while循环的 条件与下一个表达式之间,
- 在for-comprehension的枚举数 和下一个表达式之间,和
- 在类型定义或声明中的初始
type
关键字 之后。
接受单个新行令牌
两行之间的换行符不被视为语句分隔符。
if (x > 0) x = x - 1 while (x > 0) x = x / 2 for (x <- 1 to 10) println(x) type IntList = List[Int]
new Iterator[Int] { private var x = 0 def hasNext = true def next = { x += 1; x } }
使用其他换行符时,相同的代码将被解释为对象创建,后跟本地块:
new Iterator[Int] { private var x = 0 def hasNext = true def next = { x += 1; x } }
x < 0 || x > 10
使用额外的换行符,相同的代码将被解释为两个表达式:
x < 0 || x > 10
def func(x: Int) (y: Int) = x + y
使用额外的换行符,相同的代码被解释为抽象函数定义和语法上的非法语句:
def func(x: Int) (y: Int) = x + y
@serializable protected class Data { ... }
使用额外的换行符时,相同的代码将被解释为属性和单独的语句(在语法上是非法的)。
@serializable protected class Data { ... }
字面
有整数,浮点数,字符,布尔值,符号,字符串的文字。这些文字的语法在每种情况下都与Java一样。
整数文字
整数文字通常是类型Int
,或者Long
后跟一个L
或 l
后缀的类型 。类型的值Int
都是-2之间的整数31- 231和231- 1231- 1, 包括的。类型的值Long
都是-2之间的整数63- 263和 263- 1263- 1, 包括的。如果整数文字表示超出这些范围的数字,则会发生编译时错误。
然而,如果期望的类型PT在表达一个字面的或者是Byte
,Short
,或Char
与整数在由类型所定义的数值范围配合,则数字被转换成键入PT和文字的类型是角。这些类型给出的数值范围是:
| |
| - 27- 27到27- 127- 1 |
| - 215- 215到215- 1215- 1 |
| 00到216- 1216- 1 |
0 21 0xFFFFFFFF -42L
浮点文字
浮点文字是类型的Float
,随后当由浮点类型后缀F
或f
,并且是类型的Double
说明。该类型Float
包括所有IEEE 754 32位单精度二进制浮点值,而该类型Double
包含所有IEEE 754 64位双精度二进制浮点值。
如果程序中的浮点字面值后跟一个以字母开头的标记,则两个标记之间必须至少有一个插入的空白字符。
0.0 1e30f 3.14159f 1.0e-100 .1
该短语
1.toString
分析为三个不同的标记:整数文字1
,a .
和标识符toString
。
1.
不是有效的浮点文字,因为.
缺少后的强制数字。
布尔文字
布尔文字true
和false
类型的成员Boolean
。
字符文字
字符文字是用引号括起来的单个字符。该字符是可打印的unicode字符或由转义序列描述。
'a' '\u0041' '\n' '\t'
请注意,'\u000A'
是不是一个有效的字符文字,因为Unicode转换完成之前字面解析和Unicode字符\u000A
(换行)不是一个可打印字符。可以使用转义序列'\n'
或八进制转义'\12'
(参见此处)。
字符串文字
字符串文字是双引号中的字符序列。字符是可打印的unicode字符或由转义序列描述 。如果字符串文字包含双引号字符,则必须对其进行转义,即"\""
。字符串文字的值是类的实例String
。
"Hello,\nWorld!" "This string contains a \" character."
多行字符串文字
多行字符串文字是用三引号括起来的字符序列""" ... """
。字符序列是任意的,除了它可能只在最后包含三个或更多连续引号字符。字符不一定是可打印的; 也允许换行或其他控制字符。Unicode转义符可以像其他地方一样工作,但这里没有解释转义序列。
"""the present string spans three lines."""
这会产生字符串:
the present string spans three lines.
Scala库包含一个实用程序方法
stripMargin
,可用于从多行字符串中去除前导空格。表达方式"""the present string |spans three |lines.""".stripMargin
评估为
the present string spans three lines.
方法
stripMargin
在类scala.collection.immutable.StringLike中定义 。因为有一个预定义的 隐式转换从String
到 StringLike
,该方法适用于所有的字符串。
转义序列
在字符和字符串文字中可识别以下转义序列。
charEscapeSeq | 统一 | 名称 | 烧焦 |
| | 退格 | |
| | 水平标签 | |
| | 换行 | |
| | 形式饲料 | |
| | 回车 | |
| | 双引号 | |
| | 单引号 | |
| | 反斜线 | |
Unicode在0到255之间的字符也可以用八进制转义表示,即反斜杠'\'
后跟最多三个八进制字符的序列。
如果字符或字符串文字中的反斜杠字符未启动有效的转义序列,则为编译时错误。
符号文字
符号文字'x
是表达式的简写 scala.Symbol("x")
。Symbol
是一个案例类,定义如下。
伴随对象的apply
方法Symbol
缓存对Symbol
s的弱引用,从而确保相同的符号文字在引用相等方面是等价的。
空白和评论
标记可以用空格字符和/或注释分隔。评论有两种形式:
单行注释是一系列字符,以行开头 //
并延伸到行尾。
多行注释是/*
和之间的一系列字符 */
。多行注释可以嵌套,但需要正确嵌套。因此,类似的评论 /* /* */
将被拒绝为具有未终止的评论。
XML模式
为了允许文本包含XML片段,在下列情况下遇到开放尖括号“<”时,词法分析从Scala模式切换到XML模式:'<'必须在空格,左括号或开头之前大括号后面紧跟一个开始XML名称的字符。
如果有的话,扫描仪从XML模式切换到Scala模式
- 由初始“<”启动的XML表达式或XML模式已成功解析,或者是否已成功解析
- 解析器遇到嵌入的Scala表达式或模式,并强制扫描程序返回正常模式,直到成功解析Scala表达式或模式。在这种情况下,由于代码和XML片段可以嵌套,因此解析器必须维护一个堆栈,以充分反映XML和Scala表达式的嵌套。
请注意,没有Scala令牌在XML模式下构造,并且注释被解释为文本。
以下值定义使用带有两个嵌入式Scala表达式的XML文本:
val b = <book> <title>The Scala Language Specification</title> <version>{scalaBook.version}</version> <authors>{scalaBook.authors.mkList("", ", ", "")}</authors> </book>