[Scala 基础]-- 词汇语法

英文原文: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字符替换。

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)。

身份标识

op       ::=  opchar {opchar}
varid    ::=  lower idrest
plainid  ::=  upper idrest
           |  varid
           |  op
id       ::=  plainid
           |  ‘`’ stringLiteral ‘`’
idrest   ::=  {letter | digit} [‘_’ op]

有三种方法可以形成标识符。首先,标识符可以以字母开头,后面可以是任意字母和数字序列。其后可以是下划线‘_‘ 字符和由字母和数字或运算符字符组成的另一个字符串。其次,标识符可以以操作符字符开头,后跟任意操作符字符序列。前两种形式称为普通标识符。最后,标识符也可以由后引号之间的任意字符串形成(主机系统可以对哪些字符串对于标识符合法施加一些限制)。然后,标识符由除反引号本身之外的所有字符组成。

像往常一样,适用最长匹配规则。例如,字符串

big_bob++=`def`

分解为三个标识符big_bob++=和 def。模式匹配的规则进一步区分 变量标识符常量标识符变量标识符以小写字母开头,而 常量标识符则不是。

' $ '字符保留用于编译器合成的标识符。用户程序不应定义包含' $ '字符的标识符。

以下名称是保留字,而不是id词法标识符的语法类的成员。

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

Unicode的运营商\u21D2“ ⇒⇒'和\u2190' ←←”,其中具有ASCII当量=><-,也是保留。

以下是标识符的示例:

扫描二维码关注公众号,回复: 4723558 查看本文章
    x         Object        maxIndex   p2p      empty_?
    +         `yield`       αρετη     _y       dot_product_*
    __system  _MAX_LEN_

当需要访问Scala中保留字的Java标识符时,请使用反引号括起的字符串。例如,该语句Thread.yield()是非法的,因为它yield是Scala中的保留字。但是,这是一个解决方法:Thread.`yield`()

换行符

semi ::= ‘;’ |  nl {nl}

Scala是一种面向行的语言,语句可以用分号或换行符终止。如果满足以下三个条件,则Scala源文本中的换行符将被视为特殊标记“nl”:

  1. 紧接在换行符之前的令牌可以终止语句。
  2. 紧接在换行符之后的令牌可以开始声明。
  3. 令牌显示在启用换行符的区域中。

可以终止语句的标记是:文字,标识符和以下分隔符和保留字:

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

可以开始声明的标记都是Scala标记, 以下分隔符和保留字除外

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

一个case令牌可以开始只有当后跟一个声明 classobject标记。

在以下位置启用换行符:

  1. 所有Scala源文件,除了禁用换行的嵌套区域,以及
  2. 匹配{}大括号标记之间的间隔,但禁用换行符的嵌套区域除外。

新线被禁用:

  1. 匹配()括号标记之间的间隔,除了启用换行的嵌套区域,和
  2. 匹配[]括号标记之间的间隔,但启用了换行符的嵌套区域除外。
  3. case令牌与其匹配 =>令牌之间的间隔,但启用了换行符的嵌套区域除外。
  4. XML模式下分析的任何区域。

请注意,{...}XML和字符串文字中转义的大括号字符不是标记,因此不会包含启用换行符的区域。

通常,nl即使两个令牌之间存在多条线,也只在一个位于不同线路上的两个连续非换行令牌之间插入一个令牌。但是,如果两个令牌被至少一个完全空行(即不包含可打印字符的行)分开,则nl插入两个令牌。

Scala语法(在这里完整给出)包含可选nl令牌但不接受分号的产品。这导致其中一个位置的换行不终止表达式或语句。这些职位可归纳如下:

在以下位置接受多个换行符令(请注意,在每种情况下,用分号代替换行符都是非法的):

接受单个新行令牌

  • 在开口括号'{'前面,如果该括号是当前陈述或表达的合法延续,
  • 在中缀运算符之后,如果下一行的第一个标记可以启动表达式,
  • 参数子句前面,和
  • 注释之后

两行之间的换行符不被视为语句分隔符。

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一样。

Literal  ::=  [‘-’] integerLiteral
           |  [‘-’] floatingPointLiteral
           |  booleanLiteral
           |  characterLiteral
           |  stringLiteral
           |  symbolLiteral
           |  ‘null’

整数文字

integerLiteral  ::=  (decimalNumeral | hexNumeral)
                       [‘L’ | ‘l’]
decimalNumeral  ::=  ‘0’ | nonZeroDigit {digit}
hexNumeral      ::=  ‘0’ (‘x’ | ‘X’) hexDigit {hexDigit}
digit           ::=  ‘0’ | nonZeroDigit
nonZeroDigit    ::=  ‘1’ | … | ‘9’

整数文字通常是类型Int,或者Long后跟一个L或 l后缀的类型 。类型的值Int都是-2之间的整数31- 231和231- 1231- 1, 包括的。类型的值Long都是-2之间的整数63- 263和 263- 1263- 1, 包括的。如果整数文字表示超出这些范围的数字,则会发生编译时错误。

然而,如果期望的类型PT在表达一个字面的或者是ByteShort,或Char 与整数在由类型所定义的数值范围配合,则数字被转换成键入PT和文字的类型是。这些类型给出的数值范围是:

   
Byte - 27- 27到27- 127- 1
Short - 215- 215到215- 1215- 1
Char 00到216- 1216- 1
0          21          0xFFFFFFFF       -42L

浮点文字

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

浮点文字是类型的Float,随后当由浮点类型后缀Ff,并且是类型的Double说明。该类型Float 包括所有IEEE 754 32位单精度二进制浮点值,而该类型Double包含所有IEEE 754 64位双精度二进制浮点值。

如果程序中的浮点字面值后跟一个以字母开头的标记,则两个标记之间必须至少有一个插入的空白字符。

0.0        1e30f      3.14159f      1.0e-100      .1

该短语1.toString分析为三个不同的标记:整数文字1,a .和标识符toString

1.不是有效的浮点文字,因为.缺少后的强制数字。

布尔文字

booleanLiteral  ::=  ‘true’ | ‘false’

布尔文字truefalse类型的成员Boolean

字符文字

characterLiteral  ::=  ‘'’ (printableChar | charEscapeSeq) ‘'’

字符文字是用引号括起来的单个字符。该字符是可打印的unicode字符或由转义序列描述。

'a'    '\u0041'    '\n'    '\t'

请注意,'\u000A'不是一个有效的字符文字,因为Unicode转换完成之前字面解析和Unicode字符\u000A(换行)不是一个可打印字符。可以使用转义序列'\n'或八进制转义'\12'参见此处)。

字符串文字

stringLiteral  ::=  ‘"’ {stringElement} ‘"’
stringElement  ::=  printableCharNoDoubleQuote  |  charEscapeSeq

字符串文字是双引号中的字符序列。字符是可打印的unicode字符或由转义序列描述 。如果字符串文字包含双引号字符,则必须对其进行转义,即"\""。字符串文字的值是类的实例String

"Hello,\nWorld!"
"This string contains a \" character."

多行字符串文字

stringLiteral   ::=  ‘"""’ multiLineChars ‘"""’
multiLineChars  ::=  {[‘"’] [‘"’] charNoDoubleQuote} {‘"’}

多行字符串文字是用三引号括起来的字符序列""" ... """。字符序列是任意的,除了它可能只在最后包含三个或更多连续引号字符。字符不一定是可打印的; 也允许换行或其他控制字符。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 统一 名称 烧焦
‘\‘ ‘b‘ \u0008 退格 BS
‘\‘ ‘t‘ \u0009 水平标签 HT
‘\‘ ‘n‘ \u000a 换行 LF
‘\‘ ‘f‘ \u000c 形式饲料 FF
‘\‘ ‘r‘ \u000d 回车 CR
‘\‘ ‘"‘ \u0022 双引号 "
‘\‘ ‘'‘ \u0027 单引号 '
‘\‘ ‘\‘ \u005c 反斜线 \

Unicode在0到255之间的字符也可以用八进制转义表示,即反斜杠'\'后跟最多三个八进制字符的序列。

如果字符或字符串文字中的反斜杠字符未启动有效的转义序列,则为编译时错误。

符号文字

symbolLiteral  ::=  ‘'’ plainid

符号文字'x是表达式的简写 scala.Symbol("x")Symbol是一个案例类,定义如下。

package scala
final case class Symbol private (name: String) {
  override def toString: String = "'" + name
}

伴随对象的apply方法Symbol缓存对Symbols的弱引用,从而确保相同的符号文字在引用相等方面是等价的。

空白和评论

标记可以用空格字符和/或注释分隔。评论有两种形式:

单行注释是一系列字符,以行开头 //并延伸到行尾。

多行注释是/*和之间的一系列字符 */。多行注释可以嵌套,但需要正确嵌套。因此,类似的评论 /* /* */将被拒绝为具有未终止的评论。

XML模式

为了允许文本包含XML片段,在下列情况下遇到开放尖括号“<”时,词法分析从Scala模式切换到XML模式:'<'必须在空格,左括号或开头之前大括号后面紧跟一个开始XML名称的字符。

 ( whitespace | ‘(’ | ‘{’ ) ‘<’ (XNameStart | ‘!’ | ‘?’)

  XNameStart ::= ‘_’ | BaseChar | Ideographic // as in W3C XML, but without ‘:’

如果有的话,扫描仪从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>

猜你喜欢

转载自blog.csdn.net/high2011/article/details/84953125
今日推荐