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 指令的话,函数不返回值。 (未完待续)
相关文章
相关标签/搜索