lua词法分析原理介绍
来源:互联网 发布:手机必备软件下载 编辑:程序博客网 时间:2024/06/04 19:31
lua词法分析原理介绍
目录
一、内部实现
(a)lua保留字
(b)LexState结构介绍
(c)Token词法但愿
(d)llex:词法分析
(e)关于注释的一些想法
二、可优化方向
(a)continue和其他关键字实现
(b)lua底层编译加密
(c)细节优化
(d)调整保留字顺序加密
一、内部实现
(a)lua保留字
在这里存储了全部的lua保留字,存储在luaX_token里,这里存储的是tokens
static const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while",
"..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
"<number>", "<name>", "<string>"
};
(b)LexState结构介绍
typedef struct LexState { int current; 当前读入的字符(char/int) int linenumber; 输入的行的计数器 int lastline; 上一个行 Token t; 当前对比token Token lookahead; lookahead Token struct FuncState *fs; FuncState 解析器私有值 struct lua_State *L;lua_State虚拟机全局状态机,这里不做深入介绍了 ZIO *z; 这里可以通过lzio.h看出,这里是字符流,通过这里读取输入的字符流 Mbuffer *buff; tokens的流存储器 struct Dyndata *dyd; 5.2新增,还未了解 TString *source; 这里存储的是当前资源的名字 TString *envn; 5.2新增,目前还不太了解 char decpoint; 定界符的值} LexState;
***TString
结构比较复杂,这里可以理解为一个lua自己定制的string类型,较为简便
***Mbuffer
包含{char* buffer,size_t n,size_t buffsize}
buffer应当是字符流的指针
n是字符流的长度(这里的值还是因为底下的luaZ_bufflen定义)
buffsize表示字符流的大小
***FuncState状态机需要为输入的function生成编码,下面会专门做讲解
***Token 源于编译原理 Token词法单元,具体作用会在下文讲解
***lookahead源于编译原理 lookahead 输入中当前被扫描的终结符号通常被成为“向前看”符号,语法分析时会用到
(c)Token词法单元
这个词法单元包含2个参数
int token
SemInfo seminfo
SemInfo是一个union,可能是一个lua_Number,也可能是一个TString 用来存储词义信息
这是编译过程中的最小单元
(d)llex:词法分析
在llex.c文件中,llex方法是获取token的方法,也就是词法分析方法,通过这个方法得到token并且进行存储处理,再进行语法分析
static int llex(LexState *ls,SemInfo *seminfo)
这里会把ls作为状态存储器,然后江源代码加载进来进行分析
其中会有多条switch判断,根据各个case情况进行处理判别,返回token
例如在default case中就做了TK_NAME和相关保留字Token分析处理
Token会在luaX_init中初始化好相对应的TString tsv.extra 这里存储了需要用到的保留字信息
void luaX_init (lua_State *L) { int i; for (i=0; i<NUM_RESERVED; i++) { TString *ts = luaS_new(L, luaX_tokens[i]); luaS_fix(ts); /* reserved words are never collected */ ts->tsv.extra = cast_byte(i+1); }-------->就是在这里存储了保留字信息@!!!!!}
然后在defualt中作如下操作:(这里是5.2代码)
static int llex (LexState *ls, SemInfo *seminfo) { luaZ_resetbuffer(ls->buff); for (;;) { switch (ls->current) { case '\n': case '\r': { /* line breaks */ inclinenumber(ls); break; } case ' ': case '\f': case '\t': case '\v': { /* spaces */ next(ls); break; } ………… default: { if (lislalpha(ls->current)) { /* identifier or reserved word? */ TString *ts;//关于保留字的处理,存储到tsv.extra do { save_and_next(ls); } while (lislalnum(ls->current));这里用来判别词法是否是数字和字母符号 ts = luaX_newstring(ls, luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff)); seminfo->ts = ts; if (isreserved(ts)) /* reserved word? */ return ts->tsv.extra - 1 + FIRST_RESERVED;返回保留字标识符Token else {返回name标识符Token return TK_NAME; } } else { /* single-char tokens (+ - / ...) */ int c = ls->current; next(ls); return c; } } } }}
然后这些token就会存储在Mbuffer *buffer里面供给语法分析器进行语法分析
(e)关于注释的一些想法
在这里可以发现,lua关于注释的处理
我们会发现lua里面关于注释的过程,也会在程序运行时进行处理,如果将lua作为一个语言,那么应当将注释在预编译过程中直接移除
关于lua预编译部分应当有更进一步的研究
二、可优化方向
这里是将外部lua源码编译成lua虚拟机可识别指令的第一步,我们针对这里可以做的优化有很多
(a)continue和其他关键字实现
我们新建一个continue保留字,只需要在这里新增词法分析,那么continue就会成为一个lua中的保留字
然后再根据语法分析中,我们去设置continue语句在上下文中的语法表现,就可以实现continue
这里很明显就是在定义保留字的入口和实现基石
(b)lua底层编译加密
如果在这一层做加密,那么我们可以通过工具将源码进行加密替换,然后在这里实现对应的解密操作
这样解谜操作就相当于是现在了lua底层,用C语言实现了,同时保证lua源码不会暴露出来
这样的加密方式安全度会有所提高,但是实现成本会比较高,同时也要做到字节码的加密才能有效
(c)细节优化
如果lua的编译过程需要在运行时进行,那么这里的操作就会对效率产生一定的影响,最好将编译过程独立完成
可以尝试调整相关lua词法分析步骤,就可以对lua编译过程进行优化处理
最主要的优化应当在链接过程中处理,可能提高效率会比较高
(d)调整保留字顺序加密
- lua词法分析原理介绍
- Lua词法分析总结
- 探秘lua词法分析
- 编译原理 词法分析
- 编译原理词法分析
- 编译原理 词法分析
- 编译原理词法分析
- 编译原理词法分析
- 编译原理词法分析
- 编译原理 词法分析
- 编译原理--词法分析
- 【编译原理】词法分析
- 编译原理-词法分析
- 编译原理词法分析
- 编译原理实验----词法分析
- 编译原理词法分析程序
- 编译原理:PL0词法分析
- 编译原理 之 词法分析
- 前端基础
- 线程与锁的案例分析
- http你不得不知道的那些事(九)-缓存细节
- Unity 遮罩基础应用
- Java
- lua词法分析原理介绍
- IDEA 包导入了,但依然提示找不到
- HDU4612 Warm up (tarjan)
- Saltstack批量安装部署Zabbix代理(附zabbix自动注册详解)
- INSERT 语句与 FOREIGN KEY 约束"XXX"冲突。该冲突发生于数据库"XXX",表"XXX", column 'XXX。
- Devexpress:在GridControl中使用RepositoryItemGridLookUpEdit 进行级联选择
- js的Date类型的变量需要注意之处
- 重定向问题浅析
- 多媒体应用之控制相机