lua是我工作中的第一语言,因而工作的大部分时间,都在敲着lua代码。虽然它语法是否简单
好学,但它来做工程的人,都不免要抱怨作者的一些设定理念。 据说作者是一个学院派的人(从他的
sample代码中就能看出这点),很少也不会去考虑做工程的人的需求。 因而,留给我们这些使用lua
的人不少痛苦。
<wbr><wbr><wbr>大伙不爽的事情如下:<br><wbr><wbr><wbr>1. 默认的变量声明是全局的, 局部需要 local 关键字。<br><wbr><wbr><wbr>原因: 正常的一段代码, local的变量怎么也比全局的多, 如果反过来, 想python一样,<br><wbr><wbr><wbr>默认是local , global 来定义全局能省下不少要敲的代码量。并且避免不小心敲错一个<br><wbr><wbr><wbr>单词导致多一个global变量,而又无法察觉。<br><br><wbr><wbr><wbr>2. 没有continue....<br><wbr><wbr><wbr><wbr><wbr><wbr>- -,说不好其实也没啥,毕竟绕一下还是能实现,但作为一门成熟的编程语言,应该<br><wbr><wbr><wbr>不至于为了省点语法分析代码而不实现continue吧<br><wbr><wbr><wbr><br><wbr><wbr><wbr>3. hash 和 array不区分<br><wbr><wbr><wbr><wbr><wbr><wbr>这应该说是lua的特点, 只要把table用得正确也不会有太大问题。 但对于初学者<br><wbr><wbr><wbr>每次都必须花时间去了解table.getn之类的语义。 而且在我们项目里,因为很多table<br><wbr><wbr><wbr>不能区分到底是当array还是hash用,每次求table的大小时都必须一项一项去数。而且这<br><wbr><wbr><wbr>似乎还成为了编程的惯例。因而,我的设想是如果table里面能多一项来跟着table元素的<br><wbr><wbr><wbr>个数。将省不少麻烦。<br><br>
说是这样说,但是如果真正去改虚拟机,也是个不少的工作量。而最麻烦的是,如果项目真的使用<br>
自己改虚拟机,那么将会对以后使用第三方库带来很多麻烦。所以这一直只是个想法而没人去尝试。<br><wbr><wbr><wbr><br>
不过既然都想到这点,就不能不了解一下lua虚拟机的词法和语法分析过程。 前阵子花的点时间去<br>
阅读这部分源码。在此大家分享一些笔记。<br><br><wbr><wbr><wbr>lua源文件中与编译相关的主要有四个lopcodes(字节码),llex(词法分析),lparser(语法分析),lcode(目标代码生成).<br>
lopcodes里定义了指令的格式,寄存器和常数的表示等.这里记录下一些用语的细节,方便下文.相信大家都比较熟悉. <wbr><br>
--[[<br>
一个指令由32位的值,对于有三种模式。<br>
iABC,iABx 和 iAsBx, i是6位的操作码,A为8位, BC为9位, Bx 和 sBx为18位。<br>
A参数通常用作为需要赋值的寄存器, sBx一般用于做跳转量。<br><br>
然后是常量与寄存器的索引。lua通常使用255个寄存器,第n个寄存器一般表示为R(n),<br>
而常量从256开始编号。 常量与寄存器一起成为RK值,RK(x)如果x小于256则为R(x)<br>
否则,为K(x-256),即第x-256+1个常量。RK值经常作为指令的参数。<br><br>
pc指下一个指令的位置<br>
--]]<br><br>
----------------------------------------------------------------------------------------------------------------<br>
词法分析<br><br><wbr><wbr><wbr>词法分析过程比较简单,主要的处理函数是int llex(LexState *ls, SemInfo *seminfo)<br>
它接受一个LexState结构,通过其中的buff读取字节,返回一个token和将语义信息填充到SemInfo中(字符串和数值)。<br>
要注意的地方有两个。<br><br><wbr><wbr><wbr>一是保留字的处理。lua在初始化时调用luaX_init,建立起所有保留字的字符串对象(同时让它永远不回收,调用luaS_fix)。<br>
并且设定其reserved值为该保留字的枚举值。因为lua中相同的字符串只有一份,所以在llex中遇到reserved字段非空的<br>
字符串即为保留字,否则为TK_NAME。<br><br><wbr><wbr><wbr>二是多行注释和字符串。即当读取到'--[' 或 '['的时候,要处理长字符串的情况。通过skip_sep 和 read_long_string处理两段‘=’<br>
数量的匹配。<br>
----------------------------------------------------------------------------------------------------------------<br><br>
语法分析<br><wbr><wbr><wbr><br><wbr><wbr><wbr>语法分析是编译过程的重点,其外部接口是Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name)<br>
它从字节流z读取符合, 建议LexState做词法分析, 同时按照语法生成规则展开, 最后调用到lcode里的接口生成各条指令记录到函数体Proto.<br><br><wbr><wbr><wbr>最上层的语法规则都比较容易理解, 如 chunk , statment, block等. 执行根据生成规则一层层打开即可.<br>
需要注意的是以下的内容:<br><br>
----------------------------------------------------------------------------------------------------------------<br>
1.table的构造过程<br><br>
表构造的处理函数是void constructor (LexState *ls, expdesc *t)<br>
它先生存一条OP_NEWTABLE指令, 然后根据语法, 按','(或';')切分每项, 根据格式调用listfield 或者 recfield<br>
recfield 生成的是 记录项, 也就是 x = y 或者 [x] = y 的形式, 它用分别用expr求出key 和 value 表单式值,<br>
然后生成一条OP_SETTABLE指令.<br><br>
这里想说的是数组项的处理方式, 它并没有对每一项产生一个OP_SETTABLE指令, 而是缓存起来再一次性处理的.<br>
其实listfield的只是对之listfield里面仅仅是对value 进行expr调用. 然后记录待处理的项数量+1 (cc->tostore++)<br>
在每次遇到项处理前, 都调用closelistfield, closelistfield 发现当待处理的项达到FPF时(默认50个)<br>
生成一个OP_SETLIST指令, 批量对他们赋值.<br>
OP_SETLIST指令的格式为 OP_SETLIST<br>
意外把 寄存器A中的table批量赋值, 数量为B个, 目标值所指寄存器范围是 [C-1]*FPF+1 ~ [C-1]*FPF+B<br><br>
因而, 以下语句<br>
local a = { 1; 2; 3; [5] = 'a', 4, 5, [7] = 'b', 6, 7, 8}<br><br>
的编译结果将是<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [01] newtable<wbr><wbr> 0<wbr><wbr> 8<wbr><wbr> 2<wbr><wbr><wbr> ; array=8, hash=2<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [02] loadk<wbr><wbr><wbr><wbr><wbr> 1<wbr><wbr> 0<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 1<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [03] loadk<wbr><wbr><wbr><wbr><wbr> 2<wbr><wbr> 1<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 2<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [04] loadk<wbr><wbr><wbr><wbr><wbr> 3<wbr><wbr> 2<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 3<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [05] settable<wbr><wbr> 0<wbr><wbr> 259 260<wbr> ; 5 "a"<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [06] loadk<wbr><wbr><wbr><wbr><wbr> 4<wbr><wbr> 5<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 4<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [07] loadk<wbr><wbr><wbr><wbr><wbr> 5<wbr><wbr> 3<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 5<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [08] settable<wbr><wbr> 0<wbr><wbr> 262 263<wbr> ; 7 "b"<br><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
分享到:
相关推荐
分解词法分析器和语法分析器 添加了更多的语句类型(varstat等) 添加了一个COMMENTS频道 空格进入隐藏频道,而不是简单地跳过 用法 至于其他ANTLRv4语法: antlr4 LuaLexer.g4 LuaParser.g4 铁路图 请在以铁路图...
本书是一本面向Lua程序员和脚本语言...第二部分主要讨论Lua语法和编译器实现,包括词法分析、语法分析、代码优化、代码生成等。第三部分主要讨论Lua辅助API和标准库实现,包括基础库、实用工具库、包和模块、协程等。
Lua源码剖析(二):词法分析、语法分析、代码生成词法分析lua对与每一个文件(chunk)建立一个 LexState 来做词法分析的词法分析根据语法分析的需求
LuaMacro - Lua 的宏预处理器这是一个用于预处理和评估 Lua 代码的库和驱动程序脚本。... 这个实现使用最初由的词法分析器来标记 Lua 源代码,并显式地构建一个预处理过的字符串,然后可以以通常的方
1.3 词法约定...7 1.4 命令行方式.................7 第2章类型和值9 2.1 Nil..............9 2.2 Booleans....9 2.3 Numbers...10 2.4 Strings......10 2.5 Functions.12 2.6 Userdata and Threads.12 第3...
Lua 5.1.x 或 LuaJIT 2.0.x+ LPEG 库 用法 解析 HTML 文档 local htmlParser = require ' lexers/html ' local content = htmlParser. parse ( [[ <!DOCTYPE html> <html> <head> <title>...
LPIL的两个重要部分是词法分析器和解析器。Lexer 位于lexer.lua中,lexer的工作是接受一个字符串并将其转换为令牌表。 Lua中的令牌可以是: 字符串文字,例如“ hi”,“ hey”或-[[hello]] 数值文字,例如25或0xFF...
脚本操作系统简介:语言为简化C语言,自制编译器(词法+语法+ LR分析),IR(基于寄存器),虚拟机,GUI,VFS原理:执行程序时,即时编译代码并执行所生成的二进制指令,按需加载。介绍架构是C / C ++ ,渲染用...
1.3 词法约定 1.4 命令行方式 第2章 类型和值 2.1 Nil 2.2 Booleans 2.3 Numbers 2.4 Strings 2.5 Functions 2.6 Userdata and Threads 第3章 表达式 3.1 算术运算符 3.2 关系运算符 3.3 逻辑运算符 3.4 连接运算符 ...
华 Hua(㕦)是lua编译器的一种类似于的lisp语言。 它利用hy的解析器和宏扩展机制,并... Hua(和lua)具有适当的词法作用域实现。 例如,嵌套的let在hy中被打破,而hua完全支持嵌套的let 。 Lua被广泛地嵌入到主机应用
最新版支持Basic C PHP Lua Python ASM等120种语言的词法解析 代码折叠 添加标签 文本搜索功能一如既往强大 新增2000种宏 现在封装为易语言模块 将模块源码及实例奉出 ">最新的scintilla版本全新封装易语言模块...
正在编写一个接口(语法,识别器/词法分析器,评估器)。 Python 可以通过cffi从Python调用libmarpa C函数(并进行错误检查)。 Sample ,也是json.c的端口,带有基于Python正则表达式的手写词法分析器。 C# ...
介绍通过 HTTP接口用来 查看/添加/删除 Nginx 反向代理的节点原理通过类似于 lex/yacc 的词法和语法分析,解析nginx upstream文本配置,并生成对象通过接口操作对象内的数据,并生成新的upstream文本配置。...
PL / Lua为Lua带来了Lua的强大功能和简便性,包括:内存占用少,语法简单,词法作用域,作为一等值的功能以及用于非抢先线程的协程。 作为一个简单的示例,请考虑以下hello函数: # CREATE FUNCTION hello
记事本2-mod 基于刘凯和其他人的补丁程序的Notepad2的修改版本(分支)... 如果您发现任何错误,或对所实施的词法分析器任何建议(而不是只)随时提供补丁/拉请求。 如果没有补丁或请求请求,则很可能无法修复/实施任
生成的解析器是独立的,可以与常见的GNU Flex生成的词法分析器一起使用,而无需付出更多努力。 生成的解析器已在x86_64和ARM体系结构上成功测试。 PAPAGENO在Python 2.x中实现。 作者和贡献者 亚历山德罗·巴伦吉...