Lua2.4 参考手册(二)

(接上篇)
--------------------------------------
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 函数 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 ‘]‘

方括号用来索引 table。如果 var 的结果是一个 table,由表达式值索引的字段获得所赋的值;否则,回退函数(fallback) settable 会被调用,调用时有三个参数:var 的值,表达式的值,将要被赋的值;参见 4.7 节。

var --> var ‘.‘ name
var.NAME 仅仅是 var[‘NAME‘] 的语法糖。

---------
4.4.3 控制结构
---------
控制结构的条件表达式可以返回任何值。所有不是 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.4 函数调用做为语句
---------
由于可能的副作用(side-effects),函数调用可以作为语句执行。
stat --> functioncall
最后返回的值被丢弃。函数调用在 4.5.8 节解释。

---------
4.4.5 局部声明
---------
局部变量可以在块中的任何位置声明。它的作用域从声明的地方开始,直到块结束。声明可以包含赋初始值。
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 节中给出的规则转化为数值的字符串,所有的操作(除了幂操作)具有通常意义。否则,回退函数 "arith" 将会被调用,参见 4.7 节。幂操作将一直调用这个回退函数。标准的数学库以预想的意义重定义了幂操作的回退,参见 6.3 节。

---------
4.5.3 关系运算符
---------
Lua 提供了以下的关系运算符:
< > <= >= ~= ==
他们返回 nil 做为假,非 nil (事实是数值 1 ) 做为真。

相等首先比较两个操作数的类型。如果不同,结果为 nil。否则,比较它们的值。数值或字符串以常见的方式比较。表, Cfuntion 和函数按引用比较,也就是说,两个比较的表只有是同一个的时候才被认为是相等的。不等运算 ~= 和相等运算 (==) 具有完全相反的结果。

其它的操作符是这么工作的:如果两个参数都是数值,他们就以数值比较。如果两个参数都可以转化为字符串,它们将以字典序比较。否则的话, 回退函数 "order" 将被调用;参见 4.7 节。

---------
4.5.4 逻辑运算符
---------
所有的逻辑运算符,和控制结构一样,认为 nil 为假而其它的都为真。逻辑运算符是:
and or not
and 和 or 是短路求值,也就是说,第二个操作数只在需要的时候才被求值。

---------
4.5.5 连接
---------
Lua 提供了一个字符串连接操作符“..",如果操作数是字符串或者数字,他们按 4.2 节的规则转化为字符串。否则,回退函数 "concat" 将被调用;参见 4.7 节。

---------
4.5.6 优先级
---------
操作符的优先级如下表所示,从低到高排列:
and or
< > <= >= ~= ==
..
+ -
* /
not  - (unary)
^
二元操作符具体左结合性,^除外,幂操作具有右结合性。

---------
4.5.7 表的构造函数
---------
Table 的构造函数是创建表的表达式。当对表的构造函数求值的时候,会生成一个新的表。构造函数可以用来新建一个空表,或者新建一个表并初始化一些字段。
构造函数的语法如下:
tableconstructor --> ‘{‘ fieldlist ‘}‘
fieldlist --> lfieldlist | ffieldlist | lfieldlist ‘;‘ ffieldlist
lfieldlist --> [lfieldlist1]
ffieldlist --> [ffieldlist1]

lfieldlist1 被用来初始化列表。
lfieldlist1 --> exp {‘,‘ exp} [‘,‘]

列表中的表达式被赋值给一个连续的数值索引,索引从 1 开始。例如:
a = {"v1", "v2", 23}
等同于:
temp = {}
temp[1] = "v1"
temp[2] = "v2"
temp[3] = 34
a = temp

另一种形式初始化表中的具名字段:
ffieldlist1 --> ffield {‘,‘ ffield} [‘,‘]
field --> name ‘=‘ exp
例如:
a = {x = 1, y = 3}
等同于:
temp = {}
temp.x = 1
temp.y = 3
a = temp

---------
4.5.8 函数调用
---------
函数调用有如下语法:
functioncall --> var realParams
这里,var 可以是任何变量(全局的,局部的,下标索引的等),如果它的类型为 function 或 Cfunction,这个函数就被调用. 否则,回退函数 "function" 被调用,第一个参数为 var 的值,之后是原来的调用参数。

形如:
functioncall --> var ‘:‘ name realParams
可被用来调用 "methods"。var:name(...) 调用是 var.name(var, ...) 的语法糖。除了 var 只被求值一次。
realParams --> ‘(‘ [explist1] ‘)‘
realParams --> tableconstructor
explist1 --> exp1 {‘,‘ exp1}
所有参数表达式在函数调用前被求值;然后实参列表被调整到和形参列表一样大小(参见 4.3 节);最后,这个列表被赋值给形参。f{...} 调用是 f({...}) 的语法糖,即,参数列表是一个 新建的 table。

因为一个函数可以返回任意多个值(参见 4.4.3 节),返回值的个数在使用之前必须进行调整。如果一个函数作为语句使用(参见 4.4.4 节),它的返回结果会被调整到 0 个(也就是全部丢弃)。如果一个函数在需要一个值(语法中被表示为非终结的 exp1)的地方调用,它的返回结果会被调整到 1 个。如果一个函数在需要多个值的地方调用(语法上表示为非终结的 exp),不对返回结果进行调整。

-------------------
4.6 函数定义
-------------------
函数可以在模块中的任何全局层面定义;函数定义的语法是:
function --> function var ‘(‘ [parlist1 ] ‘)‘ block end

当 Lua 预编译一个模块,它所有的函数体也被预编译了。然后,当 Lua “执行”函数定义,它的函数体被保存在变量 var,类型为 function。

参数和局部变量的表现一样,由参数值进行初始化。
parlist1 --> ‘name‘ { ‘,‘ name }

结果由 return 语句返回(见 4.4.3节)。如果执行到函数最后也没有 return 指令的话,函数不返回值。

函数定义有一个特殊的语法,即,函数有一个额外的参数 self。
function --> function var ‘:‘ name ‘(‘ [parlist1] ‘)‘ block end
一个声明如下:
function v:f (...)
  ...
end
等同于
function v.f (self, ...)
  ...
end
也就是说,函数额外获得一个名为 self 的的形参。注意变量 v 必须预先被初始化为 table。

-------------------
4.7 回退
-------------------
(Fallbacks 不知道该翻译成什么,回退?预设?陷入?这里统一叫为回退,不过应该叫做预设应该更适当一点吧。知道写做回退的地方指的是 fallback 就行了,早知道就不翻译它,直接用英文更好些。)
Lua 提供一个强大的机制去扩展它的语义,叫做回退 (fallbacks)。基本上,一个回退就是一个程序员定义的函数,当 Lua 不知道如何继续执行时将调用它。
Lua 支持下列回退,由给定的字符串识别:
"arith" 一个算术运算应用于非数值型操作数,或者幂运算 ^ 被调用时。它接受三个参数:两个操作数(如果是单目减运算时第二个为 nil)和一个下列描述出错运算符的字符串之一:
add sub mul div pow unm
它的返回值是算术运算的最终结果。默认函数引发一个错误。
"order" 一个比较运算应用于非数值型或非字符串型操作数的时候。它接受三个参数:两个操作数和一个下列描述出错运算符的字符串之一:
lt gt le ge
它的返回值是比较运算的最终结果。默认函数引发一个错误。
"concat" 一个连接运算应用于非字符串型操作数。它接受两个操作数作为参数。它的返回值是连接运算的最终结果。默认函数引发一个错误。
"index" Lua 试图取得不在 table 中的 index 的值的时候。它接受 table 和 index 作为参数。它的返回值是索引运算的最终结果。默认函数返回 nil。
"getglobal" Lua 试图取得一个值为 nil 的全局变量的时候(或者全局变量还没有初始化的时候)。它接受变量名作为参数。它的返回值是表达式的最终结果。默认函数返回 nil。
"gettable" Lua 试图索引一个非 table 值的时候。它接受非 table 值和索引 index 作为参数。它的返回值是索引操作的最终结果。默认函数引发一个错误。
"settable" Lua 试图给一个非 table 值某个索引赋值的时候。它接受非 table 值,索引 index 和所赋的值作为参数。默认函数引发一个错误。
"function" Lua 试图调用一个非函数值时。它接受非函数值和原来调用的参数做为参数。它的返回值是调用操作的最终结果。默认函数引发一个错误。
"gc" 垃圾回收的时候。它接受将要被垃圾回收的 table 作为参数。垃圾收集器每次调用之后会调用它,参数为 nil。因为这个函数在垃圾回收中运行,使用它时必须小心谨慎,程序员应该避免在其中新建对象(表或者字符串)。默认函数什么也不做。
"error" 一个错误发生的时候。它接受一个描述错误的字符串做为参数。默认函数打印那个出错消息到标准错误输出。
函数 setfallback 被用来改变一个回退动作。它的第一个参数是一个描述 fallback 的字符串,第二个参数是新的回退函数。它返回相应的老的回退函数。
8.6 节展示了一个使用回退的例子。

-------------------
4.8 错误处理
-------------------
由于 Lua 是一个扩展语言,所有的 Lua 动作从 C 代码调用 Lua 库中的一个函数开始。当一个错误在 Lua 编译或执行时发生,一个错误 fallback 函数被调用,然后相应的库中的函数 (lua_dofile, lua_dostring, lua_call, 和 lua_callfunction) 被终止并返回一个错误状态。
错误回退函数的唯一参数是一个描述错误的字符串。标准的 I/O 库为了打印一些像调用堆栈之类的额外信息,使用调试机制(参见 7 节)重定义了这个回退。为了得到一些关于错误的更多的信息,Lua 程序可以包含编译指示选项 $debug。这个编译指示必须独占一行。当一个错误发生在有该编译指示选项时,查错程序可以打印引起出错的调用(和错误)的行。如果需要的话,可以修改错误处理回退程序。参见 4.7 节。
Lua 代码可能通过调用函数 error 生成一个错误。它的可选参数是一个被用做错误消息的字符串。
(未完待续)

时间: 2024-07-29 21:35:14

Lua2.4 参考手册(二)的相关文章

Lua2.4 参考手册(一)

说明:这个文档是 Lua2.4 的 doc 目录里的 refman.ps 文件.原文版权归原作者所有,这篇翻译只是作为学习之用.如果翻译有不当之处,请参考原文.-------------------以下是正文-------------------编程语言 Lua2.4 的参考手册 摘要:Lua 是一个扩展程序语言,被设计用做其它程序的配置语言.本文档描述 Lua 编程语言 2.4 版,以及 Lua 程序和宿主 C 程序交互的 API.它还提供了一些使用这些主要特点的例子. -----------

Ogre参考手册(二)3.1.1-3.1.2 材质、技术、通道

说明 翻译自Ogre 1.81 manual,在不影响理解的情况下做了删减,以减小阅读的时间和翻译的工作量 这么做只是去掉了文字上修饰部分,并没有减少任何原文档中的知识点,可以作为对等的参考手册 另外对一些不易理解的部分做了修改,或通过“附”做了标注 如果你发现了不易理解的部分,可以跟帖回复,我会原文做修改或回复 注:原文编写时间2006年第三季度,已经接近十年 所以里面所说的老显卡都已是古董,先进显卡也已是老显卡 3 脚本 Ogre的很多功能可以通过脚本驱动,以便于设置.脚本都是简单的文本文件

Lua2.4 参考手册(六)

(接上篇)--------------------------------------8 一些例子--------------------------------------本段给出一些显示 Lua 特性的例子.它并不打算覆盖完整的语言,只是显示一有趣的使用. -------------------8.1 数据结构-------------------表是统一的数据结构.它可以实现多种数据类型,像通常的数组,记录,集合,包,和列表.数组不用解释.在 Lua 中,索引通常从 1 开始,但这只是个惯

Lua2.4 参考手册(五)

(接上篇)--------------------------------------7 调试接口--------------------------------------Lua 没有内置的调试功能.而是借助于函数和钩子(hook)提供了一个特殊接口,可以用来构建不同种类的调试器,分析器(profile)和一些其它的需要解释器内部信息的工具.这个接口在 luadebug.h 文件中声明.-------------------7.1 栈和函数信息-------------------获得解释器栈

Lua2.4 参考手册(四)

(接上篇)--------------------------------------6 预定义的函数和库--------------------------------------Lua 的一组预定义函数虽少但功能强大.他们中大多数提供的功能让语言有一定程度的自反性.一些功能不能通过语言的其它部分模拟也不能通过标准的 Lua API 模拟.其它的只是一些有用的有用通用 API 函数接口. 库,在另一方面,提供了一种通过标准 API 实现的有用的程序.因此,它们并非语言必需的部分,并且作为单独的

Lua2.4 参考手册(三)

(接上篇)--------------------------------------5 API--------------------------------------这节主要描述 Lua 的 API, 也就是宿主程序和库交互的一组 C 函数.API 函数可以分为以下几类:1. 执行 Lua 代码:2. 在 Lua 和 C 之间进行值的转化:3. 操作(读写)Lua 对象:4. 调用 Lua 函数:5. 由 Lua 调用的 C 函数:6. Lua 对象的引用. 所有的 API 都在文件 lu

bash参考手册之五(shell变量)续二

EMACS 如果Bash在shell启动时,在环境中发现这个变量的值是 't',则会认为shell在Emacs shell缓冲区中运行,而禁止行编辑. ENV 类似于BASH_ENV,在shell以POSIX模式调用时使用.(见Bash POSIX模式) EUID 当前用户的数字形式的有效用户ID.这个变量是只读的. FCEDIT 内建命令fc带-e选项时的默认编辑器. FIGNORE 冒号分隔的后缀列表,该列表的内容在执行文件名完成时忽略.一个文件名的后缀匹配FIGNORE中的一个元素时,则该

EL表达式参考手册

一.EL简介 1.语法结构     ${expression}2.[]与.运算符     EL 提供.和[]两种运算符来存取数据.    当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要使用 [].例如:        ${user.My-Name}应当改为${user["My-Name"] }    如果要动态取值时,就可以用[]来做,而.无法做到动态取值.例如:        ${sessionScope.user[data]}中data 是一个变量3

Dubbo -- 系统学习 笔记 -- 配置参考手册

配置参考手册 <dubbo:service/> <dubbo:reference/> <dubbo:protocol/> <dubbo:registry/> <dubbo:monitor/> <dubbo:application/> <dubbo:module/> <dubbo:provider/> <dubbo:consumer/> <dubbo:method/> <dubbo: