lua语法分析原理介绍
来源:互联网 发布:电煤指标数据代码 编辑:程序博客网 时间:2024/05/24 22:41
lua语法分原理介绍
******目录
一、内部实现
(a)语法分析介绍
(b)简单产生式举例
(c)lua中实现
(d)statement举例
(e)编译成字节码
二、可优化方向
(a)continue实现
(b)预编译宏实现
(c)加密方法
一、内部实现
(a)语法分析介绍
**注---关于语法分析我们仅针对关键词进行概述,这里不做深度解释,如果有兴趣的话可以去研究编译原理
产生式 ---可以解释为语法分析对应表,扫描过得语句如果与产生式相同,就做分析
lookahead ---向前看字符,表示分析器当前被扫描的终结符号,用来与产生式中的符号做匹配
基本规则 -----lookahead和产生式依次做对比,然后按照对比成功的产生式进行编码操作(这里编码成lua的编码指令)
FIRST(a) -----表示可以产生a的所有字符串的第一个字符的集合
(b)简单产生式距离
stmt -> expr;
| if (expr) stmt
| for (optexpr;optexpr;optexpr) stmt
| other
optexpr -> nil
| expr
其中stmt表示语句,expr表示表达式
从上述描述来看stmt语句可以有
四种表现形式,直接表达式,if语句,for语句,other语句(这里是因为不想做过多列举将other设置为终结符)
FIRST(stmt)即为{expr,if,for,other}--这里讲解我们把expr和other当做是终结符,否则集合应该为{if,for} and {FIRST(other)} and {FIRST(expr)}(预测分析法需要保证FIRST集合不相交)
lookahead存储着读入的字符,先与FIRST(stmt)中字符做匹配
以for (;expr;expr) other 为例
1)lookahead初始化为“for”,在FIRST(stmt)中匹配到for
2)则lookahead变为“(”,匹配stmt产生式中“(”
3)lookahead变为“;”,stmt检测到optexpr,optexpr检测到没有匹配,默认为nil
4)lookahead不变仍为“;”,stmt检测到“;”
5)继续匹配推进
…………
(c)lua中实现
所有实现在lparser.h和lparser.c中完成
luaY_parser --------------->函数是所有语法分析的始端其中包含了词法分析状态机LexState
产生式 --------------->分为多个分析函数,在其中处理相应的产生式与lookahead字符对比
对比函数 --------------->基本通过check_match,同时check_condition,checknext,check这些用来处理特殊予以情况使用
lookahead --------------->LexState中存储了Token lookahead,这是一个token类型,具体可以通过LexState去看
基本规则 --------------->运用switch实现,划分成case分别解析处理
FIRST() --------------->这里基本是switch实现的,通过case来保证每个case执行相对应的产生式,进行更进一步的处理
例如根据chunk分解为block再分解为statement……
(d)statement举例
static void statement (LexState *ls) { int line = ls->linenumber; /* may be needed for error messages */ enterlevel(ls); switch (ls->t.token) { case ';': { /* stat -> ';' (empty statement) */ luaX_next(ls); /* skip ';' */ break; } case TK_IF: { /* stat -> ifstat */ ifstat(ls, line); break; } case TK_WHILE: { /* stat -> whilestat */ whilestat(ls, line); break; } case TK_DO: { /* stat -> DO block END */ luaX_next(ls); /* skip DO */ block(ls); check_match(ls, TK_END, TK_DO, line); break; } case TK_FOR: { /* stat -> forstat */ forstat(ls, line); break; } case TK_REPEAT: { /* stat -> repeatstat */ repeatstat(ls, line); break; } case TK_FUNCTION: { /* stat -> funcstat */ funcstat(ls, line); break; } case TK_LOCAL: { /* stat -> localstat */ luaX_next(ls); /* skip LOCAL */ if (testnext(ls, TK_FUNCTION)) /* local function? */ localfunc(ls); else localstat(ls); break; } case TK_DBCOLON: { /* stat -> label */ luaX_next(ls); /* skip double colon */ labelstat(ls, str_checkname(ls), line); break; } case TK_RETURN: { /* stat -> retstat */ luaX_next(ls); /* skip RETURN */ retstat(ls); break; } case TK_BREAK: /* stat -> breakstat */ case TK_GOTO: { /* stat -> 'goto' NAME */ gotostat(ls, luaK_jump(ls->fs)); break; } default: { /* stat -> func | assignment */ exprstat(ls); break; } }
这里就是statement的相关解析方法,根据FIRST字符来处理
(e)编译成字节码
根据语法分析结束后通过lcode.h定义的方法编译成字节码
API统一命名为luaK_
lcode.c中实现了这些方法,可以去参考学习,基本就是将语义翻译成指令集序列
二、可优化方向
(a)continue实现
1)可以通过token增加continue token进行词法分析,这里可以参考lua词法分析部分,此时保留字里面就会出现TK_CONTINUE字样
2)接下来在statement里可以新增case TK_CONTINUE进行针对这一token的分析
3)当前lua没有continue的实现,这一空缺根据我的观察,应当是在funcState里面没有关于循环开始位置的记录,这就导致没办法实现continue,这应该是最主要原因
4)所以我们可以选择在funcState中加入一个参数用来记录起始位置,例如添加一个int spc,专门用来记录开始位置即可
5)这样就可以通过类似于5.2中gotostat()方法,**(实现break指令通过跳转到funcState的jpc(PC待跳转列表),此时只需跳转到spc即可
(b)预编译宏的实现
之前一直认为,lua没有预编译会导致我们编码中会有很多冗余的全局变量,例如全局变量表中的全部信息,其实都可以在便一部分完成预编译,这样就奸商了很多内存开销
因此,tianjiadefine保留字和define的相关产生式,就可以完成相应的实现(但是涉及到exp枚举新增,会比较麻烦)
当然这样实现也只会在一个当前文件里生效,如果需要全局操作,有两个方案
A方案:
将define定义成一个constant类型,即expkind中VK 那么就需要对VK进行扩展,此时链接那边也需要修改,这样的实现就会相对比较麻烦
B方案:
我们直接写脚本,去处理所有define A= 1 部分,这里在makeFile里就可以完成,可以先预处理一遍全部文件,将define处理并记录,然后在后续编译过程总进行替换即可
(c)加密方法
关于加密,语法和此法分析,可以做深层加密解析
例如我们把lua脚本先做预处理加密,那么在加密过后,我们获取到的加密文本在编译过程中,也会解密,所以并不能起到很大的加密作用
如果我们将解密方法处理在lua语法词法编辑器里,那么解密部分就会变成黑盒,不会被破解出来
但是在编译成字节码时,代码还是会暴露出来,所以字节码部分也应当同时加密这样才能有很好的加密效果,但是相对成本也就会更高
- lua语法分析原理介绍
- lua词法语法分析
- lua词法分析原理介绍
- Lua语法分析(4)- 表达式
- 编译原理语法分析LR1
- 编译原理语法分析
- 编译原理之语法分析
- 【编译原理】语法分析
- 编译原理—语法分析
- 编译原理 - 语法分析
- 语法分析(编译原理)
- 编译原理语法分析
- 编译原理:语法分析
- 编译原理(三)语法分析
- 编译原理 实验3 语法分析
- 编译原理学习之语法分析
- 编译原理语法分析(java)
- 【编译原理】语法分析(一)
- 简单的插入排序
- vex使用...mapActions报错解决办法
- 颜色表示以及在processing中的应用
- 笨方法学习Python-习题33: While 循环
- 4.偏头痛杨的常见设计模式入门系列之代理模式篇
- lua语法分析原理介绍
- 数据库基础
- P2P互联网金融平台项目SSM+Redis+Mysql+Bootstrap+JQuery
- PAT——1031. 查验身份证
- 关于使用Intent协议在webview中跳转三方app
- selenium2java通过请求接口获取并向浏览器插入cookies
- 递归和非递归实现二分查找
- Centos查看端口占用情况和开启端口命令
- 在linux下安装MongoDB