(接上篇)
--------------------------------------
4 語言
--------------------------------------
這節描述 Lua 的詞法,語法和語義。
-------------------
4.1 詞法約定
-------------------
Lua 中的標識符能夠是任何字母,數字,下劃線組成的字符串,且首字母不可爲數字。這符合大多數語言中標識符的定義,除了字母的字義依賴於當前的區域設置:全部的在當前的區域設置中被認爲是字母的字符能夠被用在標識符裏。下面這些是保留的關鍵字,不可用作標識符:
and break do else elseif
end for function if in
local nil not or repeat
return then until while
Lua 是區分大小寫的語言:and 是保留字,可是 And 和 αnd (若是區域設置容許的話)是不一樣的,有效的標識符。做爲一個約定,由下劃線開始後跟大寫字母的標識符(好比 _INPUT)保留做爲內部變量。
如下字符串表示其它標記:
~= <= >= < > == = + - * /
( ) { } [ ] ; , . .. ...
字符串常量能夠由成對的單引號或雙引號界定,而且能夠包含 C 語言風格的轉義序列 `\a' (響鈴), `\b' (退格), `\f' (換頁), `\n' (換行), `\r' (回車), `\t' (水平製表符), `\v' (垂直製表符), `\\' (反斜槓), `\"' (雙綽號), `\'' (單引號), and `\newline' (就是說,一個反斜槓後跟一個 newline,這會在字符串中生成一個新行)。字符串中的字符能夠由它的數值來指定,經過轉義序列`\ddd',這裏的 ddd 是一個三位數字。Lua 中的字符串能夠包含任意的 8 位值,包含內嵌的 0 ,它能夠由 `\000' 來指定。
字符串常量也能夠由成對的 [[ ... ]] 界定。 這一種形式的字面量能夠跨行,能夠包含嵌套的 [[ ... ]],而且不解釋轉義序列。這種形式特別適用於編寫包含程序塊或其餘引用字符串的字符串。例如,在一個使用 ASCII 碼的系統中,下面的三個常量是等價的:
1) "alo\n123\""
2) '\97lo\10\04923"'
3) [[alo
123"]]
註釋可在字符串外面的任何地方用兩個連字符(--)開始,直到行尾。並且,塊的第一行會被跳過若是它由 # 開始。這種機制是爲了容許把 Lua 做爲一種 Unix 系統中的腳本解釋器(參見 8 節)。
數值常量能夠由可選的小數部分,可選的指數部分寫成。下面是一些有效的數值常量示例:
3 3.0 3.1416 314.16e-2 0.31416E1
-------------------
4.2 強制轉換
-------------------
Lua 在運行時提供了一些在值之間的自動轉換。在字符串上的算術運算會試圖把字符串轉換爲數值,聽從一般的規則。相反的,當一個數值參與字符串操做時,數值會被轉換爲字符串,以一種合理的格式。轉換格式要求一個數值轉換到字符串後,能再被轉換回原始的數值。因此,對於一個數值,轉換並不須要生成一個好看的文本格式。爲徹底控制數值到字符串的轉換,使用 format 函數(參見 6.2 節)。
-------------------
4.3 調整
-------------------
Lua 中的函數能夠返回多個值。由於沒有類型聲明,當一個函數被調用時系統不知道函數會返回多少值,或者它須要多少個參數。因此,有時候,值列表必須在運行時調整到給定長度。若是實際值多於所需,那麼多餘的值會被丟掉;若是須要的值多於實際的,根據須要在列表中進行 nil 擴展。調整也發生多重賦值(參見 4.4.2 節)和函數調用(參見 4.5.8 節)中。
-------------------
4.4 語句
-------------------
Lua 支持幾乎全部常規的語句,和 Pascal 和 C 相似。常規的命令包括:賦值,控制結構和過程調用。很是規的命令包括表的構造函數(參見 4.5.7 節),和局部變量的聲明(參見 4.4.6 節)。
---------
4.4.1 塊
---------
一個塊(block)就是一個語句列表。在語法中,一個 block 等同於一個 chunk:
block ::= chunk
一個 block 也能夠顯式的界定:
stat ::= do block end
顯式的 block 在控制局部變量的做用域(參見 4.4.6 節)時頗有用。顯式的 block 有時也被用於在另外一個塊中添加一個 return 或者 break 語句(參見 4.4.3 節)。
---------
4.4.2 賦值
---------
Lua 支持多重賦值。因此,語法定義了賦值的左邊是一個變量列表,右邊是一個表達式的列表。兩個列表元素都以逗號分割。
stat ::= varlist1 `=' explist1
varlist1 ::= var {`,' var}
這個語句首先求出全部右邊的值,再排列左邊的變量,最後對其賦值。因此,代碼:
i = 3
i, a[i] = 4, 20
把 a[3] 設置爲 20,可是並不影響 a[4] 由於 i 在 a[i] 裏被賦值爲 4 以前就被求值(evaluated)了。
多重賦值能夠用來交換兩個變量的值,以下所示:
x, y = y, x
賦值的兩邊的列表可能長度不一樣。在賦值前,值的列表被調整到和變量列表的長度相等(參見 4.3 節)。
一個名字能夠指示一個全局變量或局部變量或形式參數:
var ::= name
方括號用來索引 table:
var ::= varorfunc `[' exp1 `]'
varorfunc ::= var | functioncall
varorfunc 的結果是一個 table,由表達式 exp1 的值索引的字段得到所賦的值。
var.NAME 僅僅是 var["NAME"] 的語法糖。
var ::= varorfunc `.' name
全局變量和下標變量的賦值和評估(evaluations )的意義能夠被 tag method 修改(參見 4.8 節)。事實上,一個 x=val 的賦值,這裏 x 是一個全局變量,等價於調用 setglobal("x", val);而且 t[i] = val 等價於 settable_event(t,i,val)。這些函數的完整描述參見 4.8 節(setglobal 在基礎的庫中,settable_event 僅用於解釋目的)。
---------
4.4.3 控制結構
---------
控制結構 if, while 和 repeat 有一般意義和常見的語法
stat ::= while exp1 do block end
stat ::= repeat block until exp1
stat ::= if exp1 then block {elseif exp1 then block} [else block] end
一個控制結構的條件表達式 exp1 能夠返回任何值。全部不是 nil 的值都被認爲是真,只有 nil 被認爲是假。
return 語句用於從函數或者塊中返回值。由於函數或塊能夠返回多個值,return 語句的語法是:
stat ::= return [explist1]
break 語句能夠被用來終結一個循環的執行,跳到循環以後的下一條語句:
stat ::= break
break 結束包含它的最內層的循環(while, repeat 或 for)。
因爲語法緣由,return 和 break 語句只能寫在一個 block 的最後一句。若是確實須要在一個塊的中間 return 或 break,可使用一個顯式的 block,如同在語句 `do return end' 中,由於這時 return 是內層 block 的最後一個語句。
---------
4.4.4 For 語句
---------
for 語句有兩種格式,一種用於數值,一種用於表。數值型的 for 循環有以下語法:
stat ::= for name `=' exp1 `,' exp1 [`,' exp1] do block end
一個 for 語句如同
for var = e1 ,e2, e3 do block end
等價於代碼:
do
local var, _limit, _step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and _limit and _step) then error() end
while (_step>0 and var<=_limit) or (_step<=0 and var>=_limit) do
block
var = var+_step
end
end
注意以下:
> _limit 和 _step 是不可見的變量。這裏的名字僅用於解釋目的。
> 若是在 block 內部對 var 賦值,行爲未定義。
> 若是沒有第三個表達式(步長),則步長爲 1 。
> 循環結束(limit)和步長只被求值一次,在循環開始以前。
> 變量 var 是對於語句來講是局部的;在 for 結束後不可使用它的值。
> 你可使用 break 退出一個 for 循環。若是你須要索引的值,在退出前把它賦給另外一個變量。
表的 for 循環語句遍歷給定表的全部鍵值對(index, value)。它有以下語法:
stat ::= for name `,' name in exp1 do block end
一個 for 語句如同
for index, value in exp do block end
等價於下面的代碼
do
local _t = exp
local index, value = next(t, nil)
while index do
block
index, value = next(t, index)
end
end
注意以下:
> _t 是不可見變量,這裏的名字僅用於解釋目的。
> 若是在 block 內部對 index 賦值,行爲未定義。
> 若是在遍歷時改變表 _t ,行爲未定義。
> 變量 index 和 value 是對於語句來講是局部的;在 for 結束後不可使用它們的值。
> 你可使用 break 退出一個 for 循環。若是你須要 index 或 value 的值,在退出前把它們賦給另外的變量。
> 表的元素遍歷的順序是未定義的,即便是數字索引。若是你想以數字順序遍歷索引,使用數值型 for 。
---------
4.4.5 函數調用作爲語句
---------
因爲可能的反作用(side-effects),函數調用能夠做爲語句執行。
stat ::= functioncall
在這種狀況下,全部的返回值都被丟棄。函數調用在 4.5.8 節解釋。
---------
4.4.6 局部聲明
---------
局部變量能夠在塊中的任何位置聲明。聲明能夠包含賦初始值。
stat ::= local declist [init]
declist ::= name {`,' name}
init ::= `=' explist1
若是有賦初值操做,那麼他和多重賦值有一樣的語義。不然,全部的變量被初始化爲 nil。
一個 chunk 也是一個 block,因此局部變量能夠在任何顯式 block 的外部聲明。
局部變量的做用域從聲明的地方開始,直到 block 結束。因此,代碼 local print=print 新建一個名爲 print 的局部變量,該局部變量的初始值爲同名全局變量的值。
(未完待續)ide