Tải bản đầy đủ (.docx) (11 trang)

Các chương trình Scala Cú pháp lexical

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (215.43 KB, 11 trang )

Cú pháp Lexical
















1 Cú pháp Lexical
1 số nhận dạng
2 ký tự dòng mới
3 Literals
1 Integer Literals
2 dấu chấm động
3 Boolean Literals
4 ký tự chữ
5 chuỗi văn học
6 chuỗi thoát
7 Ký hiệu chữ
4 khoảng trắng và nhận xét
5 Trailing dấu phẩy trong biểu thức nhiều dòng
6 Chế độ XML






1 Cú pháp Lexical
Các chương trình Scala được viết bằng bộ ký tự Unicode Basic
Multilingual Plane ( BMP ); Các ký tự bổ sung Unicode hiện không
được hỗ trợ. Chương này định nghĩa hai chế độ cú pháp từ vựng của
Scala, chế độ Scala và chế độ XML . Nếu không được đề cập khác, các
mô tả sau đây của mã thông báo Scala tham chiếu đến chế độ
Scala và các ký tự chữ 'c' tham chiếu đến đoạn mã ASCII \u0000- \u007F.
Trong chế độ Scala, Unicode thoát được thay thế bằng ký tự Unicode
tương ứng với mã thập lục phân đã cho.
UnicodeEscape ::= ‘\’ ‘u’ {‘u’} hexDigit hexDigit hexDigit hexDigit
hexDigit
::= ‘0’ | … | ‘9’ | ‘A’ | … | ‘F’ | ‘a’ | … | ‘f’

Để tạo mã thông báo, các ký tự được phân biệt theo các lớp sau (danh
mục chung Unicode được đưa ra trong dấu ngoặc đơn):
1.
2.
3.
4.
5.
6.

Ký tự khoảng trắng. \u0020 | \u0009 | \u000D | \u000A.
Chữ cái, bao gồm chữ cái viết thường ( Ll), chữ cái viết hoa ( Lu),
chữ cái titlecase ( Lt), các chữ cái khác ( Lo), chữ số ( Nl) và hai ký
tự \u0024 ‘$’và \u005F ‘_’.

Chữ số ‘0’ | … | ‘9’.
Dấu ngoặc đơn ‘(’ | ‘)’ | ‘[’ | ‘]’ | ‘{’ | ‘}’.
Ký tự dấu tách ‘`’ | ‘'’ | ‘"’ | ‘.’ | ‘;’ | ‘,’.
Nhân vật điều hành. Chúng bao gồm tất cả các ký tự ASCII có thể
in ( \u0020- \u007E) không nằm trong các tập hợp ở trên, ký hiệu toán
học ( Sm) và các ký hiệu khác ( So).
Số nhận dạng
op
::= opchar {opchar}
varid ::= lower idrest
boundvarid ::= varid
| ‘`’ varid ‘`’
plainid ::= upper idrest
| varid
| op
id
::= plainid
| ‘`’ { charNoBackQuoteOrNewline | UnicodeEscape | charEscapeSeq } ‘`’
idrest ::= {letter | digit} [‘_’ op]

Có ba cách để tạo thành một định danh. Đầu tiên, một định danh có
thể bắt đầu bằng một chữ cái có thể được theo sau bởi một chuỗi các
chữ cái và chữ số tùy ý. Điều này có thể được theo sau bởi các ‘_‘ ký


tự gạch dưới và một chuỗi khác bao gồm các chữ cái và chữ số hoặc
các ký tự của toán tử. Thứ hai, một định danh có thể bắt đầu bằng một
ký tự toán tử, theo sau là một chuỗi ký tự toán tử tùy ý. Hai dạng trước
được gọi là các định danh đơn giản . Cuối cùng, một định danh cũng
có thể được tạo thành bởi một chuỗi tùy ý giữa các dấu ngoặc kép (các

hệ thống máy chủ có thể áp đặt một số hạn chế về các chuỗi nào là hợp
pháp đối với các mã định danh). Mã định danh sau đó bao gồm tất cả
các ký tự không bao gồm các phần tử backquotes.
Như thường lệ, quy tắc kết hợp dài nhất sẽ được áp dụng. Ví dụ, chuỗi
big_bob++=`def`

phân hủy thành ba định danh big_bob, ++=và def.
Các quy tắc để đối sánh mẫu phân biệt hơn nữa giữa các số nhận dạng
biến , bắt đầu bằng chữ cái viết thường và các số nhận dạng không
đổi. Với mục đích này, dấu gạch dưới được lấy dưới dạng chữ thường và
ký tự '\ $' được lấy làm chữ hoa.‘_‘được lấy làm trường hợp thấp hơn và
'$
Ký tự ' $ ' được dành riêng cho trình nhận dạng tổng hợp trình biên
dịch. Chương trình người dùng không nên xác định số nhận dạng chứa
' $Ký tự '\ $' được dành riêng cho trình nhận dạng tổng hợp trình biên
dịch. Chương trình người dùng không nên xác định số nhận dạng chứa
ký tự '\ $'.
Các tên sau đây là các từ dành riêng thay vì là thành viên của lớp cú
pháp idcủa các từ định danh từ vựng.
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
_ : = => <- <: <%
>: # @
Các toán tử Unicode \u21D2'$ \ Rightarrow


$' và '$ \ leftarrow $', có

tương đương ASCII và cũng được bảo lưu.⇒⇒\u2190←←=>x
Object
maxIndex p2p
empty_?
+
`yield`
αρετη
_y
dot_product_*
__system _MAX_LEN_

Khi người ta cần truy cập các mã định danh Java là các từ dành riêng
trong Scala, hãy sử dụng các chuỗi kèm theo backquote. Ví dụ, tuyên
bố Thread.yield()là bất hợp pháp, vì yieldlà một từ dành riêng trong
Scala. Tuy nhiên, đây là một công việc xung quanh:Thread.`yield`()


Ký tự dòng mới
semi ::= ‘;’ | nl {nl}

Scala là một ngôn ngữ hướng dòng, trong đó các câu lệnh có thể được
chấm dứt bằng dấu chấm phẩy hoặc dòng mới. Một dòng mới trong
văn bản nguồn Scala được coi là mã thông báo đặc biệt “nl” nếu đáp
ứng ba tiêu chí sau đây:
1.

Mã thông báo ngay trước dòng mới có thể chấm dứt một câu

lệnh.

2.
3.

Mã thông báo ngay sau dòng mới có thể bắt đầu một câu lệnh.
Mã thông báo xuất hiện trong một khu vực nơi các dòng mới
được bật.
Các mã thông báo có thể chấm dứt một câu lệnh là: các chữ, số nhận
dạng và các dấu phân cách sau và các từ dành riêng:
this null true false
_
)
]
}

return

type

<xml-start>

Các thẻ có thể bắt đầu một câu lệnh là tất cả các mã thông báo
Scala ngoại trừ các dấu phân cách sau và các từ dành riêng:
catch else extends finally forSome match
with yield , . ; : = => <- <: <%
>: # [ ) ] }
Mã casethông báo chỉ có thể bắt đầu một

câu lệnh nếu được theo sau

bởi một classhoặc một objectmã thông báo.
Các dòng mới được bật trong:
1.

tất cả tệp nguồn Scala, ngoại trừ các vùng lồng nhau trong đó
các dòng mới bị vô hiệu hóa và
2.
khoảng cách giữa mã thông báo khớp {và }dấu ngoặc ôm, ngoại
trừ các vùng lồng nhau trong đó các dòng mới bị tắt.
Các dòng mới bị tắt trong:
1.

khoảng cách giữa mã thông báo khớp (và )dấu ngoặc đơn, ngoại
trừ các vùng lồng nhau trong đó các dòng mới được bật và
2.
khoảng cách giữa mã thông báo khớp [và ]khung, ngoại trừ các
vùng lồng nhau trong đó các dòng mới được bật.
3.
Khoảng thời gian giữa casemã thông báo và mã thông báo khớp
của nó =>, ngoại trừ các vùng lồng nhau trong đó các dòng mới được
bật.
4.
Bất kỳ khu vực nào được phân tích ở chế độ XML .


Lưu ý rằng các ký tự dấu ngoặc {...}kép trong các chuỗi ký tự XML và
chuỗi không phải là mã thông báo, và do đó không kèm theo một khu
vực nơi các dòng mới được kích hoạt.
Thông thường, chỉ một nlmã thông báo duy nhất được chèn vào giữa
hai mã thông báo không phải dòng mới liên tiếp trên các dòng khác

nhau, ngay cả khi có nhiều dòng giữa hai mã thông báo. Tuy nhiên,
nếu hai thẻ được phân tách bằng ít nhất một dòng trống hoàn toàn
(tức là một dòng không chứa ký tự có thể in), thì hai nlthẻ được chèn
vào.
Ngữ pháp Scala (được đưa ra đầy đủ ở đây ) chứa các sản phẩm trong
đó các nlthẻ tùy chọn , nhưng không phải là dấu chấm phẩy, được chấp
nhận. Điều này có hiệu lực là một dòng mới ở một trong các vị trí này
không chấm dứt một biểu thức hoặc câu lệnh. Các vị trí này có thể
được tóm tắt như sau:
Nhiều mã thông báo dòng mới được chấp nhận ở các vị trí sau (lưu ý
rằng dấu chấm phẩy thay cho dòng mới sẽ là bất hợp pháp trong mỗi
trường hợp sau):
giữa điều kiện của biểu thức có điều kiện hoặc vòng lặp while và
biểu thức tiếp theo sau,

giữa các điều tra viên hiểu và biểu thức tiếp theo sau đây, và

sau typetừ khóa ban đầu trong định nghĩa kiểu hoặc khai báo .
Một mã thông báo dòng mới được chấp nhận


trước dấu ngoặc mở '{', nếu cú đúp đó là sự tiếp tục hợp pháp của
câu lệnh hoặc biểu thức hiện tại,

sau khi một toán tử infix , nếu mã thông báo đầu tiên trên dòng
tiếp theo có thể bắt đầu một biểu thức,

ở phía trước của một mệnh đề tham số , và

sau một chú thích .

Các mã thông báo dòng mới giữa hai dòng không được coi là dấu tách
câu lệnh.


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

Với một ký tự dòng mới bổ sung, cùng một mã được hiểu là tạo đối
tượng theo sau là một khối cục bộ:
new Iterator[Int]
{

}

private var x = 0
def hasNext = true

def next = { x += 1; x }
x < 0 ||
x > 10

Với một ký tự dòng mới bổ sung, cùng một mã được hiểu là hai biểu
thức:
x < 0 ||
x > 10
def func(x: Int)
(y: Int) = x + y

Với một ký tự dòng mới bổ sung, cùng một mã được hiểu là một định
nghĩa hàm trừu tượng và một câu lệnh cú pháp bất hợp pháp:
def func(x: Int)
(y: Int) = x + y
@serializable
protected class Data { ... }

Với một ký tự dòng mới bổ sung, cùng một mã được hiểu là một thuộc
tính và một câu lệnh riêng biệt (mà là cú pháp bất hợp pháp).
@serializable
protected class Data { ... }

Chữ viết
Có các chữ số cho số nguyên, số dấu chấm động, ký tự, booleans, ký
hiệu, chuỗi. Cú pháp của các chữ cái này là trong mỗi trường hợp như
trong Java.
Literal ::= [‘-’] integerLiteral
| [‘-’] floatingPointLiteral
| booleanLiteral

| characterLiteral
| stringLiteral


| symbolLiteral
| ‘null’

Integer Literals
integerLiteral ::= (decimalNumeral | hexNumeral)
[‘L’ | ‘l’]
decimalNumeral ::= ‘0’ | nonZeroDigit {digit}
hexNumeral
::= ‘0’ (‘x’ | ‘X’) hexDigit {hexDigit}
digit
::= ‘0’ | nonZeroDigit
nonZeroDigit ::= ‘1’ | … | ‘9’
Các chữ số nguyên thường là loại Inthoặc

loại Longkhi được theo sau bởi
một Lhoặc lhậu tố. Giá trị của loại Intlà tất cả các số nguyên từ $ -2 ^
{31} $ và $ 2 ^ {31} -1 $, bao gồm. Giá trị của loại là tất cả các số
nguyên từ $ -2 ^ {63} $ và $ 2 ^ {63} -1 $, bao gồm. Một lỗi biên
dịch thời gian xảy ra nếu một số nguyên chữ biểu thị một số bên ngoài
các phạm vi này.−231−231231−1231−1Long−263−263263−1263−1
Tuy nhiên, nếu loại pt dự kiến của một chữ trong một biểu thức là một
trong hai Byte, Shorthoặc hoặc Char số nguyên phù hợp trong phạm vi số
được xác định theo loại, thì số được chuyển thành loại pt và kiểu chữ
là pt . Các dãy số được đưa ra bởi các loại này là:
Byte


Short
Char

−27−2727−127−
1

−215−215215−1
215−1

00216−1216−1

0

21
0xFFFFFFFF
-42L
Chữ nổi Floating Point
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’
Các Floatdấu phẩy dấu chấm động là loại khi được theo sau bởi

một hậu
tố kiểu dấu chấm động Fhoặc f, và có kiểu Doublekhác. Loại Float này bao
gồm tất cả các giá trị điểm động nhị phân đơn chính xác IEEE 754 32

bit, trong khi loại Doublenày bao gồm tất cả các giá trị điểm động nhị
phân kép chính xác IEEE 754 64 bit.
Nếu một dấu phẩy động trong một chương trình được theo sau bởi một
mã thông báo bắt đầu bằng một chữ cái, thì phải có ít nhất một ký tự
khoảng trắng xen kẽ giữa hai thẻ.
0.0

1e30f

3.14159f

1.0e-100

.1


Cụm từ 1.toStringphân tích thành ba mã thông báo khác nhau: số
nguyên nguyên 1, a .và số nhận dạng toString.
1.không phải là một dấu chấm động hợp lệ theo nghĩa đen vì chữ số bắt
buộc sau khi .thiếu.
Boolean Literals
booleanLiteral ::= ‘true’ | ‘false’
Các boolean literals truevà falselà thành viên của type Boolean.
Chữ ký tự
characterLiteral ::= ‘'’ (charNoQuoteOrNewline | UnicodeEscape | charEscapeSeq) ‘'’

Ký tự chữ là một ký tự đơn kèm theo dấu ngoặc kép. Ký tự này có thể
là bất kỳ ký tự Unicode nào ngoại trừ dấu phân tách trích dẫn đơn
hoặc \u000A(LF) hoặc \u000D(CR); hoặc bất kỳ ký tự Unicode nào được
biểu thị bằng cách thoát Unicode hoặc bằng chuỗi thoát .

'a'

'\u0041'

'\n'

'\t'

Lưu ý rằng mặc dù chuyển đổi Unicode được thực hiện sớm trong quá
trình phân tích cú pháp, do đó các ký tự Unicode thường tương đương
với mở rộng thoát của chúng trong văn bản nguồn, phân tích cú pháp
bằng chữ chấp nhận các ký tự Unicode tùy ý, bao gồm ký tự
chữ '\u000A', cũng có thể được viết bằng chuỗi thoát '\n'.
Chuỗi ký tự
stringLiteral ::= ‘"’ {stringElement} ‘"’
stringElement ::= charNoDoubleQuoteOrNewline | UnicodeEscape | charEscapeSeq

Chuỗi ký tự là một chuỗi các ký tự trong dấu ngoặc kép. Các ký tự có
thể là bất kỳ ký tự Unicode nào ngoại trừ dấu phân cách trích dẫn kép
hoặc \u000A(LF) hoặc \u000D(CR); hoặc bất kỳ ký tự Unicode nào được
biểu thị bằng cách thoát Unicode hoặc bằng chuỗi thoát .
Nếu chuỗi ký tự chứa ký tự ngoặc kép, nó phải được thoát bằng cách sử
dụng "\"".
Giá trị của một chuỗi ký tự là một thể hiện của lớp String.
"Hello, world!\n"
"\"Hello,\" replied the world."

Văn bản chuỗi nhiều dòng
stringLiteral ::= ‘"""’ multiLineChars ‘"""’
multiLineChars ::= {[‘"’] [‘"’] charNoDoubleQuote} {‘"’}


Một chuỗi ký tự nhiều dòng là một chuỗi ký tự được đặt trong dấu
ngoặc kép """ ... """. Trình tự các ký tự là tùy ý, ngoại trừ việc nó có thể
chứa ba hoặc nhiều ký tự trích dẫn liên tiếp chỉ ở cuối cùng. Các ký tự
không nhất thiết phải có thể in được; các dòng mới hoặc các ký tự điều
khiển khác cũng được cho phép. Unicode thoát hoạt động như ở mọi
nơi khác, nhưng không có trình tự thoát nào ở đây được diễn giải.
"""the present string
spans three
lines."""


Điều này sẽ tạo ra chuỗi:
the present string
spans three
lines.

Thư viện Scala chứa một phương thức tiện ích stripMargin có thể được sử
dụng để tách khoảng trắng hàng đầu khỏi các chuỗi nhiều dòng. Cách
diễn đạt
"""the present string
|spans three
|lines.""".stripMargin

đánh giá
the present string
spans three
lines.
Phương thức stripMarginđược


định nghĩa trong
lớp scala.collection.immutable.StringLike . Bởi vì có một định nghĩa
trước chuyển đổi ngầm từ Stringđể StringLike, phương pháp này được áp
dụng cho tất cả các chuỗi.
Chuỗi thoát

Các chuỗi thoát sau đây được nhận dạng bằng ký tự và chuỗi ký tự
chuỗi.
charEscapeS
eq

unicod
e

Tên

cha
r

‘\‘ ‘b‘

\u0008

backspace

BS

‘\‘ ‘t‘

\u0009


Tab ngang

HT

‘\‘ ‘n‘

\u000a

linefeed

LF

‘\‘ ‘f‘

\u000c

thức ăn dạng

FF

‘\‘ ‘r‘

\u000d

vận chuyển trở lại

CR

‘\‘ ‘"‘


\u0022

báo giá kép

"

‘\‘ ‘'‘

\u0027

trích dẫn đơn

'

‘\‘ ‘\‘

\u005c

dấu gạch chéo
ngược

\


Một ký tự có Unicode nằm trong khoảng từ 0 đến 255 cũng có thể được
biểu diễn bằng cách thoát bát phân, tức là dấu gạch chéo ngược '\'theo
sau là một chuỗi gồm tối đa ba ký tự bát phân.
Nó là một lỗi thời gian biên dịch nếu một ký tự dấu chéo ngược trong
một ký tự hoặc chuỗi ký tự không bắt đầu một chuỗi thoát hợp lệ.

Ký hiệu chữ
symbolLiteral ::= ‘'’ plainid
Biểu tượng chữ 'xlà viết

tắt của biểu thức scala.Symbol("x").
một trường hợp lớp , được định nghĩa như sau.

Symbollà

package scala
final case class Symbol private (name: String) {
override def toString: String = "'" + name
}
Các applyphương pháp Symbol'đối tượng

của bạn đồng hành lưu trữ tài
liệu tham khảo yếu để Symbols, do đó đảm bảo rằng literals biểu tượng
giống hệt nhau là tương đương liên quan đến tham khảo bình đẳng.
Khoảng trắng và nhận xét
Các thẻ có thể được phân tách bằng các ký tự khoảng trắng và / hoặc
các chú thích. Nhận xét có hai dạng:
Một chú thích một dòng là một dãy các ký tự bắt đầu //và kéo dài đến
cuối dòng.
Nhận xét nhiều dòng là chuỗi ký tự giữa /*và */. Nhận xét nhiều dòng có
thể được lồng nhau, nhưng được yêu cầu phải lồng nhau đúng
cách. Do đó, một nhận xét như /* /* */sẽ bị từ chối vì có nhận xét chưa
được hoàn thành.
Trailing dấu phẩy trong biểu thức nhiều dòng
Nếu dấu phẩy ( ,) được theo sau ngay lập tức, bỏ qua khoảng trống,
bằng một dòng mới và dấu ngoặc đơn ( )), ngoặc đơn ( ]) hoặc dấu

ngoặc nhọn ( }), thì dấu phẩy được coi là "dấu phẩy" và bị bỏ qua. Ví
dụ:
foo(
23,
"bar",
true,
)

Chế độ XML
Để cho phép bao gồm các phân đoạn XML, phân tích từ vựng chuyển
từ chế độ Scala sang chế độ XML khi gặp phải một góc ngoặc mở '<'
trong trường hợp sau: '<' phải được đặt trước bằng khoảng trống, dấu


ngoặc đơn mở hoặc dấu mở cú đúp và ngay sau đó là ký tự bắt đầu
một tên XML.
( whitespace | ‘(’ | ‘{’ ) ‘<’ (XNameStart | ‘!’ | ‘?’)
XNameStart ::= ‘_’ | BaseChar | Ideographic // as in W3C XML, but without ‘:’

Máy quét chuyển từ chế độ XML sang chế độ Scala nếu
biểu thức XML hoặc mẫu XML bắt đầu bằng ký tự '<' ban đầu đã
được phân tích thành công hoặc nếu

trình phân tích cú pháp gặp một biểu thức hoặc mô hình Scala
được nhúng vào và buộc Máy quét quay trở lại chế độ bình thường,
cho đến khi biểu thức Scala hoặc mẫu được phân tích cú pháp thành
công. Trong trường hợp này, vì các đoạn mã và XML có thể được lồng
nhau, trình phân tích cú pháp phải duy trì một ngăn xếp phản ánh sự
lồng ghép các biểu thức XML và Scala đầy đủ.
Lưu ý rằng không có mã thông báo Scala nào được xây dựng ở chế độ

XML và các nhận xét đó được hiểu là văn bản.


Định nghĩa giá trị sau đây sử dụng một XML literal với hai biểu thức
Scala được nhúng:
val b = <book>
<title>The Scala Language Specification</title>
<version>{scalaBook.version}</version>
<authors>{scalaBook.authors.mkList("", ", ", "")}</authors>
</book>



×