Skip to content

0x0314 Lua

KaiserKatze edited this page Jan 3, 2019 · 5 revisions

Lua

Lua(发音为 /ˈluːə/ 意指月亮)是一款轻量级(lightweight)多范式(multi-paradigm)的编程语言。其解释器是用 ANSI C 写成,这意味着它可以跨平台使用。

搭建运行环境

sudo apt install libreadline-dev

curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz
tar zxf lua-5.3.0.tar.gz
cd lua-5.3.0

make linux test
sudo make install

语法

AST

chunk ::= block

block ::= {stat} [retstat]

stat ::=  ‘;’ | 
     varlist ‘=’ explist | 
     functioncall | 
     label | 
     break | 
     goto Name | 
     do block end | 
     while exp do block end | 
     repeat block until exp | 
     if exp then block {elseif exp then block} [else block] end | 
     for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | 
     for namelist in explist do block end | 
     function funcname funcbody | 
     local function Name funcbody | 
     local namelist [‘=’ explist] 

retstat ::= return [explist] [‘;’]

label ::= ‘::’ Name ‘::’

funcname ::= Name {‘.’ Name} [‘:’ Name]

varlist ::= var {‘,’ var}

var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name 

namelist ::= Name {‘,’ Name}

explist ::= exp {‘,’ exp}

exp ::=  nil | false | true | Numeral | LiteralString | ‘...’ | functiondef | 
     prefixexp | tableconstructor | exp binop exp | unop exp 

prefixexp ::= var | functioncall | ‘(’ exp ‘)’

functioncall ::=  prefixexp args | prefixexp ‘:’ Name args 

args ::=  ‘(’ [explist] ‘)’ | tableconstructor | LiteralString 

functiondef ::= function funcbody

funcbody ::= ‘(’ [parlist] ‘)’ block end

parlist ::= namelist [‘,’ ‘...’] | ‘...’

tableconstructor ::= ‘{’ [fieldlist] ‘}’

fieldlist ::= field {fieldsep field} [fieldsep]

field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp

fieldsep ::= ‘,’ | ‘;’

binop ::=  ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘//’ | ‘^’ | ‘%’ | 
     ‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ | 
     ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | 
     and | or

unop ::= ‘-’ | not | ‘#’ | ‘~’

标识符(Identifiers)

Lua 中的标识符,可以是任何以字母或下划线开始,由字母([a-zA-Z])、数字([0-9])或下划线([_])构成的字符串。 Lua 对大小写敏感,也就是说 Lua 跟 LUA 是不同的两个标识符。

关键字(Key words)

Lua提供了共计21个关键字,即:

and	break	do	else	elseif
end	false	for	function	if
in	local	nil	not	or
repeat	return	then	true	until	while

由于 Lua 是对大小写敏感的语言:
尽管 and 是保留字,但 And 和 AND 却是两个不同且合法的标识符。

按照惯例,以下划线开头的标识符保留为 Lua 内部变量。

其他符号:

+         -         *         /         ^         =
~=        <=        >=        <         >         ==
(         )         {         }         [         ]
;         :         ,         .         ..        ...

字符串

字符串(Literal string)可以通过匹配单引号或者双引号进行界定,并且可以包括下列类C转义序列(escape sequence):

另外,换行还可以用转义符'\newline'表示;字符可以以 '\d'、'\dd' 或 '\ddd'(其中字母 d 表示十进制数字,decimal digit)的形式,用其对应数值表示;Lua 字符串可以包含任何 8 位字符,包括 '\0'。 Lua 字符串还可以用一对形如 ... 的双方括号界定,如此可以跨行定义字符串,并且可以嵌套。

数字常数

Lua 的数字常数与 C 语言类似,以下是一些示例:

3	3.0	3.1416	314.16e-2	0.31416E1

注释

Lua 的注释以两个连续的连接符,即 -- 开头

类型

Lua 是一种动态类型语言。这就意味着变量没有类型,而只有值才具有类型。 Lua 中有 8 种基本类型: nil, boolean, number, string, function, userdata, threadtable。 其中 number双精度浮点数string8 bit 字符串

赋值(Assignment)

Lua,正如 JavaScript 一样,是一种类型松散(loose typing)的脚本语言; 换言之,与 C/C++ 和 Java 等强类型定义语言中要求声明(declare)变量时必须选择变量的类型不同,
Lua赋值时只需要变量名和变量值:

my_var = "hello"

操作符优先级

or
and
<     >     <=    >=    ~=    ==
|
~
&
<<    >>
..
+     -
*     /     //    %
unary operators (not   #     -     ~)
^

表(Table)

Lua的设计者在其语法中引入了表的概念,用以表示中的数组(Array)和图(Map)两种数据结构。

创建一个表

你可以创建一个以字符串为键(Key)的表,即:

my_map = { apple = 5, banana = 10, melon = 9 }

或者一个类似数组的表,即:

my_array = { "Tom", "Jack", "Peter" }

修改表中的数据

如果你的表是以字符串为键的,那么你可以:

my_map.apple = 15

或者

my_map["apple"] = 17

如果你的表示以数字为键的,那么你可以:

my_array[1] = "Tompson"

请注意,Lua 中以数字为键的表跟 C/C++ 中数组不同,也就是 my_array[0] 的值是 nil

表的遍历

以字符串为键的表通过以下语法进行遍历:

for k, v in pairs(my_map) do

而以数字为键的表则是:

for i, v in ipairs(my_array) do

控制结构与循环

选择(if 语句)

if 语句遵守以下句法:

stat ::= if exp then block {elseif exp then block} [else block] end

实例:

if exp then
    -- block
elseif exp then
    -- block
else
    -- block
end
短路求值(Minimal evaluation)

由于 Lua 内核是基于 C 语言编写的,支持短路求值自然不足为奇。

所谓短路求值,即在以下Lua代码

if condition_A and condition_B and condition_C then

中,首先计算 condition_A 的真值,若 condition_A 为假(false),则跳出; 否则依次计算下一个布尔表达式的真值,直到出现假或者全部表达式都计算完毕为止。

当型循环(while 循环)

while 语句遵守以下句法:

stat ::= while exp do block end

实例:

while exp do
    -- block
end

直到型循环(repeat-until 循环)

repeat-until 语句遵守以下句法:

stat ::= repeat block until exp

实例:

repeat
    -- block
until exp

从循环中跳出

使用 return 可从控制结构或者循环中跳出。return 语句遵守以下句法:

stat ::= return [explist] [‘;’]

使用 break 可从循环中跳出。break 语句遵守以下句法:

stat ::= break

使用 goto 也可以从控制结构或者循环中跳出。goto 语句遵守以下句法:

stat ::= goto Name
stat ::= label
label ::= ‘::’ Name ‘::’

for 循环

for 语句遵守以下句法:

stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end

或以下句法:

stat ::= for namelist in explist do block end
namelist ::= Name {‘,’ Name}

实例:

for i = first, last, delta do
  -- block
end

函数

Clone this wiki locally