【Lua篇】静态代码扫描分析(三)语法分析

一、语法分析
通过将词法分析获取的Token流按照目标语言的语法进行解析的过程,例如解析函数声明、函数调用、变量声明、各种语句等。
二、Lua语法分析
在写语法分析程序前,先需要了解Lua的语句和语法,然后进行逐个解析。
下面简单列举一下Lua的语句:
1. 函数定义
1 -- 普通的函数声明
2 function demo1()
3 -- <函数体>
4 end
5 -- 类方法
6 function t.demo2(self)
7 -- <函数体>
8 end
9 -- 方法调用中的匿名函数(其实还有很多)
10 some_method_call(arg1, function() <callback> end)
2. 函数调用
1 -- 普通的函数调用
2 print("Hello Lua")
3 -- 模块方法
4 math.random(1,2)
5 -- 类方法
6 obj:set_id(xx)
3. 赋值语句
1 -- 带local局部变量声明赋值
2 local a = 1
3 -- 多变量
4 local a,b,c = 2,3
5 -- 全局的变量
6 g_a = 3
7 -- 赋值可以是函数、函数调用、表等
8 g_c,g_b = {}, function() end
4. 条件分支
1 -- if条件分支
2 if a > 1 then
3 elseif a > 2 then
4 else
5 end
5. for循环
1 -- for循环
2 for i=1,10,2 do
3 end
6. for迭代器
1 -- 迭代包含in pairs 和 in ipairs
2 for k,v in pairs(tb) do
3 end
7. while循环
1 -- while循环,条件可以很复杂
2 while a >1 and b > 1 do
3 end
8. repeat until 循环
1 repeat
2 until a > 1
上面仅仅简单了进行了举例,实际上项目中的写法是千奇百怪的,因此需要确保包含所有的语法规则。在进行语法解析的时候,首先进行代码块的解析,可以把一个文件看作整个代码块,里面包含各种的语句。然后其实是逐语句解析,先取出一个Token,判断这个Token的类型,然后决定更细规则的解析,就像下面代码列举的过程一样。
1. 语法解析的入口,调用block解析。
1 def parse(self):
2 self._TokenNum = self.mTokens
3 block = self.on_block_parse()
4 return block
2. 对block解析的时候,实际是循环调用逐语句解析,直到匹配到语句块结束标记。
1 def on_block_parse(self):
2 token = self.get_token()
3 statements = []
4 while token is not None:
5 # until,else,elseif,end
6 if self.is_end_token(token):
7 self.put_token()
8 break
9 # 语句解析
10 statement = self.on_statement_parse(token)
11 if not statement:
12 break
13 statements.append(statement)
14 token = self.get_token()
15 return Block(statements)
3. 逐语句解析就是获取Token的类型,并调用对应类型的解析方法。
1 def on_statement_parse(self, token):
2 # 函数
3 if token.tokenType == T.FUNCTION:
4 return self.on_function_parse(token)
5 # for .. in .. do .. end
6 elif token.tokenType == T.FOR:
7 return self.on_for_parse(token)
8 # while .. do .. end
9 elif token.tokenType == T.WHILE:
10 return self.on_while_parse(token)
11 # repeat ... until xx
12 elif token.tokenType == T.REPEAT:
13 return self.on_repeat_parse(token)
14 # if .. elseif ... else .. end
15 elif token.tokenType == T.IF:
16 return self.on_if_parse(token)
17 # do ... end
18 elif token.tokenType == T.DO:
19 return self.on_do_parse(token)
20 # local xx
21 elif token.tokenType == T.LOCAL:
22 return self.on_local_parse(token)
23 # return xxx
24 elif token.tokenType == T.RETURN:
25 return self.on_return_parse(token)
26 else:
27 return self.on_expression_parse(token)
4. 列举一下while循环的解析,其中会调用表达式解析while的条件,调用block解析while的语句体,然后检查是否有end。基本上其他的语句也是按照这样的方式进行分析与解析。
1 def on_while_parse(self, token):
2 """ while 循环 """
3 # while <condition> do
4 exp = self.on_expression_parse(self.get_token())
5 if not exp:
6 self.print_syntax_error(token)
7 return None
8 next_token = self.get_token()
9 if next_token.text != 'do':
10 self.print_syntax_error(next_token)
11 return
12 body = self.on_block_parse()
13 next_token = self.get_token()
14 if next_token.text != 'end':
15 self.print_syntax_error(next_token)
16 return None
17 while_statement = LNodeWhile(token.lineno, exp, body)
18 return while_statement
三、总结
通过上面的简单介绍,不知可能上手写一写呢?将所有的语句都解析完成后,接下来就是进行静态代码扫描了。如果是使用C或者C++写的话,完全可以从Lua的源码中提取上面的词法和语法解析内容,而直接进行代码规则扫描检查的编写。
文章来自我的公众号,大家如果有兴趣可以关注,具体扫描关注下图。

【Lua篇】静态代码扫描分析(三)语法分析的更多相关文章
- 【Lua篇】静态代码扫描分析(一)初步介绍
一.静态代码分析 静态代码分析是一种通过检查代码而不是执行程序来发现源代码中错误的手段.通常可以帮助我们发现常见的编码错误,例如: 语法错误 违反制定的标准编码 未定义的变量 安全性问 ...
- 【Lua篇】静态代码扫描分析(四)规则检查
一.前言 通过前面三篇文章已经初步实现了将Lua源代码文件读取解析成语法树,现在就可以通过得到的语法树进行指定规则的代码扫描检查.下图简单列举了一下单个Lua文件内部的语法关系情况(注意并非真正的类图 ...
- 【Lua篇】静态代码扫描分析(二)词法分析
一.词法分析 词法分析(英语:lexical analysis)是计算机科学中将字符序列转换为单词(Token)序列的过程.进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer, ...
- 静态代码扫描工具PMD定制xml的规则(一)操作篇
0.前言 PMD作为开源的静态代码扫描工具有很强的扩展能力,可使用java或xpath定制rule.第一篇从操作上讲解如何定制一个用于扫描xml是否规范的规则.首先我们知道xml格式的文件在java工 ...
- DEVOPS技术实践_05:sonar静态代码扫描
一.SonarQube静态代码扫描平台 1.1 安装 https://www.sonarqube.org/官网 1.2 下载软件包 https://www.sonarqube.org/download ...
- 使用OClint进行iOS项目的静态代码扫描
使用OClint进行iOS项目的静态代码扫描 原文链接:http://blog.yourtion.com/static-code-analysis-ios-using-oclint.html 最近需要 ...
- Lint——Android SDK提供的静态代码扫描工具
Lint和FindBugs一样,都是静态代码扫描工具,区别在于它是Android SDK提供的,会检查Android项目源文件的正确性.安全性.性能.可用性等潜在的bug并优化改进. 下图简单地描述了 ...
- Objective C静态代码扫描和代码质量管理 OClint + SonarQube
OClint是针对C, C++及Objective C代码的静态扫描分析工具,而SonarQube是一个开源的代码质量管理平台.本文将实现将OClint的扫描结果导入到SonarQube中,已实现对O ...
- Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
静态代码块:用staitc声明,jvm加载类时执行,仅执行一次构造代码块:类中直接用{}定义,每一次创建对象时执行.执行顺序优先级:静态块,main(),构造块,构造方法. 构造函数 public H ...
随机推荐
- 源码搭建Zabbix4.0.23LTS监控系统
实验环境 centos 7.5 主机名 IP地址 配置 应用 controlnode 172.16.1.120/24 4核/8G/60G java-1.8.0-openjdk zabbix serve ...
- 非静态的字段、方法或属性“System.Web.UI.Page.ClientScript.get”要求对象引用
解决Response.Write("<script>alert('修改失败,请稍后再试!');</script>");布局错误的问题 在后台CS代码(不是C ...
- Typecho 安装教程 -- Linux
1.下载宝塔面板 1 使用 SSH 连接工具,如堡塔SSH终端连接到您的 Linux 服务器后,挂载磁盘,根据系统执行相应命令开始安装(大约2分钟完成面板安装): 2 Centos安装脚本 yum i ...
- POJ 1556 计算几何 判断线段相交 最短路
题意: 在一个左下角坐标为(0,0),右上角坐标为(10,10)的矩形内,起点为(0,5),终点为(10,5),中间会有许多扇垂直于x轴的门,求从起点到终点在能走的情况下的最短距离. 分析: 既然是求 ...
- 其他:Windows10安装自带的Linux
1.首先我们要打开Windows功能 2.在这里把勾打上 3.然后打开 设置 --- 更新和安全 --- 针对开发人员 --- (选择)开发人员模式 --- 确定启动 就行了 4.打开PowerShe ...
- Spring:在web.xml正确加载spring配置文件的方式
web.xml加载spring配置文件的方式主要依据该配置文件的名称和存放的位置不同来区别,目前主要有两种方式. 1. 如果spring配置文件的名称为applicationContext.xml,并 ...
- C语言:if条件写法
if 语句的判断条件中不是必须要包含关系运算符,它可以是赋值表达式,甚至也可以是一个变量,常量 例如: //情况① if(b){ //TODO: } //情况② if(b=5){ //情况① //TO ...
- C语言:标识符 关键字 保留字 表达式 语句
标识符(Identifier)标识符就是程序员自己起的名字,符号常量(宏).变量名.函数名.宏名.结构体名等,它们都是标识符.遵守规范:C语言规定,标识符只能由字母(A~Z, a~z).数字(0~9) ...
- printf函数返回值
//返回值:正确返回输出的字符总数,错误返回负值,与此同时,输入输出流错误标志将被置值,可由指示器ferror来检查输入输出流的错误标志. #include <stdio.h> #defi ...
- 【redis前传】redis整数集为什么不能降级
前言 整数集合相信有的同学没有听说过,因为redis对外提供的只有封装的五大对象!而我们本系列主旨是学习redis内部结构.内部结构是redis五大结构重要支撑! 前面我们分别从redis内部结构分析 ...