Scala语法详解之基本词法_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4011 | 回复: 0   主题: Scala语法详解之基本词法        下一篇 
wei.wang
注册用户
等级:少校
经验:1001
发帖:87
精华:0
注册:2013-8-29
状态:离线
发送短消息息给wei.wang 加好友    发送短消息息给wei.wang 发消息
发表于: IP:您无权察看 2013-9-5 14:56:48 | [全部帖] [楼主帖] 楼主

1. 词法

     Scala 程 序 使 用的 字 符集 是 Unicode 的基 本多 文 种 平 面字 符 集 ;目前 不 支 持

Unicode 中增补的字符。本章定义了 Scala 词法的两种模式:Scala 模式与 XML 模式。

如果没有特别说明,以下对 Scala 符号的描述均指 Scala 模式,常量字符„c‟指 ASCII

段\u0000-\u007F。

     在 Scala 模式中,十六进制 Unicode 转义字符会被对应的 Unicode 字符替换。

UnicodeEscape ::= \{\\}u{u} hexDigit hexDigit hexDigit hexDigit
hexDigit
::= „0‟|...|„9‟|„A‟|...|„F‟|...|„a‟|...|„f‟|


符号由下面几类字符构成(括号中是 Unicode 通用类别):

1. 空白字符。\u0020|\u0009| \u000D|\u000A

2. 字母,包括小写 (Ll),大写 (Lu),词首字母大写 (Lt),其他 (Lo),数字

     (Nl),以及\u0024 ‟$‟ 和 \u005F „_‟,这两个字母归类为大写字母

3. 数字 „0‟|...|„9‟

4. 括号 „(‟ | „)‟ | „[‟ | „]‟ | „{‟ | „}‟。

5. 分隔符 „„‟ | „‟‟ | „”‟ | „.‟ | „;‟ | „,‟。

6. 算符字符。由所有的没有包括在以上分类中的可打印 ASCII 字符\u0020-

     \u007F,数学符号(Sm)以及其他符号(So)构成

1.1.

语法:

op


标识符

::= opchar {opchar}
::= lower idrest
::= upper idrest
| varid
| op
varid
plainid
id
idrest
::= plainid
| „\‟‟ stringLit „\‟‟
::= {letter | digit}[„_‟ op]


有三种方法可以构造一个标识符。第一,首字符是字母,后续字符是任意字母和数字。

这种标识符还可后接下划线‟_‟,然后是任意字母和数字。第二,首字符是算符字符,后

续字符是任意算符字符。这两种形式是普通标识符。最后,标识符可以是由反引号‟`‟括

起来的任意字符串(宿主系统可能会对字符串和合法性有些限制)。这种标识符可以由除了

反引号的任意字符构成。

1

换行字符

按惯例,标识符符合最长匹配原则。例如:

Big_bob++=‟def‟


可以分解为三个标识符 big_bob,++=,和 def。变量标识符(varid,小写字母开头)

和常量标识符(没有小写字母开头的限制)的模式匹配规则有所不同。

以下命名是保留字,不能用作词法标识符的语法类 id。

abstract
do
finally
import
object
requires
throw
val
_
:
=
case
else
for
lazy
override
return
trait
var
=>
<-
<:
catch
extends
forSome
match
package
sealed
try
while
<%
>:
#
class
false
if
new
private
super
true
with
@
def
final
implicit
null
protected
this
type
yield


Unicode 算符\u21D2 „⇒‟ 和 \u2190 „←‟以及它们的 ASCII 对应‟=>‟也是保

留字

示例 1.1.1 以下是一些标识符的示例

x
+
__system
Object
_MAX_LEN_
maxIndex
_y
p2p
empty_?
dot_product_*
`yield` αρετη


示例 1.1.2 反引号括起来的字符串是那些 Scala 中是保留字的 Java 中标识符的一

个方法。例如,在 Scala 中 Thread.yield()是非法的,因为 yield 是保留字。但

是可以这样调用:

Thread.`yield`()
1.2.


语法:

换行字符

::= „;‟ | nl{nl}
semi


Scala 是一个基于行的语言。分号和换行均可作为语句的结束。如果换行满足以下三

个条件则会被认为是一个特殊符号‟nl‟:

     1. 换行之前的符号是一个语句的结束

     2. 换行之后的符号是一个语句的开始

     3. 符号处在一个允许多语句的区域中

可以作为语句结束的符号是:常量,标识符,保留字以及以下的分隔符:

this
-
null
)
true
]
false
}
return
type
<xml-start>
2


可以作为语句开始的符号是除了以下分隔符及保留字之外的所有 Scala 符号:

catch
with
]
}
else
yield
extends finally forSome match
,
.
;
:
_
=
=>
<-
requires
<:
<%
>:
#
[
)


符号 case 只有在 class 或者 object 符号之前才可以作为语句开始。

     多行语句许可的条件:

     1. 整个 Scala 源文件中,除了换行被禁止的嵌套区域

     2. 在匹配的{与}之间,除了换行被禁止的嵌套区域

     多行语句在以下区域被禁止:

     1. 在匹配的(与)之间,除了换行被允许的嵌套区域。

     2. 在匹配的[与]之间,除了换行被允许的嵌套区域。

     3. 在 case 符号以及与其匹配的=>符号之间,除了换行被允许的嵌套区域。

     4. XML 模式下的区域(§1.5)。

     注意在 XML 中大括号{..}被转义,字符串并不是符号。因此当换行被允许时不要关

闭区域。

     一般地,即使连续的两个非换行符号中有多行,也只会插入一个 nl 符号。然而,如

果两个符号被至少一个空行(行中没有可打印字符)分隔开,那么两个符号中就会插入两个

nl 符号。

     Scala 语法(全文见附录 A)允许可选的 nl 符号,但分号不在此列。这样在某些位置

换行并不会结束一个表达式或语句。这些位置如下所列:

     以下位置允许多个换行符号(换了分号是不行地):

     - 在条件表达式(§6.16) 或 while 循环(§6.17)的条件及下一个表达式间

     - For 循环(§6.19)中计数器及下一个表达式间

     - 类型定义或声明中,在开始的 type 关键字之后

     以下位置允许单个换行:

     - 在一个是当前语句或表达式的合法继续的大括号”{”前

     - 如果下行的第一个符号是一个表达式的开始(§6.12),本行的中缀算符之后

     - 在一个参数子句前(§4.6)

     - 在一个标注(§11)之后

示例 1.2.1 以下是跨两行的四个合法语句。两行间的换行符号并未作为语句结束。

if(x > 0)
x=x–1
while(x > 0)
x=x/2
for(x <- 1 to 10)
println(x)
type
IntList = List[Int]
3


示例 1.2.2 以下代码定义了一个匿名类

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 }
}


示例 1.2.3 以下代码定义了一个表达式:

x < 0 ||
x > 10


加一个换行后就成了两个表达式:

x < 0 ||
x > 10


示例 1.2.4 以下代码定义了一个单一的柯里化的函数:

def func(x: Int)
(y: Int) = x + y


加一个换行后,同样的代码就成了一个抽象函数和一个非法语句

def func(x: Int)
(y: Int) = x + y


示例 1.2.5 以下代码是一个加了标注的定义:

@serializable
protected class Data{...}


加一个换行后,同样的代码就成了一个属性标记和一个单独的语句(实际上是非法的)

@serializable
protected class Data{...}
4
1.3.


字面值

     字面值包括整数,浮点数,字符,布尔值,记号,字符串。这些字面值的语法均和

Java 中的字面值一致。

语法:

Literal ::= [„-„] integerLiteral
| [„-„] floatingPointLiteral
| booleanLiteral
| characterLiteral
| stringLiteral
| symbolLiteral
| „null‟


1.3.1. 整型字面值

语法:

integerLiteral ::= (decimalNumeral | hexNumeral | octalNumeral)[„L‟|„l‟]
decimalNumeral ::= „0‟ | nonZeroDigit {digit}
hexNumeral
octalNumeral
digit
nonZeroDigit
octalDigit
::= „0‟„x‟ hexDigit {hexDigit}
::= „0‟ octalDigit {octalDigit}
::= „0‟ | nonZeroDigit
::= „1‟ | ... | „9‟
::= „0‟ | ... | „7‟


   整型字面值通常表示 Int 型,或者后面加上 L 或 l 表示 Long 型。Int 的值的范围是

-2 到 231-1 间的整数,包含边界值。Long 的值的范围是-263 到 263-1 间的整数,包含

边界值。整型字面值的值超出以上范围就会导致编译错误。

     如果一个字面值在表达式中期望的类型 pt(§6.1)是 Byte, Short 或者 Char 中的

一个,并且整数的值符合该类型的值的范围,那么这个数值就会被转为 pt 类型,这个字

面值的类型也是 pt。数值范围如下所示:

31
Byte
Short
Char


-27 到 27-1

-215 到 215-1

0 到 216-1

示例 1.3.1 以下是一些整型字面值:

0
21
0xFFFFFFFF 0777L


1.3.2. 浮点型字面值

语法:

floatingPointLiteral
::= digit { digit } „.‟ { digit } [ exponentPart ]
[ floatType ]
| „.‟ digit { digit } exponentPart [ floatType ]
|digit{digit}exponentPart [ floatType]
5
| digit { digit } [ exponentPart ] floatType
exponentPart
floatType
::= („E‟ | „e‟)[„+‟ | „-‟]digit{digit}
::= „F‟ | „f‟ | „D‟ | „d‟


   如果浮点数字面值的后缀是 F 或者 f,那么这个字面值的类型是 Float,否则就是

Double。Float 类型包括所有 IEEE 754 32 位单精度二进制浮点数值,Double 类型

包括所有 IEEE 754 64 位双精度二进制浮点数值。

     如果程序中浮点数字面值后面跟一个字母开头的符号,那么这两者之间应当至少有一

个空白字符。

示例 1.3.2 以下是一些浮点型字面值:

0.0

1e30f
3.14159f
1.0e-100
.1


示例 1.3.3 短语„1.toString‟将被解析为三个符号:„1‟, „.‟和„toString‟。但是

如果在句点后插入一个空格,短语„1. toString‟就会被解析为一个浮点数„1.‟和一个

标识符„toString‟。

1.3.3. 布尔型字面值

语法:

booleanLiteral ::= „true‟ | „false‟


布尔型字面值 true 和 false 是 Boolean 类型的成员

1.3.4. 字符型字面值

语法:

characterLiteral
::= „\‟‟ printableChar „\‟‟
| „\‟‟ charEscapeSeq „\‟‟


字符型字面值就是单引号括起来的单个字符。字符可以是可打印 unicode 字符或者

由一个转义序列(§1.3.6)描述的 unicode 字符。

示例 1.3.4 以下是一些字符型字面值:

„a‟
„\u0041‟
„\n‟
„\t‟


注意„\u000A‟不是一个合法的字符常数,因为在处理字面值前已经完成了 Unicode

转换,而 Unicode 字符\u000A(换行)不是一个可打印字符。可以使用转义序列„\n‟或

八进制转义„\12‟来表示一个换行字符(§1.3.6)。

1.3.5. 字符串字面值

语法:

stringLiteral
stringElement
::= „\”‟ {stringElement} „\”‟
::= printableCharNoDoubleQuote | charEscapeSeq
6


字符串字面值是由双引号括起来的字符序列。字符必须是可打印 unicode 字符或者

转义序列(§1.3.6)。如果一个字符串字面值包括双引号,那么这个双引号必须用转义字

符,比如:\”。字符串字面值的值是类 String 的一个实例。

示例 1.3.5 以下是一些字符串字面值

“Hello,\nWorld!”
“This string contains a \” character.”


多行字符串字面值

语法:

stringLiteral
::= „”””‟ multiLineChars ‟”””‟
multiLineChars ::= {[„”‟][„”‟] charNoDoubleQuote}


多行字符串字面值是由三个双引号括起来的字符序列”””...”””。字符序列是除了三

个双引号之外的任意字符序列。字符不一定必须是可打印的;换行或者其他控制字符也是

可以的。Unicode 转义序列也可以,不过在(§1.3.6)中定义的转义序列不会被解析。

示例 1.3.6 以下是一个多行字符串字面值:

”””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.runtime.RichString。由于有预定义的从

String 到 RichString 的隐式转换,因此这个方法可以应用到所有的字符串。

1.3.6. 转义序列

在字符串或字符字面值中可以有以下转义序列:

\b
\t


\u0008:退格 BS

\u0090:水平制表符 HT

7
\n
\f
\r
\”
\‟
\\


\u000a:换行 LF

\u000c: 格式进纸 FF

\u000d:回车 CR

\u0022:双引号 ”

\u0027:单引号 ‟

\u005c:反斜线 \

0 到 255 间的 Unicode 字符可以用一个八进制转义序列来表示,即反斜线‟\‟后跟

最多三个八进制。

在字符或字符串中,反斜线和后面的字符序列不能构成一个合法的转义序列将会导致

编译错误。

1.3.7. 记号字面值

语法:

symbolLiteral
::= „‟‟ idrest


  记号字面值‟x 是表达式 scala.Symbol(“x”)的简写形式。Symbol 是一个 case

类(§5.3.2),定义如下:

package scala
final case class Symbol private (name: String) {
      override def toString: String = “‟” + name
}


Symbol 的伴随实例的 apply 方法中缓存了一个到 Symbol 的弱引用,因此同样的记

号字面值是引用相等的。

1.4.

空白与注释

符号可由空白字符或注释分隔开。注释有两种格式:

单行注释是由//开始直到行尾的字符序列

多行注释是在/*和*/之间的字符序列。多行注释可以嵌套,但是必须合理的嵌套。因

此像/* /* */这样的注释是非法的,因为有一个没有结束的注释。

1.5.

XML 模式

     为了允许包含 XML 片段字面值。当遇到左尖括号‟<‟时,在以下情况下词法分析就会

从 Scala 模式切换到 XML 模式:‟<‟前必须是空白,左括号或者左大括号,‟<‟后必须跟

一个 XML 命名。

语法:

(whitespace | „(‟ | „{‟ } „<‟ (XNameStart | „!‟ | „?‟)
XNameStart ::= „_‟ | BaseChar | Ideographic (和 W3C XML 一样, 但没有„:‟)


扫描器遇到以下条件之一时将会从 XML 模式切换到 Scala 模式:

8

     由‟<‟开始的 XML 表达式或模式已被成功解析。

     解析器遇到一个内嵌的 Scala 表达式或模式强制扫描器返回正常模式,直到

     Scala 表达式或模式被成功解析。在这种情况下,由于代码和 XML 片段可以嵌套,

     解析器将会用一个堆栈来储存嵌套的 XML 和 Scala 表达式。

注意在 XML 模式中不会生成 Scala 的符号,注释会解析为文本。

示例 1.5.1 以下定义了一个值,包括一个 XML 字面值,内嵌了两个 Scala 表达式

val b = <book>
<title>The Scala Language Specification</title>
<version>{scalaBook.version}</version>
<authors>{scalaBook.authors.mkList(””,”, “, ””)}</authors>
</book>
l
l
9




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论