Lua1.1 Lua 的參考手冊 (一)

說明:
這個文檔是 Lua1.1 的 doc 目錄裏的 manual.ps 文件。
原文版權歸原做者全部,這篇翻譯只是做爲學習之用。若是翻譯有不當之處,請參考原文。
-------------------如下是正文-------------------
編程語言 Lua 的參考手冊

摘要:Lua 是嵌入式語言,被設計用來作爲一個配置語言給其它程序使用。本文檔描述 Lua 編程語言以及 Lua 程序和宿主 C 程序交互的 API。它展現了一些使用這些主要特色的例子。

--------------------------------------
1 簡介
--------------------------------------
Lua 是一種嵌入式編程語言,支持過程式編程與數據描述功能。它常常作爲別的程序的配置語言使用。Lua 是由 R. Ierusalimschy, L. H. de Figueiredo 和 W. Celes 設計, 由 W. Celes 實現。

Lua 被實現爲由 C 語言寫成的庫。作爲一個嵌入式語言,Lua 沒有 "main" 函數的概念;它只能嵌入到宿主運行,叫作嵌入程序。宿主能夠執行一段 Lua 代碼,能夠讀寫 Lua 變量,能夠註冊被 Lua 代碼調用的 C 函數。經過註冊 C 函數,Lua 能夠擴展本身以應對不一樣的領域,從而建立可定製、共享語法框架的編程語言。

Lua 是自由分發的軟件,正常提供沒有什麼保證。本文檔裏描述的這個實現能夠從下面的匿名 ftp 獲得:

www.lua.org/ftp/refman-1.1.ps.gz

--------------------------------------
2 環境和模塊
--------------------------------------
Lua 中全部的語句都在一個全局環境中執行。這個全局環境持有全部的全局變量和函數,在嵌入語言一開始執行時進行初始化,並持續到結束。

這個全局環境能夠用 Lua 代碼或者嵌入程序來管理,能夠經過 Lua 的實現庫來讀寫全局變量。

全局變量不須要聲明。全部的變量被認爲是全局的除非明確聲明爲 local (詳見 4.4.5 節,local 的聲明)。在第一次賦值以前,全局變量的值爲 nil。

Lua 的執行單元叫作模塊(module) 。module 的語法爲(注一):

 module --> { statement | function }

一個模塊能夠包含語句和/或函數定義,能夠在一個文件中或者在一個宿主程序的字符串中。當執行一個模塊,首先它全部的函數和語句被編譯,函數被添加到全局環境,而後語句按順序執行。模塊對於全局環境的全部修改是持久的,這些修改在模塊結束後依然可見。修改包括全局變量的修改和新函數的定義(注二)

注一:這裏如常見的擴展的 BNF 範式同樣,{ a } 表示 0 個或多個 a,[ a ] 表示一個可選的 a,{ a } +(加號是右上角標)表示一個或多個 a。
注二:實際上,一個函數的定義就是給一個全局變量賦值。(詳見第 3 節)。

--------------------------------------
3 類型
--------------------------------------
Lua 是動態類型語言。變量沒有類型;只有值有類型。全部值含有本身的類型。全部,Lua 語言中沒有類型定義。

Lua 中有七種基本數據類型:nil, number, string, function, Cfunction, userdata, 和 table。Nil 是值爲 nil 的類型,它的主要性質就是和其它值不一樣。Number 表示實數(浮點型),string 是字符串。

函數是第一類值(first-class values)。這意味着他們能夠存儲在變量中,作爲參數傳遞給其餘函數或者作爲結果返回。當函數被定義,它的函數體被編譯並保存在一個給定名稱的全局變量。Lua 能夠調用(和操做)寫在 Lua 或 C 中的函數;後者的類型是 Cfunction。

userdata 類型容許 Lua 變量保存任意的 C 指針(void*)。它至關於 C 語言中的 void* 型指針,因此在 Lua 中除分配和相等測試操做之外,其它的操做是無效的。

table 類型實現爲關聯數組,便可以用數字和字符串索引的數組。所以,該類型不只可用於表示普通數組,也能夠用於表示符號表,集合,記錄等。爲表示一個記錄,Lua 使用字段名爲下標。語言經過提供 a.name 這種表示做爲 a["name"] 的語法糖。

須要特色注意的是 table 是對象而非值。變量不能包含 table,只能引用它。賦值,參數傳遞,返回老是會涉及到 table 的引用,而不會對 table 進行拷貝。並且,table 必須在使用前顯式建立。詳見 4.5.7 節。

--------------------------------------
4 語言
--------------------------------------
這節介紹 Lua 的詞法,語法和語義。

-------------------
4.1 詞法約定
-------------------
Lua 是區別大小寫的語言。標識符能夠是任何字母,數字,下劃線組成的字符串,且首字母不可爲數字。下面這些是保留的關鍵字,不可用作標識符:
and     do     else     elseif     end
function     if     local     nil     not
or     repeat     return     until     then     while

下面的字符串留作它用:
~= <= >= < > = .. + - * / %
( ) { } [ ] @ ; , .

字符串常量能夠由成對的單引號或雙引號界定,而且能夠包括 C 語言風格的轉義序列 '\n', '\t' 和 '\r'。註釋可在字符串外面的任何地方用兩個連字符(--)開始,直到行尾。

數值常量能夠由可選的小數部分,可選的指數部分寫成。下面是一些有效的數值常量示例:
4 4. .4 4.57e-3 .3e12

-------------------
4.2 約定
-------------------
Lua 提供了一些自動轉化。在字符串上的算術運算會試圖把字符串轉化爲數值。更明確的說,字符串經過 C 函數 strtod 轉化爲數值。相反的,當一個數值參與字符串操做時,數值會被轉化爲字符串。按照如下規則:若是數值是一個整數,沒有指數或小數點,則直接轉化;不然,它和標準 C 函數 printf 用格式 "%g" 同樣的格式轉化。

-------------------
4.3 調整
-------------------
Lua 中的函數能夠返回多個值。由於函數沒有類型聲明,編譯器不知道函數會返回多少值。因此,有時候,值列表必須在運行時調整到給定長度:若是實際值多於所需,那麼多餘的值會被扔掉;若是須要的值多於實際的,根據須要在列表中進行 nil 擴展。調整也發生在其它地方,例如多重賦值。

-------------------
4.4 語句
-------------------
Lua 支持幾乎全部常規的語句。常規的命令包括:賦值,控件結構和過程調用。很是規的命令包括 4.5.7 節中描述的表的構造函數,和局部變量的聲明。

---------
4.4.1 塊
---------
一個塊(block)就是一個順序執行的語句列表。任何語句均可以可選的後跟一個分號。
block --> { stat sc } [ret sc]
sc --> [ ';' ]
因爲語義分析的緣由, return 語句只能寫做爲一個塊裏的最後一句。這一個約束同時能夠避免了「語句不可達」的錯誤。

---------
4.4.2 賦值
---------
Lua 支持多重賦值。因此,語法定義了賦值的左邊但是一個變量列表,右邊能夠是一個表達式的列表。兩個列表元素都以逗號分割。
stat --> varlist1 '=' explist1
varlist1 --> var { ',' var }
這個語句首先求出全部右邊的值,再排列左邊的變量,最後對其賦值。因此,能夠這樣交換兩個變量的值,以下所示:
x, y = y, x
賦值前,值的列表被調整到和變量列表的長度相等(詳見 4.3 節)。
一個名字能夠指示一個全局變量或者局部變量。
var --> name
var --> var '[' exp1 ']' | var '.' |name
方括號用來索引 table。在這種狀況下,var 通過求值必須是一個 table;不然,會有一個執行錯誤。語法 var.NAME 僅僅是 var['NAME'] 的語法糖。

---------
4.4.2 控制結構
---------
控制結構的條件表達式能夠返回任何值。全部不是 nil 的值都被認爲是真,nil 被認爲是假。if, while 和 repeat 和別的語言中的意義同樣。
stat --> while exp1 do block end
stat --> repeat block until exp1
stat --> if exp1 then block { elseif } [else block] end
elseif --> elseif exp1 then block
return 用於從函數中返回值。由於一個函數能夠返回多個值,return 語句的語法是:
ret --> return explist

---------
4.4.2 表達式作爲語句
---------
全部可能出現反作用的表達式均可以做爲語句執行。這包括函數調用和列表的構造:
stat --> functioncall
stat --> tableconstructor
最後返回的值被丟棄。函數調用在 4.5.8 節解釋,構造函數是 4.5.7 節的主題。

---------
4.4.2 局部聲明
---------
局部變量能夠在塊中的任何位置聲明。它的做用域從聲明的地方開始,直到塊結束。聲明能夠包含賦初始值。
stat --> local declist [init]
declist --> name { ',' name }
init --> '=' explist1
若是聲明時含有賦初值操做,那麼他和多重賦值有一樣的語義。不然,全部的變量被初始化爲 nil。

-------------------
4.5 表達式
-------------------
---------
4.5.1 簡單表達式
---------
簡單表達式是:
exp --> '(' exp ')'
exp --> nil
exp --> 'number'
exp --> 'literal'
exp --> var
數值(數值常量)和字符串常量在 4.1 節解釋過了。變量在 4.4.2 節解釋過了。

---------
4.5.2 算術運算符
---------
Lua 支持常見的算術運算符,意思也保持不變。這些操做符是二元操做符 +, -, *, / 和一元操做符 + 和 -。操做數必須是數值,或者能夠根據 4.2 節中給出的規則轉化爲數值的字符串,

---------
4.5.3 關係運算符
---------
Lua 提供瞭如下的關係運算符:
< > <= >= ~= =
他們返回 nil 作爲假,1 作爲真。

相等首先比較兩個操做數的類型。若是不一樣,結果爲 nil。不然,比較它們的值。數值或字符串以常見的方式比較。表, Cfuntion 和函數按引用比較,也就是說,兩個比較的表只有是同一個的時候才被認爲是相等的。不等操做 ~= 和相等運算具備徹底相反的結果。

其它的操做符只能應用於字符串或數值。若是一個參數是一個字符串,另外一個也會被轉化爲字符串,而且它們的值以字典序進行比較。不然,兩個都是數值的話,狀況相似。

---------
4.5.4 邏輯運算符
---------
全部的邏輯運算符,如控制結構同樣,認爲 nil 爲假而其它的都爲真。像關係運算符同樣,他們返回 nil 爲假,1 爲真。輪迴運算符是:
and or not
and 和 or 是短路求值,也就是說,第二個操做數只在須要的時候才被求值。

---------
4.5.5 鏈接
---------
Lua 提供了一個字符串鏈接操做符「..",操做數必須是字符串或者數字,若是是數字的話,則按 4.2 節描述的規則進行轉化。

---------
4.5.6 優先級
---------
操做符的優先級以下表所示,從低到高排列:
and or
< > <= >= ~= =
..
+ -
* /
not + (unary) - (unary)
二元操做符具體左結合性

---------
4.5.7 表的構造函數
---------
Table 的構造函數是建立表的構造函數。表的構造函數有不一樣的使用方法。最簡單的一種是:
tableconstructor --> '@' '(' [exp1 ] ')'
這樣的表達式會生成一個新的的空表。表的尺寸是可選的,而且能夠給初始表的大小一個提示。Lua 中的表能夠根據須要進行動態擴展不管初始大小是多大。

構造一個表並初始化一些字段能夠用下面的語法:
tableconstructor --> '@' [name] fieldlist
這樣的表達式會新建一個表,表的值是肯定的,表中的一些字段根據 fieldlist 被初始化了。若是這裏給出了 name,將會調用一個參數爲這個表的 name 函數。該函數能夠用來字段值,新建一些默認字段,或者用來作其它的有反作用的事。
fieldlist --> '{' [ffieldlist1 ] '}'
ffieldlist1 --> ffield { ',' ffield }
ffield --> name '=' exp
這些字段列表初始化表中具名的字段。以下面的例子:
a = @f { x = 1, y = 3 } 和下面的是等價的: temp = @(2) temp.x = 1 temp.y = 3 f(temp) a = temp 可使用下面的語法初始化列表 fieldlist --> '[' [lfieldlist1 ] ']' lfieldlist1 --> exp { ',' exp } 例如: a = @["v1", "vv"] 和下面的等價: temp = @(2) temp[1] = "v1" temp[2] = "vv" a = temp 在特定的狀況下,下面的表達式是徹底等價的: @f{} @f[] --------- 4.5.8 函數調用 --------- 函數調用語法以下: functioncall --> var '(' [explist1 ] ')'        explist1 --> { exp1 ',' } exp 這裏,var 但是是什麼變量(全局的,局部的,下標索引的等),只要它的類型爲 function 或 Cfunction. 全部的表達式參數在函數調用以前被從左到右求值;而後參數被調整到和函數調用所用的參數個數一致(詳見 4.3 節);以後被賦值對實際參數。 由於一個函數能夠返回多個值(詳見 4.4.3 節),返回值的個數在使用以前會進行調整。若是一個函數做爲語句使用(詳見 4.4.4 節),它的返回結果會被調整到 0 個(也就是所有丟棄)。若是一個函數在須要一個值(語法中被表示爲非終結的 exp1)的地方調用,它的返回結果會被調整到 1 個。若是一個函數在須要多個值的地方調用(語法上表示爲非終結的 exp),不對返回結果進行調整。 ------------------- 4.6 函數定義 ------------------- 函數能夠在模塊中的任何全局層面定義;函數不能夠定義在另外一個函數中。函數定義的語法是: function --> function name '(' [parlist1 ] ')' block end 當 Lua 發現一個函數定義,它把函數體編譯爲字節碼保存在全局變量 name 中,類型爲 function。 參數和局部變量的表現同樣,由參數值進行初始化。 parlist1 --> 'name' { ',' name } 結果由 return 語句返回(見 4.4.3)節。若是執行到函數最後也沒有 return 指令的話,函數不返回值。 (未完待續)
相關文章
相關標籤/搜索